Update copyright header. Normalize line endings to LF.

This commit is contained in:
Paul Chote
2011-02-13 10:38:57 +13:00
parent ea5e2c0588
commit 094907c1a9
489 changed files with 43614 additions and 43613 deletions

View File

@@ -1,81 +1,81 @@
#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 OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
/* non-turreted attack */
public class Attack : CancelableActivity
{
protected Target Target;
ITargetable targetable;
int Range;
bool AllowMovement;
int nextPathTime;
const int delayBetweenPathingAttempts = 20;
const int delaySpread = 5;
public Attack(Target target, int range, bool allowMovement)
{
Target = target;
if (target.IsActor)
targetable = target.Actor.TraitOrDefault<ITargetable>();
Range = range;
AllowMovement = allowMovement;
}
public Attack(Target target, int range) : this(target, range, true) {}
public override IActivity Tick( Actor self )
{
var attack = self.Trait<AttackBase>();
var ret = InnerTick( self, attack );
attack.IsAttacking = ( ret == this );
return ret;
}
protected virtual IActivity InnerTick( Actor self, AttackBase attack )
{
if (IsCanceled) return NextActivity;
var facing = self.Trait<IFacing>();
if (!Target.IsValid)
return NextActivity;
if (targetable != null && !targetable.TargetableBy(Target.Actor, self))
return NextActivity;
if (!Combat.IsInRange(self.CenterLocation, Range, Target))
{
if (--nextPathTime > 0)
return this;
nextPathTime = self.World.SharedRandom.Next(delayBetweenPathingAttempts - delaySpread,
delayBetweenPathingAttempts + delaySpread);
return (AllowMovement) ? Util.SequenceActivities(self.Trait<Mobile>().MoveWithinRange(Target, Range), this) : NextActivity;
}
var desiredFacing = Util.GetFacing(Target.CenterLocation - self.CenterLocation, 0);
if (facing.Facing != desiredFacing)
return Util.SequenceActivities( new Turn( desiredFacing ), this );
attack.DoAttack(self, Target);
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
/* non-turreted attack */
public class Attack : CancelableActivity
{
protected Target Target;
ITargetable targetable;
int Range;
bool AllowMovement;
int nextPathTime;
const int delayBetweenPathingAttempts = 20;
const int delaySpread = 5;
public Attack(Target target, int range, bool allowMovement)
{
Target = target;
if (target.IsActor)
targetable = target.Actor.TraitOrDefault<ITargetable>();
Range = range;
AllowMovement = allowMovement;
}
public Attack(Target target, int range) : this(target, range, true) {}
public override IActivity Tick( Actor self )
{
var attack = self.Trait<AttackBase>();
var ret = InnerTick( self, attack );
attack.IsAttacking = ( ret == this );
return ret;
}
protected virtual IActivity InnerTick( Actor self, AttackBase attack )
{
if (IsCanceled) return NextActivity;
var facing = self.Trait<IFacing>();
if (!Target.IsValid)
return NextActivity;
if (targetable != null && !targetable.TargetableBy(Target.Actor, self))
return NextActivity;
if (!Combat.IsInRange(self.CenterLocation, Range, Target))
{
if (--nextPathTime > 0)
return this;
nextPathTime = self.World.SharedRandom.Next(delayBetweenPathingAttempts - delaySpread,
delayBetweenPathingAttempts + delaySpread);
return (AllowMovement) ? Util.SequenceActivities(self.Trait<Mobile>().MoveWithinRange(Target, Range), this) : NextActivity;
}
var desiredFacing = Util.GetFacing(Target.CenterLocation - self.CenterLocation, 0);
if (facing.Facing != desiredFacing)
return Util.SequenceActivities( new Turn( desiredFacing ), this );
attack.DoAttack(self, Target);
return this;
}
}
}

View File

@@ -1,58 +1,58 @@
#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 System.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Activities
{
public class CallFunc : IActivity
{
public CallFunc(Action a) { this.a = a; }
public CallFunc(Action a, bool interruptable)
{
this.a = a;
this.interruptable = interruptable;
}
Action a;
bool interruptable;
IActivity NextActivity { get; set; }
public IActivity Tick(Actor self)
{
if (a != null) a();
return NextActivity;
}
public void Cancel(Actor self)
{
if (!interruptable)
return;
a = null;
NextActivity = null;
}
public void Queue( IActivity activity )
{
if( NextActivity != null )
NextActivity.Queue( activity );
else
NextActivity = activity;
}
public IEnumerable<float2> GetCurrentPath()
{
yield break;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Activities
{
public class CallFunc : IActivity
{
public CallFunc(Action a) { this.a = a; }
public CallFunc(Action a, bool interruptable)
{
this.a = a;
this.interruptable = interruptable;
}
Action a;
bool interruptable;
IActivity NextActivity { get; set; }
public IActivity Tick(Actor self)
{
if (a != null) a();
return NextActivity;
}
public void Cancel(Actor self)
{
if (!interruptable)
return;
a = null;
NextActivity = null;
}
public void Queue( IActivity activity )
{
if( NextActivity != null )
NextActivity.Queue( activity );
else
NextActivity = activity;
}
public IEnumerable<float2> GetCurrentPath()
{
yield break;
}
}
}

View File

@@ -1,52 +1,52 @@
#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.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
class CaptureBuilding : CancelableActivity
{
Actor target;
public CaptureBuilding(Actor target) { this.target = target; }
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
if (target.Owner == self.Owner) return NextActivity;
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
return NextActivity;
// todo: clean this up
self.World.AddFrameEndTask(w =>
{
// momentarily remove from world so the ownership queries don't get confused
var oldOwner = target.Owner;
w.Remove(target);
target.Owner = self.Owner;
w.Add(target);
foreach (var t in target.TraitsImplementing<INotifyCapture>())
t.OnCapture(target, self, oldOwner, self.Owner);
foreach (var t in self.World.Queries.WithTrait<INotifyOtherCaptured>())
t.Trait.OnActorCaptured(t.Actor, target, self, oldOwner, self.Owner);
self.Destroy();
});
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
class CaptureBuilding : CancelableActivity
{
Actor target;
public CaptureBuilding(Actor target) { this.target = target; }
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
if (target.Owner == self.Owner) return NextActivity;
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
return NextActivity;
// todo: clean this up
self.World.AddFrameEndTask(w =>
{
// momentarily remove from world so the ownership queries don't get confused
var oldOwner = target.Owner;
w.Remove(target);
target.Owner = self.Owner;
w.Add(target);
foreach (var t in target.TraitsImplementing<INotifyCapture>())
t.OnCapture(target, self, oldOwner, self.Owner);
foreach (var t in self.World.Queries.WithTrait<INotifyOtherCaptured>())
t.Trait.OnActorCaptured(t.Actor, target, self, oldOwner, self.Owner);
self.Destroy();
});
return this;
}
}
}

View File

@@ -1,72 +1,72 @@
#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.Collections.Generic;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
public class DeliverResources : IActivity
{
IActivity NextActivity { get; set; }
bool isDocking;
public DeliverResources() { }
public IActivity Tick( Actor self )
{
if( NextActivity != null )
return NextActivity;
var mobile = self.Trait<Mobile>();
var harv = self.Trait<Harvester>();
if (harv.LinkedProc == null || !harv.LinkedProc.IsInWorld)
harv.ChooseNewProc(self, null);
if (harv.LinkedProc == null) // no procs exist; check again in 1s.
return Util.SequenceActivities( new Wait(25), this );
var proc = harv.LinkedProc;
if( self.Location != proc.Location + proc.Trait<IAcceptOre>().DeliverOffset )
{
return Util.SequenceActivities( mobile.MoveTo(proc.Location + proc.Trait<IAcceptOre>().DeliverOffset, 0), this );
}
else if (!isDocking)
{
isDocking = true;
proc.Trait<IAcceptOre>().OnDock(self, this);
}
return Util.SequenceActivities( new Wait(10), this );
}
public void Cancel(Actor self)
{
// TODO: allow canceling of deliver orders?
}
public void Queue( IActivity activity )
{
if( NextActivity != null )
NextActivity.Queue( activity );
else
NextActivity = activity;
}
public IEnumerable<float2> GetCurrentPath()
{
yield break;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
public class DeliverResources : IActivity
{
IActivity NextActivity { get; set; }
bool isDocking;
public DeliverResources() { }
public IActivity Tick( Actor self )
{
if( NextActivity != null )
return NextActivity;
var mobile = self.Trait<Mobile>();
var harv = self.Trait<Harvester>();
if (harv.LinkedProc == null || !harv.LinkedProc.IsInWorld)
harv.ChooseNewProc(self, null);
if (harv.LinkedProc == null) // no procs exist; check again in 1s.
return Util.SequenceActivities( new Wait(25), this );
var proc = harv.LinkedProc;
if( self.Location != proc.Location + proc.Trait<IAcceptOre>().DeliverOffset )
{
return Util.SequenceActivities( mobile.MoveTo(proc.Location + proc.Trait<IAcceptOre>().DeliverOffset, 0), this );
}
else if (!isDocking)
{
isDocking = true;
proc.Trait<IAcceptOre>().OnDock(self, this);
}
return Util.SequenceActivities( new Wait(10), this );
}
public void Cancel(Actor self)
{
// TODO: allow canceling of deliver orders?
}
public void Queue( IActivity activity )
{
if( NextActivity != null )
NextActivity.Queue( activity );
else
NextActivity = activity;
}
public IEnumerable<float2> GetCurrentPath()
{
yield break;
}
}
}

View File

@@ -1,37 +1,37 @@
#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.Linq;
using OpenRA.Effects;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
class Demolish : CancelableActivity
{
Actor target;
public Demolish( Actor target ) { this.target = target; }
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
return NextActivity;
self.World.AddFrameEndTask(w => w.Add(new DelayedAction(25 * 2,
() => { if (target.IsInWorld) target.Kill(self); })));
return NextActivity;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Effects;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
class Demolish : CancelableActivity
{
Actor target;
public Demolish( Actor target ) { this.target = target; }
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
return NextActivity;
self.World.AddFrameEndTask(w => w.Add(new DelayedAction(25 * 2,
() => { if (target.IsInWorld) target.Kill(self); })));
return NextActivity;
}
}
}

View File

@@ -1,38 +1,38 @@
#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 System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
public class Enter : CancelableActivity
{
readonly Actor target;
public Enter( Actor target ) { this.target = target; }
public override IActivity Tick( Actor self )
{
if( IsCanceled || target.Destroyed || !target.IsInWorld )
return NextActivity;
var mobile = self.Trait<Mobile>();
var nearest = target.Trait<IOccupySpace>().NearestCellTo( mobile.toCell );
if( ( nearest - mobile.toCell ).LengthSquared > 2 )
return Util.SequenceActivities( new MoveAdjacentTo( target ), this );
return Util.SequenceActivities( mobile.MoveTo( nearest, target ), NextActivity );
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
public class Enter : CancelableActivity
{
readonly Actor target;
public Enter( Actor target ) { this.target = target; }
public override IActivity Tick( Actor self )
{
if( IsCanceled || target.Destroyed || !target.IsInWorld )
return NextActivity;
var mobile = self.Trait<Mobile>();
var nearest = target.Trait<IOccupySpace>().NearestCellTo( mobile.toCell );
if( ( nearest - mobile.toCell ).LengthSquared > 2 )
return Util.SequenceActivities( new MoveAdjacentTo( target ), this );
return Util.SequenceActivities( mobile.MoveTo( nearest, target ), NextActivity );
}
}
}

View File

@@ -1,46 +1,46 @@
#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 OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
class EnterTransport : CancelableActivity
{
public Actor transport;
public EnterTransport(Actor self, Actor transport)
{
this.transport = transport;
}
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (transport == null || !transport.IsInWorld) return NextActivity;
var cargo = transport.Trait<Cargo>();
if (cargo.IsFull(transport))
return NextActivity;
// Todo: Queue a move order to the transport? need to be
// careful about units that can't path to the transport
if ((transport.Location - self.Location).Length > 1)
return NextActivity;
cargo.Load(transport, self);
self.World.AddFrameEndTask(w => w.Remove(self));
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
class EnterTransport : CancelableActivity
{
public Actor transport;
public EnterTransport(Actor self, Actor transport)
{
this.transport = transport;
}
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (transport == null || !transport.IsInWorld) return NextActivity;
var cargo = transport.Trait<Cargo>();
if (cargo.IsFull(transport))
return NextActivity;
// Todo: Queue a move order to the transport? need to be
// careful about units that can't path to the transport
if ((transport.Location - self.Location).Length > 1)
return NextActivity;
cargo.Load(transport, self);
self.World.AddFrameEndTask(w => w.Remove(self));
return this;
}
}
}

View File

@@ -1,49 +1,49 @@
#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 OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
public class Follow : CancelableActivity
{
Target Target;
int Range;
int nextPathTime;
const int delayBetweenPathingAttempts = 20;
const int delaySpread = 5;
public Follow(Target target, int range)
{
Target = target;
Range = range;
}
public override IActivity Tick( Actor self )
{
if (IsCanceled) return NextActivity;
if (!Target.IsValid) return NextActivity;
var inRange = ( Util.CellContaining( Target.CenterLocation ) - self.Location ).LengthSquared < Range * Range;
if( inRange ) return this;
if (--nextPathTime > 0) return this;
nextPathTime = self.World.SharedRandom.Next(delayBetweenPathingAttempts - delaySpread,
delayBetweenPathingAttempts + delaySpread);
var mobile = self.Trait<Mobile>();
return Util.SequenceActivities( mobile.MoveWithinRange( Target, Range ), this );
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
public class Follow : CancelableActivity
{
Target Target;
int Range;
int nextPathTime;
const int delayBetweenPathingAttempts = 20;
const int delaySpread = 5;
public Follow(Target target, int range)
{
Target = target;
Range = range;
}
public override IActivity Tick( Actor self )
{
if (IsCanceled) return NextActivity;
if (!Target.IsValid) return NextActivity;
var inRange = ( Util.CellContaining( Target.CenterLocation ) - self.Location ).LengthSquared < Range * Range;
if( inRange ) return this;
if (--nextPathTime > 0) return this;
nextPathTime = self.World.SharedRandom.Next(delayBetweenPathingAttempts - delaySpread,
delayBetweenPathingAttempts + delaySpread);
var mobile = self.Trait<Mobile>();
return Util.SequenceActivities( mobile.MoveWithinRange( Target, Range ), this );
}
}
}

View File

@@ -1,78 +1,78 @@
#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.Linq;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
public class Harvest : CancelableActivity
{
bool isHarvesting = false;
public override IActivity Tick( Actor self )
{
if( isHarvesting ) return this;
if( IsCanceled ) return NextActivity;
if( NextActivity != null ) return NextActivity;
var harv = self.Trait<Harvester>();
harv.LastHarvestedCell = self.Location;
if( harv.IsFull )
return Util.SequenceActivities( new DeliverResources(), NextActivity );
if (HarvestThisTile(self))
return this;
else
{
FindMoreResource(self);
return NextActivity;
}
}
bool HarvestThisTile(Actor self)
{
var harv = self.Trait<Harvester>();
var renderUnit = self.Trait<RenderUnit>(); /* better have one of these! */
var resource = self.World.WorldActor.Trait<ResourceLayer>().Harvest(self.Location);
if (resource == null)
return false;
if (renderUnit.anim.CurrentSequence.Name != "harvest")
{
isHarvesting = true;
renderUnit.PlayCustomAnimation(self, "harvest", () => isHarvesting = false);
}
harv.AcceptResource(resource);
return true;
}
void FindMoreResource(Actor self)
{
var mobile = self.Trait<Mobile>();
var res = self.World.WorldActor.Trait<ResourceLayer>();
var harv = self.Info.Traits.Get<HarvesterInfo>();
var mobileInfo = self.Info.Traits.Get<MobileInfo>();
self.QueueActivity(mobile.MoveTo(
() =>
{
return self.World.WorldActor.Trait<PathFinder>().FindPath(PathSearch.Search(self.World, mobileInfo, true)
.WithHeuristic(loc => (res.GetResource(loc) != null && harv.Resources.Contains( res.GetResource(loc).info.Name )) ? 0 : 1)
.FromPoint(self.Location));
}));
self.QueueActivity(new Harvest());
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
public class Harvest : CancelableActivity
{
bool isHarvesting = false;
public override IActivity Tick( Actor self )
{
if( isHarvesting ) return this;
if( IsCanceled ) return NextActivity;
if( NextActivity != null ) return NextActivity;
var harv = self.Trait<Harvester>();
harv.LastHarvestedCell = self.Location;
if( harv.IsFull )
return Util.SequenceActivities( new DeliverResources(), NextActivity );
if (HarvestThisTile(self))
return this;
else
{
FindMoreResource(self);
return NextActivity;
}
}
bool HarvestThisTile(Actor self)
{
var harv = self.Trait<Harvester>();
var renderUnit = self.Trait<RenderUnit>(); /* better have one of these! */
var resource = self.World.WorldActor.Trait<ResourceLayer>().Harvest(self.Location);
if (resource == null)
return false;
if (renderUnit.anim.CurrentSequence.Name != "harvest")
{
isHarvesting = true;
renderUnit.PlayCustomAnimation(self, "harvest", () => isHarvesting = false);
}
harv.AcceptResource(resource);
return true;
}
void FindMoreResource(Actor self)
{
var mobile = self.Trait<Mobile>();
var res = self.World.WorldActor.Trait<ResourceLayer>();
var harv = self.Info.Traits.Get<HarvesterInfo>();
var mobileInfo = self.Info.Traits.Get<MobileInfo>();
self.QueueActivity(mobile.MoveTo(
() =>
{
return self.World.WorldActor.Trait<PathFinder>().FindPath(PathSearch.Search(self.World, mobileInfo, true)
.WithHeuristic(loc => (res.GetResource(loc) != null && harv.Resources.Contains( res.GetResource(loc).info.Name )) ? 0 : 1)
.FromPoint(self.Location));
}));
self.QueueActivity(new Harvest());
}
}
}

View File

@@ -1,32 +1,32 @@
#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 OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
/* non-turreted attack */
public class Heal : Attack
{
public Heal(Target target, int range, bool allowMovement)
: base(target, range, allowMovement) {}
protected override IActivity InnerTick( Actor self, AttackBase attack )
{
if (Target.IsActor && Target.Actor.GetDamageState() == DamageState.Undamaged)
return NextActivity;
return base.InnerTick(self, attack);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
/* non-turreted attack */
public class Heal : Attack
{
public Heal(Target target, int range, bool allowMovement)
: base(target, range, allowMovement) {}
protected override IActivity InnerTick( Actor self, AttackBase attack )
{
if (Target.IsActor && Target.Actor.GetDamageState() == DamageState.Undamaged)
return NextActivity;
return base.InnerTick(self, attack);
}
}
}

View File

@@ -1,39 +1,39 @@
#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.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
class Infiltrate : CancelableActivity
{
Actor target;
public Infiltrate(Actor target) { this.target = target; }
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
if (target.Owner == self.Owner) return NextActivity;
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
return NextActivity;
foreach (var t in target.TraitsImplementing<IAcceptSpy>())
t.OnInfiltrate(target, self);
self.Destroy();
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
class Infiltrate : CancelableActivity
{
Actor target;
public Infiltrate(Actor target) { this.target = target; }
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
if (target.Owner == self.Owner) return NextActivity;
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
return NextActivity;
foreach (var t in target.TraitsImplementing<IAcceptSpy>())
t.OnInfiltrate(target, self);
self.Destroy();
return this;
}
}
}

View File

@@ -1,87 +1,87 @@
#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.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
// assumes you have Minelayer on that unit
class LayMines : CancelableActivity
{
public override IActivity Tick( Actor self )
{
if (IsCanceled) return NextActivity;
var mobile = self.Trait<Mobile>();
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if (!limitedAmmo.HasAmmo())
{
// rearm & repair at fix, then back out here to refill the minefield some more
var buildings = self.Info.Traits.Get<MinelayerInfo>().RearmBuildings;
var rearmTarget = self.World.Actors.FirstOrDefault(a => a.Owner != null && self.Owner.Stances[a.Owner] == Stance.Ally
&& buildings.Contains(a.Info.Name));
if (rearmTarget == null)
return new Wait(20);
return Util.SequenceActivities(
new Enter(rearmTarget),
//new Move(Util.CellContaining(rearmTarget.CenterLocation), rearmTarget),
new Rearm(),
new Repair(rearmTarget),
this );
}
var ml = self.Trait<Minelayer>();
if (ml.minefield.Contains(self.Location) &&
ShouldLayMine(self, self.Location))
{
LayMine(self);
return Util.SequenceActivities( new Wait(20), this ); // a little wait after placing each mine, for show
}
for (var n = 0; n < 20; n++) // dont get stuck forever here
{
var p = ml.minefield.Random(self.World.SharedRandom);
if (ShouldLayMine(self, p))
return Util.SequenceActivities( mobile.MoveTo(p, 0), this );
}
// todo: return somewhere likely to be safe (near fix) so we're not sitting out in the minefield.
return new Wait(20); // nothing to do here
}
bool ShouldLayMine(Actor self, int2 p)
{
// if there is no unit (other than me) here, we want to place a mine here
return !self.World.WorldActor.Trait<UnitInfluence>()
.GetUnitsAt(p).Any(a => a != self);
}
void LayMine(Actor self)
{
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if (limitedAmmo != null) limitedAmmo.Attacking(self, Target.FromCell(self.Location));
self.World.AddFrameEndTask(
w => w.CreateActor(self.Info.Traits.Get<MinelayerInfo>().Mine, new TypeDictionary
{
new LocationInit( self.Location ),
new OwnerInit( self.Owner ),
}));
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
// assumes you have Minelayer on that unit
class LayMines : CancelableActivity
{
public override IActivity Tick( Actor self )
{
if (IsCanceled) return NextActivity;
var mobile = self.Trait<Mobile>();
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if (!limitedAmmo.HasAmmo())
{
// rearm & repair at fix, then back out here to refill the minefield some more
var buildings = self.Info.Traits.Get<MinelayerInfo>().RearmBuildings;
var rearmTarget = self.World.Actors.FirstOrDefault(a => a.Owner != null && self.Owner.Stances[a.Owner] == Stance.Ally
&& buildings.Contains(a.Info.Name));
if (rearmTarget == null)
return new Wait(20);
return Util.SequenceActivities(
new Enter(rearmTarget),
//new Move(Util.CellContaining(rearmTarget.CenterLocation), rearmTarget),
new Rearm(),
new Repair(rearmTarget),
this );
}
var ml = self.Trait<Minelayer>();
if (ml.minefield.Contains(self.Location) &&
ShouldLayMine(self, self.Location))
{
LayMine(self);
return Util.SequenceActivities( new Wait(20), this ); // a little wait after placing each mine, for show
}
for (var n = 0; n < 20; n++) // dont get stuck forever here
{
var p = ml.minefield.Random(self.World.SharedRandom);
if (ShouldLayMine(self, p))
return Util.SequenceActivities( mobile.MoveTo(p, 0), this );
}
// todo: return somewhere likely to be safe (near fix) so we're not sitting out in the minefield.
return new Wait(20); // nothing to do here
}
bool ShouldLayMine(Actor self, int2 p)
{
// if there is no unit (other than me) here, we want to place a mine here
return !self.World.WorldActor.Trait<UnitInfluence>()
.GetUnitsAt(p).Any(a => a != self);
}
void LayMine(Actor self)
{
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if (limitedAmmo != null) limitedAmmo.Attacking(self, Target.FromCell(self.Location));
self.World.AddFrameEndTask(
w => w.CreateActor(self.Info.Traits.Get<MinelayerInfo>().Mine, new TypeDictionary
{
new LocationInit( self.Location ),
new OwnerInit( self.Owner ),
}));
}
}
}

View File

@@ -1,61 +1,61 @@
#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.Linq;
using OpenRA.Mods.RA.Render;
using OpenRA.Mods.RA.Move;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
class Leap : CancelableActivity
{
Target target;
int2 initialLocation;
int moveFraction;
const int delay = 6;
public Leap(Actor self, Target target)
{
this.target = target;
initialLocation = self.Trait<Mobile>().PxPosition;
self.Trait<RenderInfantry>().Attacking(self, target);
Sound.Play("dogg5p.aud", self.CenterLocation);
}
public override IActivity Tick(Actor self)
{
if( moveFraction == 0 && IsCanceled ) return NextActivity;
if (!target.IsValid) return NextActivity;
self.Trait<AttackLeap>().IsLeaping = true;
var mobile = self.Trait<Mobile>();
++moveFraction;
mobile.PxPosition = int2.Lerp(initialLocation, target.PxPosition, moveFraction, delay);
if (moveFraction >= delay)
{
self.TraitsImplementing<IMove>().FirstOrDefault()
.SetPosition(self, Util.CellContaining(target.CenterLocation));
if (target.IsActor)
target.Actor.Kill(self);
self.Trait<AttackLeap>().IsLeaping = false;
return NextActivity;
}
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Mods.RA.Render;
using OpenRA.Mods.RA.Move;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
class Leap : CancelableActivity
{
Target target;
int2 initialLocation;
int moveFraction;
const int delay = 6;
public Leap(Actor self, Target target)
{
this.target = target;
initialLocation = self.Trait<Mobile>().PxPosition;
self.Trait<RenderInfantry>().Attacking(self, target);
Sound.Play("dogg5p.aud", self.CenterLocation);
}
public override IActivity Tick(Actor self)
{
if( moveFraction == 0 && IsCanceled ) return NextActivity;
if (!target.IsValid) return NextActivity;
self.Trait<AttackLeap>().IsLeaping = true;
var mobile = self.Trait<Mobile>();
++moveFraction;
mobile.PxPosition = int2.Lerp(initialLocation, target.PxPosition, moveFraction, delay);
if (moveFraction >= delay)
{
self.TraitsImplementing<IMove>().FirstOrDefault()
.SetPosition(self, Util.CellContaining(target.CenterLocation));
if (target.IsActor)
target.Actor.Kill(self);
self.Trait<AttackLeap>().IsLeaping = false;
return NextActivity;
}
return this;
}
}
}

View File

@@ -1,55 +1,55 @@
#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 System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
public class MoveAdjacentTo : CancelableActivity
{
readonly Actor target;
public MoveAdjacentTo( Actor target )
{
this.target = target;
}
public override IActivity Tick( Actor self )
{
if( IsCanceled || target.Destroyed || !target.IsInWorld) return NextActivity;
var mobile = self.Trait<Mobile>();
var ps1 = new PathSearch( self.World, mobile.Info )
{
checkForBlocked = true,
heuristic = location => 0,
inReverse = true
};
foreach( var cell in target.Trait<IOccupySpace>().OccupiedCells() )
{
ps1.AddInitialCell( cell.First );
if( ( mobile.toCell - cell.First ).LengthSquared <= 2 )
return NextActivity;
}
ps1.heuristic = PathSearch.DefaultEstimator( mobile.toCell );
var ps2 = PathSearch.FromPoint( self.World, mobile.Info, mobile.toCell, target.Location, true );
var ret = self.World.WorldActor.Trait<PathFinder>().FindBidiPath( ps1, ps2 );
if( ret.Count > 0 )
ret.RemoveAt( 0 );
return Util.SequenceActivities( mobile.MoveTo( () => ret ), this );
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
public class MoveAdjacentTo : CancelableActivity
{
readonly Actor target;
public MoveAdjacentTo( Actor target )
{
this.target = target;
}
public override IActivity Tick( Actor self )
{
if( IsCanceled || target.Destroyed || !target.IsInWorld) return NextActivity;
var mobile = self.Trait<Mobile>();
var ps1 = new PathSearch( self.World, mobile.Info )
{
checkForBlocked = true,
heuristic = location => 0,
inReverse = true
};
foreach( var cell in target.Trait<IOccupySpace>().OccupiedCells() )
{
ps1.AddInitialCell( cell.First );
if( ( mobile.toCell - cell.First ).LengthSquared <= 2 )
return NextActivity;
}
ps1.heuristic = PathSearch.DefaultEstimator( mobile.toCell );
var ps2 = PathSearch.FromPoint( self.World, mobile.Info, mobile.toCell, target.Location, true );
var ret = self.World.WorldActor.Trait<PathFinder>().FindBidiPath( ps1, ps2 );
if( ret.Count > 0 )
ret.RemoveAt( 0 );
return Util.SequenceActivities( mobile.MoveTo( () => ret ), this );
}
}
}

View File

@@ -1,77 +1,77 @@
#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 System.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Activities
{
public class QueuedActivity : IActivity
{
public QueuedActivity(Action<QueuedActivity> a) { this.a = a; }
public QueuedActivity(Action<QueuedActivity> a, bool interruptable)
{
this.a = a;
this.interruptable = interruptable;
}
Action<QueuedActivity> a;
private bool interruptable = true;
public IActivity NextActivity { get; set; }
public IActivity Tick(Actor self) { return Run(self); }
public IActivity Run(Actor self)
{
if (a != null)
a(this);
return NextActivity;
}
public void Insert(IActivity activity)
{
if (activity == null)
return;
activity.Queue(NextActivity);
NextActivity = activity;
}
public void Cancel(Actor self)
{
if (!interruptable)
return;
a = null;
NextActivity = null;
}
public void Queue( IActivity activity )
{
if( NextActivity != null )
NextActivity.Queue( activity );
else
NextActivity = activity;
}
public IEnumerable<float2> GetCurrentPath()
{
if (NextActivity != null)
foreach (var path in NextActivity.GetCurrentPath())
{
yield return path;
}
yield break;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Activities
{
public class QueuedActivity : IActivity
{
public QueuedActivity(Action<QueuedActivity> a) { this.a = a; }
public QueuedActivity(Action<QueuedActivity> a, bool interruptable)
{
this.a = a;
this.interruptable = interruptable;
}
Action<QueuedActivity> a;
private bool interruptable = true;
public IActivity NextActivity { get; set; }
public IActivity Tick(Actor self) { return Run(self); }
public IActivity Run(Actor self)
{
if (a != null)
a(this);
return NextActivity;
}
public void Insert(IActivity activity)
{
if (activity == null)
return;
activity.Queue(NextActivity);
NextActivity = activity;
}
public void Cancel(Actor self)
{
if (!interruptable)
return;
a = null;
NextActivity = null;
}
public void Queue( IActivity activity )
{
if( NextActivity != null )
NextActivity.Queue( activity );
else
NextActivity = activity;
}
public IEnumerable<float2> GetCurrentPath()
{
if (NextActivity != null)
foreach (var path in NextActivity.GetCurrentPath())
{
yield return path;
}
yield break;
}
}
}

View File

@@ -1,10 +1,10 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion

View File

@@ -1,46 +1,46 @@
#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.Linq;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
public class Rearm : CancelableActivity
{
int remainingTicks = ticksPerPip;
const int ticksPerPip = 25 * 2;
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if (limitedAmmo == null) return NextActivity;
if (--remainingTicks == 0)
{
if (!limitedAmmo.GiveAmmo()) return NextActivity;
var hostBuilding = self.World.FindUnits(self.CenterLocation, self.CenterLocation)
.FirstOrDefault(a => a.HasTrait<RenderBuilding>());
if (hostBuilding != null)
hostBuilding.Trait<RenderBuilding>().PlayCustomAnim(hostBuilding, "active");
remainingTicks = ticksPerPip;
}
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
public class Rearm : CancelableActivity
{
int remainingTicks = ticksPerPip;
const int ticksPerPip = 25 * 2;
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if (limitedAmmo == null) return NextActivity;
if (--remainingTicks == 0)
{
if (!limitedAmmo.GiveAmmo()) return NextActivity;
var hostBuilding = self.World.FindUnits(self.CenterLocation, self.CenterLocation)
.FirstOrDefault(a => a.HasTrait<RenderBuilding>());
if (hostBuilding != null)
hostBuilding.Trait<RenderBuilding>().PlayCustomAnim(hostBuilding, "active");
remainingTicks = ticksPerPip;
}
return this;
}
}
}

View File

@@ -1,25 +1,25 @@
#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 OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
public class RemoveSelf : CancelableActivity
{
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
self.Destroy();
return null;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
public class RemoveSelf : CancelableActivity
{
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
self.Destroy();
return null;
}
}
}

View File

@@ -1,61 +1,61 @@
#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.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
public class Repair : CancelableActivity
{
int remainingTicks;
Actor host;
public Repair(Actor host) { this.host = host; }
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (host != null && !host.IsInWorld) return NextActivity;
if (remainingTicks == 0)
{
var health = self.TraitOrDefault<Health>();
if (health == null) return NextActivity;
var repairsUnits = host.Info.Traits.Get<RepairsUnitsInfo>();
var unitCost = self.Info.Traits.Get<ValuedInfo>().Cost;
var hpToRepair = Math.Min(repairsUnits.HpPerStep, health.MaxHP - health.HP);
var cost = (hpToRepair * unitCost * repairsUnits.ValuePercentage) / (health.MaxHP * 100);
if (!self.Owner.PlayerActor.Trait<PlayerResources>().TakeCash(cost))
{
remainingTicks = 1;
return this;
}
self.InflictDamage(self, -hpToRepair, null);
if (health.DamageState == DamageState.Undamaged)
return NextActivity;
if (host != null)
host.Trait<RenderBuilding>()
.PlayCustomAnim(host, "active");
remainingTicks = repairsUnits.Interval;
}
else
--remainingTicks;
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
public class Repair : CancelableActivity
{
int remainingTicks;
Actor host;
public Repair(Actor host) { this.host = host; }
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (host != null && !host.IsInWorld) return NextActivity;
if (remainingTicks == 0)
{
var health = self.TraitOrDefault<Health>();
if (health == null) return NextActivity;
var repairsUnits = host.Info.Traits.Get<RepairsUnitsInfo>();
var unitCost = self.Info.Traits.Get<ValuedInfo>().Cost;
var hpToRepair = Math.Min(repairsUnits.HpPerStep, health.MaxHP - health.HP);
var cost = (hpToRepair * unitCost * repairsUnits.ValuePercentage) / (health.MaxHP * 100);
if (!self.Owner.PlayerActor.Trait<PlayerResources>().TakeCash(cost))
{
remainingTicks = 1;
return this;
}
self.InflictDamage(self, -hpToRepair, null);
if (health.DamageState == DamageState.Undamaged)
return NextActivity;
if (host != null)
host.Trait<RenderBuilding>()
.PlayCustomAnim(host, "active");
remainingTicks = repairsUnits.Interval;
}
else
--remainingTicks;
return this;
}
}
}

View File

@@ -1,13 +1,13 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion
#endregion
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
@@ -21,20 +21,20 @@ namespace OpenRA.Mods.RA.Activities
public RepairBuilding(Actor target) { this.target = target; }
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
return NextActivity;
{
if (IsCanceled) return NextActivity;
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
return NextActivity;
var health = target.Trait<Health>();
if (health.DamageState == DamageState.Undamaged)
return NextActivity;
target.InflictDamage(self, -health.MaxHP, null);
target.InflictDamage(self, -health.MaxHP, null);
self.Destroy();
return this;
}
}
}
}

View File

@@ -1,32 +1,32 @@
#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.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
public class Teleport : CancelableActivity
{
int2 destination;
public Teleport(int2 destination)
{
this.destination = destination;
}
public override IActivity Tick(Actor self)
{
self.TraitsImplementing<ITeleportable>().FirstOrDefault().SetPosition(self, destination);
return NextActivity;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
public class Teleport : CancelableActivity
{
int2 destination;
public Teleport(int2 destination)
{
this.destination = destination;
}
public override IActivity Tick(Actor self)
{
self.TraitsImplementing<ITeleportable>().FirstOrDefault().SetPosition(self, destination);
return NextActivity;
}
}
}

View File

@@ -1,87 +1,87 @@
#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 OpenRA.FileFormats;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
class Transform : CancelableActivity
{
string actor = null;
int2 offset;
string[] sounds = null;
int facing;
RenderBuilding rb;
public Transform(Actor self, string toActor, int2 offset, int facing, string[] sounds)
{
this.actor = toActor;
this.offset = offset;
this.sounds = sounds;
this.facing = facing;
rb = self.TraitOrDefault<RenderBuilding>();
}
void DoTransform(Actor self)
{
// Hack: repeat the first frame of the make anim instead
// of flashing the full structure for a frame
if (rb != null)
rb.PlayCustomAnim(self, "make");
self.World.AddFrameEndTask(w =>
{
var selected = w.Selection.Contains(self);
self.Destroy();
foreach (var s in sounds)
Sound.PlayToPlayer(self.Owner, s, self.CenterLocation);
var init = new TypeDictionary
{
new LocationInit( self.Location + offset ),
new OwnerInit( self.Owner ),
new FacingInit( facing ),
};
if (self.HasTrait<Health>())
init.Add( new HealthInit( self.Trait<Health>().HPFraction ));
var a = w.CreateActor( actor, init );
if (selected)
w.Selection.Add(w, a);
});
}
bool started = false;
public override IActivity Tick( Actor self )
{
if (IsCanceled) return NextActivity;
if (started) return this;
if (rb == null)
DoTransform(self);
else
{
rb.PlayCustomAnimBackwards(self, "make", () => DoTransform(self));
foreach (var s in self.Info.Traits.Get<BuildingInfo>().SellSounds)
Sound.PlayToPlayer(self.Owner, s, self.CenterLocation);
started = true;
}
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.FileFormats;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
class Transform : CancelableActivity
{
string actor = null;
int2 offset;
string[] sounds = null;
int facing;
RenderBuilding rb;
public Transform(Actor self, string toActor, int2 offset, int facing, string[] sounds)
{
this.actor = toActor;
this.offset = offset;
this.sounds = sounds;
this.facing = facing;
rb = self.TraitOrDefault<RenderBuilding>();
}
void DoTransform(Actor self)
{
// Hack: repeat the first frame of the make anim instead
// of flashing the full structure for a frame
if (rb != null)
rb.PlayCustomAnim(self, "make");
self.World.AddFrameEndTask(w =>
{
var selected = w.Selection.Contains(self);
self.Destroy();
foreach (var s in sounds)
Sound.PlayToPlayer(self.Owner, s, self.CenterLocation);
var init = new TypeDictionary
{
new LocationInit( self.Location + offset ),
new OwnerInit( self.Owner ),
new FacingInit( facing ),
};
if (self.HasTrait<Health>())
init.Add( new HealthInit( self.Trait<Health>().HPFraction ));
var a = w.CreateActor( actor, init );
if (selected)
w.Selection.Add(w, a);
});
}
bool started = false;
public override IActivity Tick( Actor self )
{
if (IsCanceled) return NextActivity;
if (started) return this;
if (rb == null)
DoTransform(self);
else
{
rb.PlayCustomAnimBackwards(self, "make", () => DoTransform(self));
foreach (var s in self.Info.Traits.Get<BuildingInfo>().SellSounds)
Sound.PlayToPlayer(self.Owner, s, self.CenterLocation);
started = true;
}
return this;
}
}
}

View File

@@ -1,38 +1,38 @@
#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.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
public class Turn : CancelableActivity
{
int desiredFacing;
public Turn( int desiredFacing )
{
this.desiredFacing = desiredFacing;
}
public override IActivity Tick( Actor self )
{
if (IsCanceled) return NextActivity;
var facing = self.Trait<IFacing>();
if( desiredFacing == facing.Facing )
return NextActivity;
facing.Facing = Util.TickFacing(facing.Facing, desiredFacing, facing.ROT);
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
public class Turn : CancelableActivity
{
int desiredFacing;
public Turn( int desiredFacing )
{
this.desiredFacing = desiredFacing;
}
public override IActivity Tick( Actor self )
{
if (IsCanceled) return NextActivity;
var facing = self.Trait<IFacing>();
if( desiredFacing == facing.Facing )
return NextActivity;
facing.Facing = Util.TickFacing(facing.Facing, desiredFacing, facing.ROT);
return this;
}
}
}

View File

@@ -1,82 +1,82 @@
#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.Linq;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using System.Drawing;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
public class UnloadCargo : CancelableActivity
{
int2? ChooseExitTile(Actor self, Actor cargo)
{
// is anyone still hogging this tile?
if (self.World.WorldActor.Trait<UnitInfluence>().GetUnitsAt(self.Location).Count() > 1)
return null;
var mobile = cargo.Trait<Mobile>();
for (var i = -1; i < 2; i++)
for (var j = -1; j < 2; j++)
if ((i != 0 || j != 0) &&
mobile.CanEnterCell(self.Location + new int2(i, j)))
return self.Location + new int2(i, j);
return null;
}
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
// if we're a thing that can turn, turn to the
// right facing for the unload animation
var facing = self.TraitOrDefault<IFacing>();
var unloadFacing = self.Info.Traits.Get<CargoInfo>().UnloadFacing;
if (facing != null && facing.Facing != unloadFacing)
return Util.SequenceActivities( new Turn(unloadFacing), this );
// todo: handle the BS of open/close sequences, which are inconsistent,
// for reasons that probably make good sense to the westwood guys.
var cargo = self.Trait<Cargo>();
if (cargo.IsEmpty(self))
return NextActivity;
var ru = self.TraitOrDefault<RenderUnit>();
if (ru != null)
ru.PlayCustomAnimation(self, "unload", null);
var exitTile = ChooseExitTile(self, cargo.Peek(self));
if (exitTile == null)
return this;
var actor = cargo.Unload(self);
self.World.AddFrameEndTask(w =>
{
if (actor.Destroyed) return;
w.Add(actor);
var mobile = actor.Trait<Mobile>();
mobile.SetPosition(actor, self.Location);
actor.CancelActivity();
actor.QueueActivity(mobile.MoveTo(exitTile.Value, 0));
actor.SetTargetLine(Target.FromCell(exitTile.Value), Color.Green, false);
});
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using System.Drawing;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
public class UnloadCargo : CancelableActivity
{
int2? ChooseExitTile(Actor self, Actor cargo)
{
// is anyone still hogging this tile?
if (self.World.WorldActor.Trait<UnitInfluence>().GetUnitsAt(self.Location).Count() > 1)
return null;
var mobile = cargo.Trait<Mobile>();
for (var i = -1; i < 2; i++)
for (var j = -1; j < 2; j++)
if ((i != 0 || j != 0) &&
mobile.CanEnterCell(self.Location + new int2(i, j)))
return self.Location + new int2(i, j);
return null;
}
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
// if we're a thing that can turn, turn to the
// right facing for the unload animation
var facing = self.TraitOrDefault<IFacing>();
var unloadFacing = self.Info.Traits.Get<CargoInfo>().UnloadFacing;
if (facing != null && facing.Facing != unloadFacing)
return Util.SequenceActivities( new Turn(unloadFacing), this );
// todo: handle the BS of open/close sequences, which are inconsistent,
// for reasons that probably make good sense to the westwood guys.
var cargo = self.Trait<Cargo>();
if (cargo.IsEmpty(self))
return NextActivity;
var ru = self.TraitOrDefault<RenderUnit>();
if (ru != null)
ru.PlayCustomAnimation(self, "unload", null);
var exitTile = ChooseExitTile(self, cargo.Peek(self));
if (exitTile == null)
return this;
var actor = cargo.Unload(self);
self.World.AddFrameEndTask(w =>
{
if (actor.Destroyed) return;
w.Add(actor);
var mobile = actor.Trait<Mobile>();
mobile.SetPosition(actor, self.Location);
actor.CancelActivity();
actor.QueueActivity(mobile.MoveTo(exitTile.Value, 0));
actor.SetTargetLine(Target.FromCell(exitTile.Value), Color.Green, false);
});
return this;
}
}
}

View File

@@ -1,41 +1,41 @@
#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 OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
public class Wait : CancelableActivity
{
int remainingTicks;
bool interruptable = true;
public Wait(int period) { remainingTicks = period; }
public Wait(int period, bool interruptable)
{
remainingTicks = period;
this.interruptable = interruptable;
}
public override IActivity Tick(Actor self)
{
if (remainingTicks-- == 0) return NextActivity;
return this;
}
protected override bool OnCancel( Actor self )
{
if( !interruptable ) return false;
remainingTicks = 0;
return true;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
public class Wait : CancelableActivity
{
int remainingTicks;
bool interruptable = true;
public Wait(int period) { remainingTicks = period; }
public Wait(int period, bool interruptable)
{
remainingTicks = period;
this.interruptable = interruptable;
}
public override IActivity Tick(Actor self)
{
if (remainingTicks-- == 0) return NextActivity;
return this;
}
protected override bool OnCancel( Actor self )
{
if( !interruptable ) return false;
remainingTicks = 0;
return true;
}
}
}

View File

@@ -1,10 +1,10 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion

View File

@@ -1,160 +1,160 @@
#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 System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
using OpenRA.FileFormats;
namespace OpenRA.Mods.RA.Air
{
public class DebugAircraftFacingInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new DebugAircraftFacing(init.self); }
}
public class DebugAircraftFacing : ISync
{
readonly Actor self;
public DebugAircraftFacing(Actor self){this.self = self;}
[Sync] public int foo { get { return self.Trait<Aircraft>().Facing; } }
}
public class DebugAircraftSubPxXInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new DebugAircraftSubPxX(init.self); }
}
public class DebugAircraftSubPxX : ISync
{
readonly Actor self;
public DebugAircraftSubPxX(Actor self){this.self = self;}
[Sync] public int foo { get { return self.Trait<Aircraft>().SubPxPosition.X; } }
}
public class DebugAircraftSubPxYInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new DebugAircraftSubPxY(init.self); }
}
public class DebugAircraftSubPxY : ISync
{
readonly Actor self;
public DebugAircraftSubPxY(Actor self){this.self = self;}
[Sync] public int foo { get { return self.Trait<Aircraft>().SubPxPosition.Y; } }
}
public class DebugAircraftAltitudeInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new DebugAircraftAltitude(init.self); }
}
public class DebugAircraftAltitude : ISync
{
readonly Actor self;
public DebugAircraftAltitude(Actor self){this.self = self;}
[Sync] public int Facing { get { return self.Trait<Aircraft>().Altitude; } }
}
public class AircraftInfo : ITraitInfo
{
public readonly int CruiseAltitude = 30;
[ActorReference]
public readonly string[] RepairBuildings = { "fix" };
[ActorReference]
public readonly string[] RearmBuildings = { "hpad", "afld" };
public readonly int InitialFacing = 128;
public readonly int ROT = 255;
public readonly int Speed = 1;
public readonly string[] LandableTerrainTypes = { };
public virtual object Create( ActorInitializer init ) { return new Aircraft( init , this ); }
}
public class Aircraft : IMove, IFacing, IOccupySpace, ISync
{
protected readonly Actor self;
[Sync]
public int Facing { get; set; }
[Sync]
public int Altitude { get; set; }
[Sync]
public int2 SubPxPosition;
public int2 PxPosition { get { return new int2( SubPxPosition.X / 1024, SubPxPosition.Y / 1024 ); } }
public int2 TopLeft { get { return Util.CellContaining( PxPosition ); } }
readonly AircraftInfo Info;
public Aircraft( ActorInitializer init , AircraftInfo info)
{
this.self = init.self;
if( init.Contains<LocationInit>() )
this.SubPxPosition = 1024 * Util.CenterOfCell( init.Get<LocationInit, int2>() );
this.Facing = init.Contains<FacingInit>() ? init.Get<FacingInit,int>() : info.InitialFacing;
this.Altitude = init.Contains<AltitudeInit>() ? init.Get<AltitudeInit,int>() : 0;
Info = info;
}
public int ROT { get { return Info.ROT; } }
public int InitialFacing { get { return Info.InitialFacing; } }
public void SetPosition(Actor self, int2 cell)
{
SetPxPosition( self, Util.CenterOfCell( cell ) );
}
public void SetPxPosition( Actor self, int2 px )
{
SubPxPosition = px * 1024;
}
public void AdjustPxPosition(Actor self, int2 px) { SetPxPosition(self, px); }
public bool AircraftCanEnter(Actor a)
{
if( self.Owner != a.Owner ) return false;
return Info.RearmBuildings.Contains( a.Info.Name )
|| Info.RepairBuildings.Contains( a.Info.Name );
}
public bool CanEnterCell(int2 location) { return true; }
public int MovementSpeed
{
get
{
decimal ret = Info.Speed;
foreach( var t in self.TraitsImplementing<ISpeedModifier>() )
ret *= t.GetSpeedModifier();
return (int)ret;
}
}
Pair<int2, SubCell>[] noCells = new Pair<int2, SubCell>[] { };
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { return noCells; }
public void TickMove( int speed, int facing )
{
var rawspeed = speed * 7 / (32 * 1024);
SubPxPosition += rawspeed * -Util.SubPxVector[facing];
}
public bool CanLand(int2 cell)
{
if (!self.World.Map.IsInMap(cell))
return false;
if (self.World.WorldActor.Trait<UnitInfluence>().AnyUnitsAt(cell))
return false;
var type = self.World.GetTerrainType(cell);
return Info.LandableTerrainTypes.Contains(type);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
using OpenRA.FileFormats;
namespace OpenRA.Mods.RA.Air
{
public class DebugAircraftFacingInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new DebugAircraftFacing(init.self); }
}
public class DebugAircraftFacing : ISync
{
readonly Actor self;
public DebugAircraftFacing(Actor self){this.self = self;}
[Sync] public int foo { get { return self.Trait<Aircraft>().Facing; } }
}
public class DebugAircraftSubPxXInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new DebugAircraftSubPxX(init.self); }
}
public class DebugAircraftSubPxX : ISync
{
readonly Actor self;
public DebugAircraftSubPxX(Actor self){this.self = self;}
[Sync] public int foo { get { return self.Trait<Aircraft>().SubPxPosition.X; } }
}
public class DebugAircraftSubPxYInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new DebugAircraftSubPxY(init.self); }
}
public class DebugAircraftSubPxY : ISync
{
readonly Actor self;
public DebugAircraftSubPxY(Actor self){this.self = self;}
[Sync] public int foo { get { return self.Trait<Aircraft>().SubPxPosition.Y; } }
}
public class DebugAircraftAltitudeInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new DebugAircraftAltitude(init.self); }
}
public class DebugAircraftAltitude : ISync
{
readonly Actor self;
public DebugAircraftAltitude(Actor self){this.self = self;}
[Sync] public int Facing { get { return self.Trait<Aircraft>().Altitude; } }
}
public class AircraftInfo : ITraitInfo
{
public readonly int CruiseAltitude = 30;
[ActorReference]
public readonly string[] RepairBuildings = { "fix" };
[ActorReference]
public readonly string[] RearmBuildings = { "hpad", "afld" };
public readonly int InitialFacing = 128;
public readonly int ROT = 255;
public readonly int Speed = 1;
public readonly string[] LandableTerrainTypes = { };
public virtual object Create( ActorInitializer init ) { return new Aircraft( init , this ); }
}
public class Aircraft : IMove, IFacing, IOccupySpace, ISync
{
protected readonly Actor self;
[Sync]
public int Facing { get; set; }
[Sync]
public int Altitude { get; set; }
[Sync]
public int2 SubPxPosition;
public int2 PxPosition { get { return new int2( SubPxPosition.X / 1024, SubPxPosition.Y / 1024 ); } }
public int2 TopLeft { get { return Util.CellContaining( PxPosition ); } }
readonly AircraftInfo Info;
public Aircraft( ActorInitializer init , AircraftInfo info)
{
this.self = init.self;
if( init.Contains<LocationInit>() )
this.SubPxPosition = 1024 * Util.CenterOfCell( init.Get<LocationInit, int2>() );
this.Facing = init.Contains<FacingInit>() ? init.Get<FacingInit,int>() : info.InitialFacing;
this.Altitude = init.Contains<AltitudeInit>() ? init.Get<AltitudeInit,int>() : 0;
Info = info;
}
public int ROT { get { return Info.ROT; } }
public int InitialFacing { get { return Info.InitialFacing; } }
public void SetPosition(Actor self, int2 cell)
{
SetPxPosition( self, Util.CenterOfCell( cell ) );
}
public void SetPxPosition( Actor self, int2 px )
{
SubPxPosition = px * 1024;
}
public void AdjustPxPosition(Actor self, int2 px) { SetPxPosition(self, px); }
public bool AircraftCanEnter(Actor a)
{
if( self.Owner != a.Owner ) return false;
return Info.RearmBuildings.Contains( a.Info.Name )
|| Info.RepairBuildings.Contains( a.Info.Name );
}
public bool CanEnterCell(int2 location) { return true; }
public int MovementSpeed
{
get
{
decimal ret = Info.Speed;
foreach( var t in self.TraitsImplementing<ISpeedModifier>() )
ret *= t.GetSpeedModifier();
return (int)ret;
}
}
Pair<int2, SubCell>[] noCells = new Pair<int2, SubCell>[] { };
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { return noCells; }
public void TickMove( int speed, int facing )
{
var rawspeed = speed * 7 / (32 * 1024);
SubPxPosition += rawspeed * -Util.SubPxVector[facing];
}
public bool CanLand(int2 cell)
{
if (!self.World.Map.IsInMap(cell))
return false;
if (self.World.WorldActor.Trait<UnitInfluence>().AnyUnitsAt(cell))
return false;
var type = self.World.GetTerrainType(cell);
return Info.LandableTerrainTypes.Contains(type);
}
}
}

View File

@@ -1,30 +1,30 @@
#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 OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Air
{
class AttackHeliInfo : AttackFrontalInfo
{
public override object Create(ActorInitializer init) { return new AttackHeli(init.self, this); }
}
class AttackHeli : AttackFrontal
{
public AttackHeli(Actor self, AttackHeliInfo info) : base(self, info) { }
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
return new HeliAttack( newTarget );
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Air
{
class AttackHeliInfo : AttackFrontalInfo
{
public override object Create(ActorInitializer init) { return new AttackHeli(init.self, this); }
}
class AttackHeli : AttackFrontal
{
public AttackHeli(Actor self, AttackHeliInfo info) : base(self, info) { }
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
return new HeliAttack( newTarget );
}
}
}

View File

@@ -1,37 +1,37 @@
#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 OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Air
{
class AttackPlaneInfo : AttackFrontalInfo
{
public override object Create(ActorInitializer init) { return new AttackPlane(init.self, this); }
}
class AttackPlane : AttackFrontal
{
public AttackPlane(Actor self, AttackPlaneInfo info) : base(self, info) { }
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
return new FlyAttack( newTarget );
}
protected override bool CanAttack(Actor self, Target target)
{
// dont fire while landed
return base.CanAttack(self, target)
&& self.Trait<Aircraft>().Altitude > 0;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Air
{
class AttackPlaneInfo : AttackFrontalInfo
{
public override object Create(ActorInitializer init) { return new AttackPlane(init.self, this); }
}
class AttackPlane : AttackFrontal
{
public AttackPlane(Actor self, AttackPlaneInfo info) : base(self, info) { }
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
return new FlyAttack( newTarget );
}
protected override bool CanAttack(Actor self, Target target)
{
// dont fire while landed
return base.CanAttack(self, target)
&& self.Trait<Aircraft>().Altitude > 0;
}
}
}

View File

@@ -1,81 +1,81 @@
#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 OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
class FallsToEarthInfo : TraitInfo<FallsToEarth>
{
[WeaponReference]
public readonly string Explosion = null;
public readonly bool Spins = true;
public readonly bool Moves = false;
}
class FallsToEarth : INotifyDamage
{
public void Damaged(Actor self, AttackInfo e)
{
if (self.IsDead())
{
self.Trait<Health>().RemoveOnDeath = false;
self.CancelActivity();
self.QueueActivity(new FallToEarth(self, self.Info.Traits.Get<FallsToEarthInfo>()));
}
}
}
class FallToEarth : CancelableActivity
{
int acceleration = 0;
int spin = 0;
FallsToEarthInfo info;
public FallToEarth(Actor self, FallsToEarthInfo info)
{
this.info = info;
if (info.Spins)
acceleration = self.World.SharedRandom.Next(2) * 2 - 1;
}
public override IActivity Tick(Actor self)
{
var aircraft = self.Trait<Aircraft>();
if (aircraft.Altitude <= 0)
{
if (info.Explosion != null)
Combat.DoExplosion(self, info.Explosion, self.CenterLocation, 0);
self.Destroy();
return null;
}
if (info.Spins)
{
spin += acceleration;
aircraft.Facing = (aircraft.Facing + spin) % 256;
}
if (info.Moves)
FlyUtil.Fly(self, aircraft.Altitude);
aircraft.Altitude--;
return this;
}
protected override bool OnCancel(Actor self) { return false; }
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
class FallsToEarthInfo : TraitInfo<FallsToEarth>
{
[WeaponReference]
public readonly string Explosion = null;
public readonly bool Spins = true;
public readonly bool Moves = false;
}
class FallsToEarth : INotifyDamage
{
public void Damaged(Actor self, AttackInfo e)
{
if (self.IsDead())
{
self.Trait<Health>().RemoveOnDeath = false;
self.CancelActivity();
self.QueueActivity(new FallToEarth(self, self.Info.Traits.Get<FallsToEarthInfo>()));
}
}
}
class FallToEarth : CancelableActivity
{
int acceleration = 0;
int spin = 0;
FallsToEarthInfo info;
public FallToEarth(Actor self, FallsToEarthInfo info)
{
this.info = info;
if (info.Spins)
acceleration = self.World.SharedRandom.Next(2) * 2 - 1;
}
public override IActivity Tick(Actor self)
{
var aircraft = self.Trait<Aircraft>();
if (aircraft.Altitude <= 0)
{
if (info.Explosion != null)
Combat.DoExplosion(self, info.Explosion, self.CenterLocation, 0);
self.Destroy();
return null;
}
if (info.Spins)
{
spin += acceleration;
aircraft.Facing = (aircraft.Facing + spin) % 256;
}
if (info.Moves)
FlyUtil.Fly(self, aircraft.Altitude);
aircraft.Altitude--;
return this;
}
protected override bool OnCancel(Actor self) { return false; }
}
}

View File

@@ -1,65 +1,65 @@
#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 System.Collections.Generic;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
public class Fly : CancelableActivity
{
public readonly int2 Pos;
private Fly( int2 px ) { Pos = px; }
public static Fly ToPx( int2 px ) { return new Fly( px ); }
public static Fly ToCell( int2 pos ) { return new Fly( Util.CenterOfCell( pos ) ); }
public override IActivity Tick(Actor self)
{
var cruiseAltitude = self.Info.Traits.Get<PlaneInfo>().CruiseAltitude;
if (IsCanceled) return NextActivity;
var d = Pos - self.CenterLocation;
if (d.LengthSquared < 50) /* close enough */
return NextActivity;
var aircraft = self.Trait<Aircraft>();
var desiredFacing = Util.GetFacing(d, aircraft.Facing);
if (aircraft.Altitude == cruiseAltitude)
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);
if (aircraft.Altitude < cruiseAltitude)
++aircraft.Altitude;
FlyUtil.Fly(self, cruiseAltitude);
return this;
}
public override IEnumerable<float2> GetCurrentPath()
{
yield return Pos;
}
}
public static class FlyUtil
{
public static void Fly(Actor self, int desiredAltitude )
{
var aircraft = self.Trait<Aircraft>();
aircraft.TickMove( 1024 * aircraft.MovementSpeed, aircraft.Facing );
aircraft.Altitude += Math.Sign(desiredAltitude - aircraft.Altitude);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
public class Fly : CancelableActivity
{
public readonly int2 Pos;
private Fly( int2 px ) { Pos = px; }
public static Fly ToPx( int2 px ) { return new Fly( px ); }
public static Fly ToCell( int2 pos ) { return new Fly( Util.CenterOfCell( pos ) ); }
public override IActivity Tick(Actor self)
{
var cruiseAltitude = self.Info.Traits.Get<PlaneInfo>().CruiseAltitude;
if (IsCanceled) return NextActivity;
var d = Pos - self.CenterLocation;
if (d.LengthSquared < 50) /* close enough */
return NextActivity;
var aircraft = self.Trait<Aircraft>();
var desiredFacing = Util.GetFacing(d, aircraft.Facing);
if (aircraft.Altitude == cruiseAltitude)
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);
if (aircraft.Altitude < cruiseAltitude)
++aircraft.Altitude;
FlyUtil.Fly(self, cruiseAltitude);
return this;
}
public override IEnumerable<float2> GetCurrentPath()
{
yield return Pos;
}
}
public static class FlyUtil
{
public static void Fly(Actor self, int desiredAltitude )
{
var aircraft = self.Trait<Aircraft>();
aircraft.TickMove( 1024 * aircraft.MovementSpeed, aircraft.Facing );
aircraft.Altitude += Math.Sign(desiredAltitude - aircraft.Altitude);
}
}
}

View File

@@ -1,71 +1,71 @@
#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 OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
public class FlyAttack : CancelableActivity
{
readonly Target Target;
IActivity inner;
public FlyAttack(Target target) { Target = target; }
public override IActivity Tick(Actor self)
{
if( !Target.IsValid )
Cancel( self );
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if( limitedAmmo != null && !limitedAmmo.HasAmmo() )
Cancel( self );
var attack = self.Trait<AttackPlane>();
attack.DoAttack( self, Target );
if( inner == null )
{
if( IsCanceled )
return NextActivity;
inner = Util.SequenceActivities(
Fly.ToPx(Target.CenterLocation),
new FlyTimed(50));
}
inner = Util.RunActivity( self, inner );
return this;
}
protected override bool OnCancel( Actor self )
{
if( inner != null )
inner.Cancel( self );
return base.OnCancel( self );
}
}
public class FlyCircle : CancelableActivity
{
int2 Target;
public FlyCircle(int2 target) { Target = target; }
public override IActivity Tick(Actor self)
{
if( IsCanceled ) return NextActivity;
return Util.SequenceActivities(
Fly.ToCell(Target),
new FlyTimed(50),
this);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
public class FlyAttack : CancelableActivity
{
readonly Target Target;
IActivity inner;
public FlyAttack(Target target) { Target = target; }
public override IActivity Tick(Actor self)
{
if( !Target.IsValid )
Cancel( self );
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if( limitedAmmo != null && !limitedAmmo.HasAmmo() )
Cancel( self );
var attack = self.Trait<AttackPlane>();
attack.DoAttack( self, Target );
if( inner == null )
{
if( IsCanceled )
return NextActivity;
inner = Util.SequenceActivities(
Fly.ToPx(Target.CenterLocation),
new FlyTimed(50));
}
inner = Util.RunActivity( self, inner );
return this;
}
protected override bool OnCancel( Actor self )
{
if( inner != null )
inner.Cancel( self );
return base.OnCancel( self );
}
}
public class FlyCircle : CancelableActivity
{
int2 Target;
public FlyCircle(int2 target) { Target = target; }
public override IActivity Tick(Actor self)
{
if( IsCanceled ) return NextActivity;
return Util.SequenceActivities(
Fly.ToCell(Target),
new FlyTimed(50),
this);
}
}
}

View File

@@ -1,49 +1,49 @@
#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 OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
public class FlyTimed : CancelableActivity
{
int remainingTicks;
public FlyTimed(int ticks) { remainingTicks = ticks; }
public override IActivity Tick(Actor self)
{
if( IsCanceled ) return NextActivity;
var targetAltitude = self.Info.Traits.Get<PlaneInfo>().CruiseAltitude;
if (remainingTicks-- == 0) return NextActivity;
FlyUtil.Fly(self, targetAltitude);
return this;
}
}
public class FlyOffMap : CancelableActivity
{
public bool Interruptible = true;
public override IActivity Tick(Actor self)
{
var targetAltitude = self.Info.Traits.Get<PlaneInfo>().CruiseAltitude;
if (IsCanceled || !self.World.Map.IsInMap(self.Location)) return NextActivity;
FlyUtil.Fly(self, targetAltitude);
return this;
}
protected override bool OnCancel( Actor self )
{
return Interruptible;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
public class FlyTimed : CancelableActivity
{
int remainingTicks;
public FlyTimed(int ticks) { remainingTicks = ticks; }
public override IActivity Tick(Actor self)
{
if( IsCanceled ) return NextActivity;
var targetAltitude = self.Info.Traits.Get<PlaneInfo>().CruiseAltitude;
if (remainingTicks-- == 0) return NextActivity;
FlyUtil.Fly(self, targetAltitude);
return this;
}
}
public class FlyOffMap : CancelableActivity
{
public bool Interruptible = true;
public override IActivity Tick(Actor self)
{
var targetAltitude = self.Info.Traits.Get<PlaneInfo>().CruiseAltitude;
if (IsCanceled || !self.World.Map.IsInMap(self.Location)) return NextActivity;
FlyUtil.Fly(self, targetAltitude);
return this;
}
protected override bool OnCancel( Actor self )
{
return Interruptible;
}
}
}

View File

@@ -1,55 +1,55 @@
#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 System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
public class HeliAttack : CancelableActivity
{
Target target;
public HeliAttack( Target target ) { this.target = target; }
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (!target.IsValid) return NextActivity;
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if (limitedAmmo != null && !limitedAmmo.HasAmmo())
return Util.SequenceActivities( new HeliReturn(), NextActivity );
var aircraft = self.Trait<Aircraft>();
var info = self.Info.Traits.Get<HelicopterInfo>();
if (aircraft.Altitude != info.CruiseAltitude)
{
aircraft.Altitude += Math.Sign(info.CruiseAltitude - aircraft.Altitude);
return this;
}
var attack = self.Trait<AttackHeli>();
var range = attack.GetMaximumRange() - 1;
var dist = target.CenterLocation - self.CenterLocation;
var desiredFacing = Util.GetFacing(dist, aircraft.Facing);
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);
if( !float2.WithinEpsilon( float2.Zero, dist, range * Game.CellSize ) )
aircraft.TickMove( 1024 * aircraft.MovementSpeed, desiredFacing );
attack.DoAttack( self, target );
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
public class HeliAttack : CancelableActivity
{
Target target;
public HeliAttack( Target target ) { this.target = target; }
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (!target.IsValid) return NextActivity;
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if (limitedAmmo != null && !limitedAmmo.HasAmmo())
return Util.SequenceActivities( new HeliReturn(), NextActivity );
var aircraft = self.Trait<Aircraft>();
var info = self.Info.Traits.Get<HelicopterInfo>();
if (aircraft.Altitude != info.CruiseAltitude)
{
aircraft.Altitude += Math.Sign(info.CruiseAltitude - aircraft.Altitude);
return this;
}
var attack = self.Trait<AttackHeli>();
var range = attack.GetMaximumRange() - 1;
var dist = target.CenterLocation - self.CenterLocation;
var desiredFacing = Util.GetFacing(dist, aircraft.Facing);
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);
if( !float2.WithinEpsilon( float2.Zero, dist, range * Game.CellSize ) )
aircraft.TickMove( 1024 * aircraft.MovementSpeed, desiredFacing );
attack.DoAttack( self, target );
return this;
}
}
}

View File

@@ -1,58 +1,58 @@
#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 System.Collections.Generic;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
class HeliFly : CancelableActivity
{
public readonly int2 Dest;
public HeliFly(int2 dest)
{
Dest = dest;
}
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
var info = self.Info.Traits.Get<HelicopterInfo>();
var aircraft = self.Trait<Aircraft>();
if (aircraft.Altitude != info.CruiseAltitude)
{
aircraft.Altitude += Math.Sign(info.CruiseAltitude - aircraft.Altitude);
return this;
}
var dist = Dest - aircraft.PxPosition;
if (float2.WithinEpsilon(float2.Zero, dist, 2))
{
aircraft.SubPxPosition = Dest * 1024;
return NextActivity;
}
var desiredFacing = Util.GetFacing(dist, aircraft.Facing);
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);
aircraft.TickMove( 1024 * aircraft.MovementSpeed, desiredFacing );
return this;
}
public override IEnumerable<float2> GetCurrentPath()
{
yield return Dest;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
class HeliFly : CancelableActivity
{
public readonly int2 Dest;
public HeliFly(int2 dest)
{
Dest = dest;
}
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
var info = self.Info.Traits.Get<HelicopterInfo>();
var aircraft = self.Trait<Aircraft>();
if (aircraft.Altitude != info.CruiseAltitude)
{
aircraft.Altitude += Math.Sign(info.CruiseAltitude - aircraft.Altitude);
return this;
}
var dist = Dest - aircraft.PxPosition;
if (float2.WithinEpsilon(float2.Zero, dist, 2))
{
aircraft.SubPxPosition = Dest * 1024;
return NextActivity;
}
var desiredFacing = Util.GetFacing(dist, aircraft.Facing);
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);
aircraft.TickMove( 1024 * aircraft.MovementSpeed, desiredFacing );
return this;
}
public override IEnumerable<float2> GetCurrentPath()
{
yield return Dest;
}
}
}

View File

@@ -1,36 +1,36 @@
#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 OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
class HeliLand : CancelableActivity
{
public HeliLand(bool requireSpace) { this.requireSpace = requireSpace; }
bool requireSpace;
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
var aircraft = self.Trait<Aircraft>();
if (aircraft.Altitude == 0)
return NextActivity;
if (requireSpace && !aircraft.CanLand(self.Location))
return this;
--aircraft.Altitude;
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
class HeliLand : CancelableActivity
{
public HeliLand(bool requireSpace) { this.requireSpace = requireSpace; }
bool requireSpace;
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
var aircraft = self.Trait<Aircraft>();
if (aircraft.Altitude == 0)
return NextActivity;
if (requireSpace && !aircraft.CanLand(self.Location))
return this;
--aircraft.Altitude;
return this;
}
}
}

View File

@@ -1,56 +1,56 @@
#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.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Activities;
namespace OpenRA.Mods.RA.Air
{
public class HeliReturn : CancelableActivity
{
static Actor ChooseHelipad(Actor self)
{
var rearmBuildings = self.Info.Traits.Get<HelicopterInfo>().RearmBuildings;
return self.World.Queries.OwnedBy[self.Owner].FirstOrDefault(
a => rearmBuildings.Contains(a.Info.Name) &&
!Reservable.IsReserved(a));
}
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
var dest = ChooseHelipad(self);
var initialFacing = self.Info.Traits.Get<AircraftInfo>().InitialFacing;
if (dest == null)
return Util.SequenceActivities(
new Turn(initialFacing),
new HeliLand(true),
NextActivity);
var res = dest.TraitOrDefault<Reservable>();
if (res != null)
self.Trait<Helicopter>().reservation = res.Reserve(self);
var exit = dest.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault();
var offset = exit != null ? exit.SpawnOffset : int2.Zero;
return Util.SequenceActivities(
new HeliFly(dest.Trait<IHasLocation>().PxPosition + offset),
new Turn(initialFacing),
new HeliLand(false),
new Rearm(),
NextActivity);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Activities;
namespace OpenRA.Mods.RA.Air
{
public class HeliReturn : CancelableActivity
{
static Actor ChooseHelipad(Actor self)
{
var rearmBuildings = self.Info.Traits.Get<HelicopterInfo>().RearmBuildings;
return self.World.Queries.OwnedBy[self.Owner].FirstOrDefault(
a => rearmBuildings.Contains(a.Info.Name) &&
!Reservable.IsReserved(a));
}
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
var dest = ChooseHelipad(self);
var initialFacing = self.Info.Traits.Get<AircraftInfo>().InitialFacing;
if (dest == null)
return Util.SequenceActivities(
new Turn(initialFacing),
new HeliLand(true),
NextActivity);
var res = dest.TraitOrDefault<Reservable>();
if (res != null)
self.Trait<Helicopter>().reservation = res.Reserve(self);
var exit = dest.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault();
var offset = exit != null ? exit.SpawnOffset : int2.Zero;
return Util.SequenceActivities(
new HeliFly(dest.Trait<IHasLocation>().PxPosition + offset),
new Turn(initialFacing),
new HeliLand(false),
new Rearm(),
NextActivity);
}
}
}

View File

@@ -1,158 +1,158 @@
#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 System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Air
{
class HelicopterInfo : AircraftInfo
{
public readonly int IdealSeparation = 40;
public readonly bool LandWhenIdle = true;
public override object Create( ActorInitializer init ) { return new Helicopter( init, this); }
}
class Helicopter : Aircraft, ITick, IIssueOrder, IResolveOrder, IOrderVoice
{
public IDisposable reservation;
HelicopterInfo Info;
public Helicopter( ActorInitializer init, HelicopterInfo info) : base( init, info )
{
Info = info;
}
public IEnumerable<IOrderTargeter> Orders
{
get
{
yield return new EnterOrderTargeter<Building>( "Enter", 5, false, true,
target => AircraftCanEnter( target ), target => !Reservable.IsReserved( target ) );
yield return new AircraftMoveOrderTargeter();
}
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{
if( order.OrderID == "Enter" )
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
if( order.OrderID == "Move" )
return new Order(order.OrderID, self, queued) { TargetLocation = Util.CellContaining(target.CenterLocation) };
return null;
}
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "Move" || order.OrderString == "Enter") ? "Move" : null;
}
public void ResolveOrder(Actor self, Order order)
{
if (reservation != null)
{
reservation.Dispose();
reservation = null;
}
if (order.OrderString == "Move")
{
var target = order.TargetLocation.Clamp(self.World.Map.Bounds);
self.SetTargetLine(Target.FromCell(target), Color.Green);
self.CancelActivity();
self.QueueActivity(new HeliFly(Util.CenterOfCell(target)));
if (Info.LandWhenIdle)
{
self.QueueActivity(new Turn(Info.InitialFacing));
self.QueueActivity(new HeliLand(true));
}
}
if (order.OrderString == "Enter")
{
if (Reservable.IsReserved(order.TargetActor)) return;
var res = order.TargetActor.TraitOrDefault<Reservable>();
if (res != null)
reservation = res.Reserve(self);
var exit = order.TargetActor.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault();
var offset = exit != null ? exit.SpawnOffset : int2.Zero;
self.SetTargetLine(Target.FromActor(order.TargetActor), Color.Green);
self.CancelActivity();
self.QueueActivity(new HeliFly(order.TargetActor.Trait<IHasLocation>().PxPosition + offset));
self.QueueActivity(new Turn(Info.InitialFacing));
self.QueueActivity(new HeliLand(false));
self.QueueActivity(Info.RearmBuildings.Contains(order.TargetActor.Info.Name)
? (IActivity)new Rearm() : new Repair(order.TargetActor));
}
if (order.OrderString == "Stop")
{
self.CancelActivity();
if (Info.LandWhenIdle)
{
self.QueueActivity(new Turn(Info.InitialFacing));
self.QueueActivity(new HeliLand(true));
}
}
}
public void Tick(Actor self)
{
var aircraft = self.Trait<Aircraft>();
if (aircraft.Altitude <= 0)
return;
var otherHelis = self.World.FindUnitsInCircle(self.CenterLocation, Info.IdealSeparation)
.Where(a => a.HasTrait<Helicopter>());
var f = otherHelis
.Select(h => GetRepulseForce(self, h))
.Aggregate(int2.Zero, (a, b) => a + b);
int RepulsionFacing = Util.GetFacing( f, -1 );
if( RepulsionFacing != -1 )
aircraft.TickMove( 1024 * aircraft.MovementSpeed, RepulsionFacing );
}
// Returns an int2 in subPx units
public int2 GetRepulseForce(Actor self, Actor h)
{
if (self == h)
return int2.Zero;
if( h.Trait<Helicopter>().Altitude < Altitude )
return int2.Zero;
var d = self.CenterLocation - h.CenterLocation;
if (d.Length > Info.IdealSeparation)
return int2.Zero;
if (d.LengthSquared < 1)
return Util.SubPxVector[self.World.SharedRandom.Next(255)];
return (5120 / d.LengthSquared) * d;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Air
{
class HelicopterInfo : AircraftInfo
{
public readonly int IdealSeparation = 40;
public readonly bool LandWhenIdle = true;
public override object Create( ActorInitializer init ) { return new Helicopter( init, this); }
}
class Helicopter : Aircraft, ITick, IIssueOrder, IResolveOrder, IOrderVoice
{
public IDisposable reservation;
HelicopterInfo Info;
public Helicopter( ActorInitializer init, HelicopterInfo info) : base( init, info )
{
Info = info;
}
public IEnumerable<IOrderTargeter> Orders
{
get
{
yield return new EnterOrderTargeter<Building>( "Enter", 5, false, true,
target => AircraftCanEnter( target ), target => !Reservable.IsReserved( target ) );
yield return new AircraftMoveOrderTargeter();
}
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{
if( order.OrderID == "Enter" )
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
if( order.OrderID == "Move" )
return new Order(order.OrderID, self, queued) { TargetLocation = Util.CellContaining(target.CenterLocation) };
return null;
}
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "Move" || order.OrderString == "Enter") ? "Move" : null;
}
public void ResolveOrder(Actor self, Order order)
{
if (reservation != null)
{
reservation.Dispose();
reservation = null;
}
if (order.OrderString == "Move")
{
var target = order.TargetLocation.Clamp(self.World.Map.Bounds);
self.SetTargetLine(Target.FromCell(target), Color.Green);
self.CancelActivity();
self.QueueActivity(new HeliFly(Util.CenterOfCell(target)));
if (Info.LandWhenIdle)
{
self.QueueActivity(new Turn(Info.InitialFacing));
self.QueueActivity(new HeliLand(true));
}
}
if (order.OrderString == "Enter")
{
if (Reservable.IsReserved(order.TargetActor)) return;
var res = order.TargetActor.TraitOrDefault<Reservable>();
if (res != null)
reservation = res.Reserve(self);
var exit = order.TargetActor.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault();
var offset = exit != null ? exit.SpawnOffset : int2.Zero;
self.SetTargetLine(Target.FromActor(order.TargetActor), Color.Green);
self.CancelActivity();
self.QueueActivity(new HeliFly(order.TargetActor.Trait<IHasLocation>().PxPosition + offset));
self.QueueActivity(new Turn(Info.InitialFacing));
self.QueueActivity(new HeliLand(false));
self.QueueActivity(Info.RearmBuildings.Contains(order.TargetActor.Info.Name)
? (IActivity)new Rearm() : new Repair(order.TargetActor));
}
if (order.OrderString == "Stop")
{
self.CancelActivity();
if (Info.LandWhenIdle)
{
self.QueueActivity(new Turn(Info.InitialFacing));
self.QueueActivity(new HeliLand(true));
}
}
}
public void Tick(Actor self)
{
var aircraft = self.Trait<Aircraft>();
if (aircraft.Altitude <= 0)
return;
var otherHelis = self.World.FindUnitsInCircle(self.CenterLocation, Info.IdealSeparation)
.Where(a => a.HasTrait<Helicopter>());
var f = otherHelis
.Select(h => GetRepulseForce(self, h))
.Aggregate(int2.Zero, (a, b) => a + b);
int RepulsionFacing = Util.GetFacing( f, -1 );
if( RepulsionFacing != -1 )
aircraft.TickMove( 1024 * aircraft.MovementSpeed, RepulsionFacing );
}
// Returns an int2 in subPx units
public int2 GetRepulseForce(Actor self, Actor h)
{
if (self == h)
return int2.Zero;
if( h.Trait<Helicopter>().Altitude < Altitude )
return int2.Zero;
var d = self.CenterLocation - h.CenterLocation;
if (d.Length > Info.IdealSeparation)
return int2.Zero;
if (d.LengthSquared < 1)
return Util.SubPxVector[self.World.SharedRandom.Next(255)];
return (5120 / d.LengthSquared) * d;
}
}
}

View File

@@ -1,47 +1,47 @@
#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 System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
public class Land : CancelableActivity
{
Target Target;
public Land(Target t) { Target = t; }
public override IActivity Tick(Actor self)
{
if (!Target.IsValid)
Cancel(self);
if (IsCanceled) return NextActivity;
var d = Target.CenterLocation - self.CenterLocation;
if (d.LengthSquared < 50) /* close enough */
return NextActivity;
var aircraft = self.Trait<Aircraft>();
if (aircraft.Altitude > 0)
--aircraft.Altitude;
var desiredFacing = Util.GetFacing(d, aircraft.Facing);
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);
aircraft.TickMove( 1024 * aircraft.MovementSpeed, aircraft.Facing );
return this;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
public class Land : CancelableActivity
{
Target Target;
public Land(Target t) { Target = t; }
public override IActivity Tick(Actor self)
{
if (!Target.IsValid)
Cancel(self);
if (IsCanceled) return NextActivity;
var d = Target.CenterLocation - self.CenterLocation;
if (d.LengthSquared < 50) /* close enough */
return NextActivity;
var aircraft = self.Trait<Aircraft>();
if (aircraft.Altitude > 0)
--aircraft.Altitude;
var desiredFacing = Util.GetFacing(d, aircraft.Facing);
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);
aircraft.TickMove( 1024 * aircraft.MovementSpeed, aircraft.Facing );
return this;
}
}
}

View File

@@ -1,146 +1,146 @@
#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 System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Air
{
public class PlaneInfo : AircraftInfo
{
public override object Create( ActorInitializer init ) { return new Plane( init, this ); }
}
public class Plane : Aircraft, IIssueOrder, IResolveOrder, IOrderVoice, ITick
{
public IDisposable reservation;
public Plane( ActorInitializer init, PlaneInfo info ) : base( init, info ) { }
bool firstTick = true;
public void Tick(Actor self)
{
if (firstTick)
{
firstTick = false;
if (self.Trait<IMove>().Altitude == 0)
{
/* not spawning in the air, so try to assoc. with our afld. this is a hack. */
var res = self.World.FindUnits(self.CenterLocation, self.CenterLocation)
.Select( a => a.TraitOrDefault<Reservable>() ).FirstOrDefault( a => a != null );
if (res != null)
reservation = res.Reserve(self);
}
}
}
public IEnumerable<IOrderTargeter> Orders
{
get
{
yield return new EnterOrderTargeter<Building>( "Enter", 5, false, true,
target => AircraftCanEnter( target ), target => !Reservable.IsReserved( target ) );
yield return new AircraftMoveOrderTargeter();
}
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{
if( order.OrderID == "Enter" )
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
if( order.OrderID == "Move" )
return new Order( order.OrderID, self, queued ) { TargetLocation = Util.CellContaining( target.CenterLocation ) };
return null;
}
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "Move" || order.OrderString == "Enter") ? "Move" : null;
}
public void UnReserve()
{
if (reservation != null)
{
reservation.Dispose();
reservation = null;
}
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Move")
{
UnReserve();
var target = order.TargetLocation.Clamp(self.World.Map.Bounds);
self.SetTargetLine(Target.FromCell(target), Color.Green);
self.CancelActivity();
self.QueueActivity(Fly.ToCell(target));
}
else if (order.OrderString == "Enter")
{
if (Reservable.IsReserved(order.TargetActor)) return;
UnReserve();
var info = self.Info.Traits.Get<PlaneInfo>();
self.SetTargetLine(Target.FromOrder(order), Color.Green);
self.CancelActivity();
self.QueueActivity(new ReturnToBase(self, order.TargetActor));
self.QueueActivity(
info.RearmBuildings.Contains(order.TargetActor.Info.Name)
? (IActivity)new Rearm() : new Repair(order.TargetActor));
}
else if (order.OrderString == "Stop")
{
UnReserve();
self.CancelActivity();
}
else
{
// Game.Debug("Unreserve due to unhandled order: {0}".F(order.OrderString));
UnReserve();
}
}
}
class AircraftMoveOrderTargeter : IOrderTargeter
{
public string OrderID { get { return "Move"; } }
public int OrderPriority { get { return 4; } }
public bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceMove, bool forceQueued, ref string cursor)
{
return false;
}
public bool CanTargetLocation(Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, bool forceQueued, ref string cursor)
{
IsQueued = forceQueued;
cursor = self.World.Map.IsInMap(location) ? "move" : "move-blocked";
return true;
}
public bool IsQueued { get; protected set; }
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Air
{
public class PlaneInfo : AircraftInfo
{
public override object Create( ActorInitializer init ) { return new Plane( init, this ); }
}
public class Plane : Aircraft, IIssueOrder, IResolveOrder, IOrderVoice, ITick
{
public IDisposable reservation;
public Plane( ActorInitializer init, PlaneInfo info ) : base( init, info ) { }
bool firstTick = true;
public void Tick(Actor self)
{
if (firstTick)
{
firstTick = false;
if (self.Trait<IMove>().Altitude == 0)
{
/* not spawning in the air, so try to assoc. with our afld. this is a hack. */
var res = self.World.FindUnits(self.CenterLocation, self.CenterLocation)
.Select( a => a.TraitOrDefault<Reservable>() ).FirstOrDefault( a => a != null );
if (res != null)
reservation = res.Reserve(self);
}
}
}
public IEnumerable<IOrderTargeter> Orders
{
get
{
yield return new EnterOrderTargeter<Building>( "Enter", 5, false, true,
target => AircraftCanEnter( target ), target => !Reservable.IsReserved( target ) );
yield return new AircraftMoveOrderTargeter();
}
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{
if( order.OrderID == "Enter" )
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
if( order.OrderID == "Move" )
return new Order( order.OrderID, self, queued ) { TargetLocation = Util.CellContaining( target.CenterLocation ) };
return null;
}
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "Move" || order.OrderString == "Enter") ? "Move" : null;
}
public void UnReserve()
{
if (reservation != null)
{
reservation.Dispose();
reservation = null;
}
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Move")
{
UnReserve();
var target = order.TargetLocation.Clamp(self.World.Map.Bounds);
self.SetTargetLine(Target.FromCell(target), Color.Green);
self.CancelActivity();
self.QueueActivity(Fly.ToCell(target));
}
else if (order.OrderString == "Enter")
{
if (Reservable.IsReserved(order.TargetActor)) return;
UnReserve();
var info = self.Info.Traits.Get<PlaneInfo>();
self.SetTargetLine(Target.FromOrder(order), Color.Green);
self.CancelActivity();
self.QueueActivity(new ReturnToBase(self, order.TargetActor));
self.QueueActivity(
info.RearmBuildings.Contains(order.TargetActor.Info.Name)
? (IActivity)new Rearm() : new Repair(order.TargetActor));
}
else if (order.OrderString == "Stop")
{
UnReserve();
self.CancelActivity();
}
else
{
// Game.Debug("Unreserve due to unhandled order: {0}".F(order.OrderString));
UnReserve();
}
}
}
class AircraftMoveOrderTargeter : IOrderTargeter
{
public string OrderID { get { return "Move"; } }
public int OrderPriority { get { return 4; } }
public bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceMove, bool forceQueued, ref string cursor)
{
return false;
}
public bool CanTargetLocation(Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, bool forceQueued, ref string cursor)
{
IsQueued = forceQueued;
cursor = self.World.Map.IsInMap(location) ? "move" : "move-blocked";
return true;
}
public bool IsQueued { get; protected set; }
}
}

View File

@@ -1,53 +1,53 @@
#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 OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
class ReturnOnIdleInfo : TraitInfo<ReturnOnIdle> { }
// fly home or fly-off-map behavior for idle planes
class ReturnOnIdle : INotifyIdle
{
public void TickIdle(Actor self)
{
var altitude = self.Trait<Aircraft>().Altitude;
if (altitude == 0) return; // we're on the ground, let's stay there.
var airfield = ReturnToBase.ChooseAirfield(self);
if (airfield != null)
{
self.QueueActivity(new ReturnToBase(self, airfield));
self.QueueActivity(new Rearm());
}
else
{
//Game.Debug("Plane has nowhere to land; flying away");
self.QueueActivity(new FlyOffMap());
self.QueueActivity(new RemoveSelf());
}
}
}
class FlyAwayOnIdleInfo : TraitInfo<FlyAwayOnIdle> { }
class FlyAwayOnIdle : INotifyIdle
{
public void TickIdle(Actor self)
{
self.QueueActivity(new FlyOffMap());
self.QueueActivity(new RemoveSelf());
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
class ReturnOnIdleInfo : TraitInfo<ReturnOnIdle> { }
// fly home or fly-off-map behavior for idle planes
class ReturnOnIdle : INotifyIdle
{
public void TickIdle(Actor self)
{
var altitude = self.Trait<Aircraft>().Altitude;
if (altitude == 0) return; // we're on the ground, let's stay there.
var airfield = ReturnToBase.ChooseAirfield(self);
if (airfield != null)
{
self.QueueActivity(new ReturnToBase(self, airfield));
self.QueueActivity(new Rearm());
}
else
{
//Game.Debug("Plane has nowhere to land; flying away");
self.QueueActivity(new FlyOffMap());
self.QueueActivity(new RemoveSelf());
}
}
}
class FlyAwayOnIdleInfo : TraitInfo<FlyAwayOnIdle> { }
class FlyAwayOnIdle : INotifyIdle
{
public void TickIdle(Actor self)
{
self.QueueActivity(new FlyOffMap());
self.QueueActivity(new RemoveSelf());
}
}
}

View File

@@ -1,103 +1,103 @@
#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 System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
public class ReturnToBase : CancelableActivity
{
bool isCalculated;
Actor dest;
int2 w1, w2, w3; /* tangent points to turn circles */
public static Actor ChooseAirfield(Actor self)
{
return self.World.Queries.OwnedBy[self.Owner]
.Where(a => self.Info.Traits.Get<PlaneInfo>().RearmBuildings.Contains(a.Info.Name)
&& !Reservable.IsReserved(a))
.OrderBy(a => (a.CenterLocation - self.CenterLocation).LengthSquared)
.FirstOrDefault();
}
void Calculate(Actor self)
{
if (dest == null)
{
dest = ChooseAirfield(self);
}
var res = dest.TraitOrDefault<Reservable>();
if (res != null)
{
var plane = self.Trait<Plane>();
plane.UnReserve();
plane.reservation = res.Reserve(self);
}
var landPos = dest.CenterLocation;
var aircraft = self.Trait<Aircraft>();
var speed = .2f * aircraft.MovementSpeed;
var approachStart = landPos - new float2(aircraft.Altitude * speed, 0);
var turnRadius = (128f / self.Info.Traits.Get<AircraftInfo>().ROT) * speed / (float)Math.PI;
/* work out the center points */
var fwd = -float2.FromAngle(aircraft.Facing / 128f * (float)Math.PI);
var side = new float2(-fwd.Y, fwd.X); /* rotate */
var sideTowardBase = new[] { side, -side }
.OrderBy(a => float2.Dot(a, self.CenterLocation - approachStart))
.First();
var c1 = self.CenterLocation + turnRadius * sideTowardBase;
var c2 = approachStart + new float2(0,
turnRadius * Math.Sign(self.CenterLocation.Y - approachStart.Y)); // above or below start point
/* work out tangent points */
var d = c2 - c1;
var e = (turnRadius / d.Length) * d;
var f = new float2(-e.Y, e.X); /* rotate */
/* todo: support internal tangents, too! */
if (f.X > 0) f = -f;
w1 = (c1 + f).ToInt2();
w2 = (c2 + f).ToInt2();
w3 = (approachStart).ToInt2();
isCalculated = true;
}
public ReturnToBase(Actor self, Actor dest)
{
this.dest = dest;
}
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (!isCalculated)
Calculate(self);
return Util.SequenceActivities(
Fly.ToPx(w1),
Fly.ToPx(w2),
Fly.ToPx(w3),
new Land(Target.FromActor(dest)),
NextActivity);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Air
{
public class ReturnToBase : CancelableActivity
{
bool isCalculated;
Actor dest;
int2 w1, w2, w3; /* tangent points to turn circles */
public static Actor ChooseAirfield(Actor self)
{
return self.World.Queries.OwnedBy[self.Owner]
.Where(a => self.Info.Traits.Get<PlaneInfo>().RearmBuildings.Contains(a.Info.Name)
&& !Reservable.IsReserved(a))
.OrderBy(a => (a.CenterLocation - self.CenterLocation).LengthSquared)
.FirstOrDefault();
}
void Calculate(Actor self)
{
if (dest == null)
{
dest = ChooseAirfield(self);
}
var res = dest.TraitOrDefault<Reservable>();
if (res != null)
{
var plane = self.Trait<Plane>();
plane.UnReserve();
plane.reservation = res.Reserve(self);
}
var landPos = dest.CenterLocation;
var aircraft = self.Trait<Aircraft>();
var speed = .2f * aircraft.MovementSpeed;
var approachStart = landPos - new float2(aircraft.Altitude * speed, 0);
var turnRadius = (128f / self.Info.Traits.Get<AircraftInfo>().ROT) * speed / (float)Math.PI;
/* work out the center points */
var fwd = -float2.FromAngle(aircraft.Facing / 128f * (float)Math.PI);
var side = new float2(-fwd.Y, fwd.X); /* rotate */
var sideTowardBase = new[] { side, -side }
.OrderBy(a => float2.Dot(a, self.CenterLocation - approachStart))
.First();
var c1 = self.CenterLocation + turnRadius * sideTowardBase;
var c2 = approachStart + new float2(0,
turnRadius * Math.Sign(self.CenterLocation.Y - approachStart.Y)); // above or below start point
/* work out tangent points */
var d = c2 - c1;
var e = (turnRadius / d.Length) * d;
var f = new float2(-e.Y, e.X); /* rotate */
/* todo: support internal tangents, too! */
if (f.X > 0) f = -f;
w1 = (c1 + f).ToInt2();
w2 = (c2 + f).ToInt2();
w3 = (approachStart).ToInt2();
isCalculated = true;
}
public ReturnToBase(Actor self, Actor dest)
{
this.dest = dest;
}
public override IActivity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (!isCalculated)
Calculate(self);
return Util.SequenceActivities(
Fly.ToPx(w1),
Fly.ToPx(w2),
Fly.ToPx(w3),
new Land(Target.FromActor(dest)),
NextActivity);
}
}
}

View File

@@ -1,39 +1,39 @@
#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.Drawing;
using OpenRA.Graphics;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Air
{
public class TargetableAircraftInfo : TargetableUnitInfo, ITraitPrerequisite<AircraftInfo>
{
public readonly string[] GroundedTargetTypes = { };
public override object Create(ActorInitializer init) { return new TargetableAircraft(init.self, this); }
}
public class TargetableAircraft : TargetableUnit<TargetableAircraftInfo>
{
Aircraft Aircraft;
public TargetableAircraft(Actor self, TargetableAircraftInfo info)
: base(self, info)
{
Aircraft = self.Trait<Aircraft>();
}
public override string[] TargetTypes
{
get { return (Aircraft.Altitude > 0) ? info.TargetTypes
: info.GroundedTargetTypes; }
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Drawing;
using OpenRA.Graphics;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Air
{
public class TargetableAircraftInfo : TargetableUnitInfo, ITraitPrerequisite<AircraftInfo>
{
public readonly string[] GroundedTargetTypes = { };
public override object Create(ActorInitializer init) { return new TargetableAircraft(init.self, this); }
}
public class TargetableAircraft : TargetableUnit<TargetableAircraftInfo>
{
Aircraft Aircraft;
public TargetableAircraft(Actor self, TargetableAircraftInfo info)
: base(self, info)
{
Aircraft = self.Trait<Aircraft>();
}
public override string[] TargetTypes
{
get { return (Aircraft.Altitude > 0) ? info.TargetTypes
: info.GroundedTargetTypes; }
}
}
}

View File

@@ -1,52 +1,52 @@
#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.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class AppearsOnRadarInfo : TraitInfo<AppearsOnRadar>
{
public readonly bool UseLocation = false;
}
public class AppearsOnRadar : IRadarSignature
{
AppearsOnRadarInfo info;
IOccupySpace Space;
public IEnumerable<int2> RadarSignatureCells(Actor self)
{
if (info == null)
info = self.Info.Traits.Get<AppearsOnRadarInfo>();
if (info.UseLocation)
return new int2[] { self.Location };
else
{
if (Space == null)
Space = self.Trait<IOccupySpace>();
return Space.OccupiedCells().Select(c => c.First);
}
}
public Color RadarSignatureColor(Actor self)
{
var mod = self.TraitsImplementing<IRadarColorModifier>().FirstOrDefault();
if (mod != null)
return mod.RadarColorOverride(self);
return self.Owner.ColorRamp.GetColor(0);
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class AppearsOnRadarInfo : TraitInfo<AppearsOnRadar>
{
public readonly bool UseLocation = false;
}
public class AppearsOnRadar : IRadarSignature
{
AppearsOnRadarInfo info;
IOccupySpace Space;
public IEnumerable<int2> RadarSignatureCells(Actor self)
{
if (info == null)
info = self.Info.Traits.Get<AppearsOnRadarInfo>();
if (info.UseLocation)
return new int2[] { self.Location };
else
{
if (Space == null)
Space = self.Trait<IOccupySpace>();
return Space.OccupiedCells().Select(c => c.First);
}
}
public Color RadarSignatureColor(Actor self)
{
var mod = self.TraitsImplementing<IRadarColorModifier>().FirstOrDefault();
if (mod != null)
return mod.RadarColorOverride(self);
return self.Owner.ColorRamp.GetColor(0);
}
}
}

View File

@@ -1,284 +1,284 @@
#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 System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public abstract class AttackBaseInfo : ITraitInfo
{
[WeaponReference]
public readonly string PrimaryWeapon = null;
[WeaponReference]
public readonly string SecondaryWeapon = null;
public readonly int Recoil = 0;
public readonly int[] PrimaryLocalOffset = { };
public readonly int[] SecondaryLocalOffset = { };
public readonly int[] PrimaryOffset = { 0, 0 };
public readonly int[] SecondaryOffset = null;
public readonly bool MuzzleFlash = false;
public readonly int FireDelay = 0;
public readonly bool AlignIdleTurrets = false;
public readonly bool CanAttackGround = true;
public readonly float ScanTimeAverage = 2f;
public readonly float ScanTimeSpread = .5f;
public abstract object Create(ActorInitializer init);
public float GetMaximumRange()
{
var priRange = PrimaryWeapon != null ? Rules.Weapons[PrimaryWeapon.ToLowerInvariant()].Range : 0;
var secRange = SecondaryWeapon != null ? Rules.Weapons[SecondaryWeapon.ToLowerInvariant()].Range : 0;
return Math.Max(priRange, secRange);
}
}
public abstract class AttackBase : IIssueOrder, IResolveOrder, ITick, IExplodeModifier, IOrderVoice, ISync
{
[Sync]
int nextScanTime = 0;
public bool IsAttacking { get; internal set; }
public List<Weapon> Weapons = new List<Weapon>();
public List<Turret> Turrets = new List<Turret>();
readonly Actor self;
public AttackBase(Actor self)
{
this.self = self;
var info = self.Info.Traits.Get<AttackBaseInfo>();
Turrets.Add(new Turret(info.PrimaryOffset));
if (info.SecondaryOffset != null)
Turrets.Add(new Turret(info.SecondaryOffset));
if (info.PrimaryWeapon != null)
Weapons.Add(new Weapon(info.PrimaryWeapon,
Turrets[0], info.PrimaryLocalOffset));
if (info.SecondaryWeapon != null)
Weapons.Add(new Weapon(info.SecondaryWeapon,
info.SecondaryOffset != null ? Turrets[1] : Turrets[0], info.SecondaryLocalOffset));
}
protected virtual bool CanAttack(Actor self, Target target)
{
if (!target.IsValid) return false;
if (Weapons.All(w => w.IsReloading)) return false;
if (self.TraitsImplementing<IDisable>().Any(d => d.Disabled)) return false;
if (target.IsActor && target.Actor.HasTrait<ITargetable>() &&
!target.Actor.Trait<ITargetable>().TargetableBy(target.Actor,self))
return false;
return true;
}
public bool ShouldExplode(Actor self) { return !IsReloading(); }
public bool IsReloading() { return Weapons.Any(w => w.IsReloading); }
List<Pair<int, Action>> delayedActions = new List<Pair<int, Action>>();
public virtual void Tick(Actor self)
{
--nextScanTime;
foreach (var w in Weapons)
w.Tick();
for (var i = 0; i < delayedActions.Count; i++)
{
var x = delayedActions[i];
if (--x.First <= 0)
x.Second();
delayedActions[i] = x;
}
delayedActions.RemoveAll(a => a.First <= 0);
}
internal void ScheduleDelayedAction(int t, Action a)
{
if (t > 0)
delayedActions.Add(Pair.New(t, a));
else
a();
}
public virtual void DoAttack(Actor self, Target target)
{
if( !CanAttack( self, target ) ) return;
var move = self.TraitOrDefault<IMove>();
var facing = self.TraitOrDefault<IFacing>();
foreach (var w in Weapons)
w.CheckFire(self, this, move, facing, target);
}
public virtual int FireDelay( Actor self, Target target, AttackBaseInfo info )
{
return info.FireDelay;
}
bool IsHeal { get { return Weapons[ 0 ].Info.Warheads[ 0 ].Damage < 0; } }
public IEnumerable<IOrderTargeter> Orders
{
get { yield return new AttackOrderTargeter( "Attack", 6, IsHeal ); }
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{
if( order is AttackOrderTargeter )
{
if( target.IsActor )
return new Order("Attack", self, queued) { TargetActor = target.Actor };
else
return new Order( "Attack", self, queued ) { TargetLocation = Util.CellContaining( target.CenterLocation ) };
}
return null;
}
public virtual void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Attack" || order.OrderString == "AttackHold")
{
var target = Target.FromOrder(order);
self.SetTargetLine(target, Color.Red);
AttackTarget(target, order.Queued, order.OrderString == "Attack");
}
else
{
/* hack */
if (self.HasTrait<Turreted>() && self.Info.Traits.Get<AttackBaseInfo>().AlignIdleTurrets)
self.Trait<Turreted>().desiredFacing = null;
}
}
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "Attack" || order.OrderString == "AttackHold") ? "Attack" : null;
}
public abstract IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove);
public bool HasAnyValidWeapons(Target t) { return Weapons.Any(w => w.IsValidAgainst(self.World, t)); }
public float GetMaximumRange() { return Weapons.Max(w => w.Info.Range); }
public Weapon ChooseWeaponForTarget(Target t) { return Weapons.FirstOrDefault(w => w.IsValidAgainst(self.World, t)); }
public void AttackTarget( Target target, bool queued, bool allowMove )
{
if( !target.IsValid ) return;
self.QueueActivity(queued, GetAttackActivity(self, target, allowMove));
}
public void ScanAndAttack(Actor self, bool allowMovement, bool holdStill)
{
var targetActor = ScanForTarget(self, null);
if (targetActor != null)
AttackTarget(Target.FromActor(targetActor), false, allowMovement && !holdStill);
}
public Actor ScanForTarget(Actor self, Actor currentTarget)
{
var range = GetMaximumRange();
if (self.IsIdle || currentTarget == null || !Combat.IsInRange(self.CenterLocation, range, currentTarget))
if(nextScanTime <= 0)
return ChooseTarget(self, range);
return currentTarget;
}
public void ScanAndAttack(Actor self, bool allowMovement)
{
ScanAndAttack(self, allowMovement, false);
}
Actor ChooseTarget(Actor self, float range)
{
var info = self.Info.Traits.Get<AttackBaseInfo>();
nextScanTime = (int)(25 * (info.ScanTimeAverage +
(self.World.SharedRandom.NextDouble() * 2 - 1) * info.ScanTimeSpread));
var inRange = self.World.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range);
return inRange
.Where(a => a.Owner != null && self.Owner.Stances[a.Owner] == Stance.Enemy)
.Where(a => !a.HasTrait<AutoTargetIgnore>())
.Where(a => HasAnyValidWeapons(Target.FromActor(a)))
.OrderBy(a => (a.CenterLocation - self.CenterLocation).LengthSquared)
.FirstOrDefault();
}
class AttackOrderTargeter : IOrderTargeter
{
readonly bool isHeal;
public AttackOrderTargeter( string order, int priority, bool isHeal )
{
this.OrderID = order;
this.OrderPriority = priority;
this.isHeal = isHeal;
}
public string OrderID { get; private set; }
public int OrderPriority { get; private set; }
public bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceMove, bool forceQueued, ref string cursor)
{
IsQueued = forceQueued;
cursor = isHeal ? "heal" : "attack";
if( self == target ) return false;
if( !self.Trait<AttackBase>().HasAnyValidWeapons( Target.FromActor( target ) ) ) return false;
var playerRelationship = self.Owner.Stances[ target.Owner ];
if( isHeal )
return playerRelationship == Stance.Ally || forceAttack;
else
return playerRelationship == Stance.Enemy || forceAttack;
}
public bool CanTargetLocation(Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, bool forceQueued, ref string cursor)
{
if (!self.World.Map.IsInMap(location))
return false;
IsQueued = forceQueued;
cursor = isHeal ? "heal" : "attack";
if( isHeal ) return false;
if( !self.Trait<AttackBase>().HasAnyValidWeapons( Target.FromCell( location ) ) ) return false;
if( forceAttack )
if( self.Info.Traits.Get<AttackBaseInfo>().CanAttackGround )
return true;
return false;
}
public bool IsQueued { get; protected set; }
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public abstract class AttackBaseInfo : ITraitInfo
{
[WeaponReference]
public readonly string PrimaryWeapon = null;
[WeaponReference]
public readonly string SecondaryWeapon = null;
public readonly int Recoil = 0;
public readonly int[] PrimaryLocalOffset = { };
public readonly int[] SecondaryLocalOffset = { };
public readonly int[] PrimaryOffset = { 0, 0 };
public readonly int[] SecondaryOffset = null;
public readonly bool MuzzleFlash = false;
public readonly int FireDelay = 0;
public readonly bool AlignIdleTurrets = false;
public readonly bool CanAttackGround = true;
public readonly float ScanTimeAverage = 2f;
public readonly float ScanTimeSpread = .5f;
public abstract object Create(ActorInitializer init);
public float GetMaximumRange()
{
var priRange = PrimaryWeapon != null ? Rules.Weapons[PrimaryWeapon.ToLowerInvariant()].Range : 0;
var secRange = SecondaryWeapon != null ? Rules.Weapons[SecondaryWeapon.ToLowerInvariant()].Range : 0;
return Math.Max(priRange, secRange);
}
}
}
}
public abstract class AttackBase : IIssueOrder, IResolveOrder, ITick, IExplodeModifier, IOrderVoice, ISync
{
[Sync]
int nextScanTime = 0;
public bool IsAttacking { get; internal set; }
public List<Weapon> Weapons = new List<Weapon>();
public List<Turret> Turrets = new List<Turret>();
readonly Actor self;
public AttackBase(Actor self)
{
this.self = self;
var info = self.Info.Traits.Get<AttackBaseInfo>();
Turrets.Add(new Turret(info.PrimaryOffset));
if (info.SecondaryOffset != null)
Turrets.Add(new Turret(info.SecondaryOffset));
if (info.PrimaryWeapon != null)
Weapons.Add(new Weapon(info.PrimaryWeapon,
Turrets[0], info.PrimaryLocalOffset));
if (info.SecondaryWeapon != null)
Weapons.Add(new Weapon(info.SecondaryWeapon,
info.SecondaryOffset != null ? Turrets[1] : Turrets[0], info.SecondaryLocalOffset));
}
protected virtual bool CanAttack(Actor self, Target target)
{
if (!target.IsValid) return false;
if (Weapons.All(w => w.IsReloading)) return false;
if (self.TraitsImplementing<IDisable>().Any(d => d.Disabled)) return false;
if (target.IsActor && target.Actor.HasTrait<ITargetable>() &&
!target.Actor.Trait<ITargetable>().TargetableBy(target.Actor,self))
return false;
return true;
}
public bool ShouldExplode(Actor self) { return !IsReloading(); }
public bool IsReloading() { return Weapons.Any(w => w.IsReloading); }
List<Pair<int, Action>> delayedActions = new List<Pair<int, Action>>();
public virtual void Tick(Actor self)
{
--nextScanTime;
foreach (var w in Weapons)
w.Tick();
for (var i = 0; i < delayedActions.Count; i++)
{
var x = delayedActions[i];
if (--x.First <= 0)
x.Second();
delayedActions[i] = x;
}
delayedActions.RemoveAll(a => a.First <= 0);
}
internal void ScheduleDelayedAction(int t, Action a)
{
if (t > 0)
delayedActions.Add(Pair.New(t, a));
else
a();
}
public virtual void DoAttack(Actor self, Target target)
{
if( !CanAttack( self, target ) ) return;
var move = self.TraitOrDefault<IMove>();
var facing = self.TraitOrDefault<IFacing>();
foreach (var w in Weapons)
w.CheckFire(self, this, move, facing, target);
}
public virtual int FireDelay( Actor self, Target target, AttackBaseInfo info )
{
return info.FireDelay;
}
bool IsHeal { get { return Weapons[ 0 ].Info.Warheads[ 0 ].Damage < 0; } }
public IEnumerable<IOrderTargeter> Orders
{
get { yield return new AttackOrderTargeter( "Attack", 6, IsHeal ); }
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{
if( order is AttackOrderTargeter )
{
if( target.IsActor )
return new Order("Attack", self, queued) { TargetActor = target.Actor };
else
return new Order( "Attack", self, queued ) { TargetLocation = Util.CellContaining( target.CenterLocation ) };
}
return null;
}
public virtual void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Attack" || order.OrderString == "AttackHold")
{
var target = Target.FromOrder(order);
self.SetTargetLine(target, Color.Red);
AttackTarget(target, order.Queued, order.OrderString == "Attack");
}
else
{
/* hack */
if (self.HasTrait<Turreted>() && self.Info.Traits.Get<AttackBaseInfo>().AlignIdleTurrets)
self.Trait<Turreted>().desiredFacing = null;
}
}
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "Attack" || order.OrderString == "AttackHold") ? "Attack" : null;
}
public abstract IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove);
public bool HasAnyValidWeapons(Target t) { return Weapons.Any(w => w.IsValidAgainst(self.World, t)); }
public float GetMaximumRange() { return Weapons.Max(w => w.Info.Range); }
public Weapon ChooseWeaponForTarget(Target t) { return Weapons.FirstOrDefault(w => w.IsValidAgainst(self.World, t)); }
public void AttackTarget( Target target, bool queued, bool allowMove )
{
if( !target.IsValid ) return;
self.QueueActivity(queued, GetAttackActivity(self, target, allowMove));
}
public void ScanAndAttack(Actor self, bool allowMovement, bool holdStill)
{
var targetActor = ScanForTarget(self, null);
if (targetActor != null)
AttackTarget(Target.FromActor(targetActor), false, allowMovement && !holdStill);
}
public Actor ScanForTarget(Actor self, Actor currentTarget)
{
var range = GetMaximumRange();
if (self.IsIdle || currentTarget == null || !Combat.IsInRange(self.CenterLocation, range, currentTarget))
if(nextScanTime <= 0)
return ChooseTarget(self, range);
return currentTarget;
}
public void ScanAndAttack(Actor self, bool allowMovement)
{
ScanAndAttack(self, allowMovement, false);
}
Actor ChooseTarget(Actor self, float range)
{
var info = self.Info.Traits.Get<AttackBaseInfo>();
nextScanTime = (int)(25 * (info.ScanTimeAverage +
(self.World.SharedRandom.NextDouble() * 2 - 1) * info.ScanTimeSpread));
var inRange = self.World.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range);
return inRange
.Where(a => a.Owner != null && self.Owner.Stances[a.Owner] == Stance.Enemy)
.Where(a => !a.HasTrait<AutoTargetIgnore>())
.Where(a => HasAnyValidWeapons(Target.FromActor(a)))
.OrderBy(a => (a.CenterLocation - self.CenterLocation).LengthSquared)
.FirstOrDefault();
}
class AttackOrderTargeter : IOrderTargeter
{
readonly bool isHeal;
public AttackOrderTargeter( string order, int priority, bool isHeal )
{
this.OrderID = order;
this.OrderPriority = priority;
this.isHeal = isHeal;
}
public string OrderID { get; private set; }
public int OrderPriority { get; private set; }
public bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceMove, bool forceQueued, ref string cursor)
{
IsQueued = forceQueued;
cursor = isHeal ? "heal" : "attack";
if( self == target ) return false;
if( !self.Trait<AttackBase>().HasAnyValidWeapons( Target.FromActor( target ) ) ) return false;
var playerRelationship = self.Owner.Stances[ target.Owner ];
if( isHeal )
return playerRelationship == Stance.Ally || forceAttack;
else
return playerRelationship == Stance.Enemy || forceAttack;
}
public bool CanTargetLocation(Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, bool forceQueued, ref string cursor)
{
if (!self.World.Map.IsInMap(location))
return false;
IsQueued = forceQueued;
cursor = isHeal ? "heal" : "attack";
if( isHeal ) return false;
if( !self.Trait<AttackBase>().HasAnyValidWeapons( Target.FromCell( location ) ) ) return false;
if( forceAttack )
if( self.Info.Traits.Get<AttackBaseInfo>().CanAttackGround )
return true;
return false;
}
public bool IsQueued { get; protected set; }
}
}
}

View File

@@ -1,51 +1,51 @@
#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.Traits;
namespace OpenRA.Mods.RA
{
public class AttackFrontalInfo : AttackBaseInfo
{
public readonly int FacingTolerance = 1;
public override object Create( ActorInitializer init ) { return new AttackFrontal( init.self, this ); }
}
public class AttackFrontal : AttackBase
{
readonly AttackFrontalInfo info;
public AttackFrontal(Actor self, AttackFrontalInfo info)
: base( self ) { this.info = info; }
protected override bool CanAttack( Actor self, Target target )
{
if( !base.CanAttack( self, target ) )
return false;
var facing = self.Trait<IFacing>().Facing;
var facingToTarget = Util.GetFacing(target.CenterLocation - self.CenterLocation, facing);
if( Math.Abs( facingToTarget - facing ) % 256 > info.FacingTolerance )
return false;
return true;
}
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
var weapon = ChooseWeaponForTarget(newTarget);
if( weapon == null )
return null;
return new Activities.Attack(newTarget, Math.Max(0, (int)weapon.Info.Range), allowMove);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class AttackFrontalInfo : AttackBaseInfo
{
public readonly int FacingTolerance = 1;
public override object Create( ActorInitializer init ) { return new AttackFrontal( init.self, this ); }
}
public class AttackFrontal : AttackBase
{
readonly AttackFrontalInfo info;
public AttackFrontal(Actor self, AttackFrontalInfo info)
: base( self ) { this.info = info; }
protected override bool CanAttack( Actor self, Target target )
{
if( !base.CanAttack( self, target ) )
return false;
var facing = self.Trait<IFacing>().Facing;
var facingToTarget = Util.GetFacing(target.CenterLocation - self.CenterLocation, facing);
if( Math.Abs( facingToTarget - facing ) % 256 > info.FacingTolerance )
return false;
return true;
}
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
var weapon = ChooseWeaponForTarget(newTarget);
if( weapon == null )
return null;
return new Activities.Attack(newTarget, Math.Max(0, (int)weapon.Info.Range), allowMove);
}
}
}

View File

@@ -1,48 +1,48 @@
#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.Mods.RA.Activities;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class AttackLeapInfo : AttackFrontalInfo
{
public override object Create(ActorInitializer init) { return new AttackLeap(init.self, this); }
}
class AttackLeap : AttackFrontal
{
internal bool IsLeaping;
public AttackLeap(Actor self, AttackLeapInfo info)
: base(self, info) {}
public override void DoAttack(Actor self, Target target)
{
if( !CanAttack( self, target ) ) return;
var weapon = Weapons[0].Info;
if( !Combat.IsInRange( self.CenterLocation, weapon.Range, target ) ) return;
self.CancelActivity();
self.QueueActivity(new Leap(self, target));
}
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
var weapon = ChooseWeaponForTarget(newTarget);
if( weapon == null )
return null;
return new Activities.Attack(newTarget, Math.Max(0, (int)weapon.Info.Range), allowMove);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class AttackLeapInfo : AttackFrontalInfo
{
public override object Create(ActorInitializer init) { return new AttackLeap(init.self, this); }
}
class AttackLeap : AttackFrontal
{
internal bool IsLeaping;
public AttackLeap(Actor self, AttackLeapInfo info)
: base(self, info) {}
public override void DoAttack(Actor self, Target target)
{
if( !CanAttack( self, target ) ) return;
var weapon = Weapons[0].Info;
if( !Combat.IsInRange( self.CenterLocation, weapon.Range, target ) ) return;
self.CancelActivity();
self.QueueActivity(new Leap(self, target));
}
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
var weapon = ChooseWeaponForTarget(newTarget);
if( weapon == null )
return null;
return new Activities.Attack(newTarget, Math.Max(0, (int)weapon.Info.Range), allowMove);
}
}
}

View File

@@ -1,34 +1,34 @@
#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.Traits;
namespace OpenRA.Mods.RA
{
public class AttackMedicInfo : AttackFrontalInfo
{
public override object Create( ActorInitializer init ) { return new AttackMedic( init.self, this ); }
}
public class AttackMedic : AttackFrontal
{
public AttackMedic(Actor self, AttackMedicInfo info)
: base( self, info ) {}
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
var weapon = ChooseWeaponForTarget(newTarget);
if( weapon == null )
return null;
return new Activities.Heal(newTarget, Math.Max(0, (int)weapon.Info.Range), allowMove);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class AttackMedicInfo : AttackFrontalInfo
{
public override object Create( ActorInitializer init ) { return new AttackMedic( init.self, this ); }
}
public class AttackMedic : AttackFrontal
{
public AttackMedic(Actor self, AttackMedicInfo info)
: base( self, info ) {}
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
var weapon = ChooseWeaponForTarget(newTarget);
if( weapon == null )
return null;
return new Activities.Heal(newTarget, Math.Max(0, (int)weapon.Info.Range), allowMove);
}
}
}

View File

@@ -1,101 +1,101 @@
#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.Drawing;
using OpenRA.Effects;
using OpenRA.Mods.RA.Move;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA
{
class AttackMoveInfo : ITraitInfo
{
public readonly bool JustMove = false;
public object Create(ActorInitializer init) { return new AttackMove(init.self, this); }
}
class AttackMove : IResolveOrder, IOrderVoice, INotifyIdle, ISync
{
[Sync] public int2 _targetLocation { get { return TargetLocation.HasValue ? TargetLocation.Value : int2.Zero; } }
public int2? TargetLocation = null;
readonly Mobile mobile;
readonly AttackMoveInfo Info;
public AttackMove(Actor self, AttackMoveInfo info)
{
Info = info;
mobile = self.Trait<Mobile>();
}
public string VoicePhraseForOrder(Actor self, Order order)
{
if (order.OrderString == "AttackMove")
return "AttackMove";
return null;
}
void Activate(Actor self)
{
self.CancelActivity();
self.QueueActivity(new AttackMoveActivity(mobile.MoveTo(TargetLocation.Value, 1)));
self.SetTargetLine(Target.FromCell(TargetLocation.Value), Color.Red);
}
public void TickIdle(Actor self)
{
if (TargetLocation.HasValue)
Activate(self);
}
public void ResolveOrder(Actor self, Order order)
{
TargetLocation = null;
if (order.OrderString == "AttackMove")
{
if (Info.JustMove)
mobile.ResolveOrder(self, new Order("Move", order));
else
{
TargetLocation = mobile.NearestMoveableCell(order.TargetLocation);
Activate(self);
}
}
}
class AttackMoveActivity : CancelableActivity
{
IActivity inner;
public AttackMoveActivity( IActivity inner ) { this.inner = inner; }
public override IActivity Tick( Actor self )
{
self.Trait<AttackBase>().ScanAndAttack(self, true);
if( inner == null )
return NextActivity;
inner = Util.RunActivity( self, inner );
return this;
}
protected override bool OnCancel( Actor self )
{
if( inner != null )
inner.Cancel( self );
return base.OnCancel( self );
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Drawing;
using OpenRA.Effects;
using OpenRA.Mods.RA.Move;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA
{
class AttackMoveInfo : ITraitInfo
{
public readonly bool JustMove = false;
public object Create(ActorInitializer init) { return new AttackMove(init.self, this); }
}
class AttackMove : IResolveOrder, IOrderVoice, INotifyIdle, ISync
{
[Sync] public int2 _targetLocation { get { return TargetLocation.HasValue ? TargetLocation.Value : int2.Zero; } }
public int2? TargetLocation = null;
readonly Mobile mobile;
readonly AttackMoveInfo Info;
public AttackMove(Actor self, AttackMoveInfo info)
{
Info = info;
mobile = self.Trait<Mobile>();
}
public string VoicePhraseForOrder(Actor self, Order order)
{
if (order.OrderString == "AttackMove")
return "AttackMove";
return null;
}
void Activate(Actor self)
{
self.CancelActivity();
self.QueueActivity(new AttackMoveActivity(mobile.MoveTo(TargetLocation.Value, 1)));
self.SetTargetLine(Target.FromCell(TargetLocation.Value), Color.Red);
}
public void TickIdle(Actor self)
{
if (TargetLocation.HasValue)
Activate(self);
}
public void ResolveOrder(Actor self, Order order)
{
TargetLocation = null;
if (order.OrderString == "AttackMove")
{
if (Info.JustMove)
mobile.ResolveOrder(self, new Order("Move", order));
else
{
TargetLocation = mobile.NearestMoveableCell(order.TargetLocation);
Activate(self);
}
}
}
class AttackMoveActivity : CancelableActivity
{
IActivity inner;
public AttackMoveActivity( IActivity inner ) { this.inner = inner; }
public override IActivity Tick( Actor self )
{
self.Trait<AttackBase>().ScanAndAttack(self, true);
if( inner == null )
return NextActivity;
inner = Util.RunActivity( self, inner );
return this;
}
protected override bool OnCancel( Actor self )
{
if( inner != null )
inner.Cancel( self );
return base.OnCancel( self );
}
}
}
}

View File

@@ -1,55 +1,55 @@
#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 OpenRA.Mods.RA.Buildings;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA
{
class AttackOmniInfo : AttackBaseInfo
{
public override object Create(ActorInitializer init) { return new AttackOmni(init.self); }
}
class AttackOmni : AttackBase, INotifyBuildComplete
{
bool buildComplete = false;
public void BuildingComplete(Actor self) { buildComplete = true; }
public AttackOmni(Actor self) : base(self) { }
protected override bool CanAttack( Actor self, Target target )
{
var isBuilding = ( self.HasTrait<Building>() && !buildComplete );
return base.CanAttack( self, target ) && !isBuilding;
}
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
return new SetTarget( newTarget );
}
class SetTarget : CancelableActivity
{
readonly Target target;
public SetTarget( Target target ) { this.target = target; }
public override IActivity Tick( Actor self )
{
if( IsCanceled || !target.IsValid )
return NextActivity;
self.Trait<AttackOmni>().DoAttack(self, target);
return this;
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Mods.RA.Buildings;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA
{
class AttackOmniInfo : AttackBaseInfo
{
public override object Create(ActorInitializer init) { return new AttackOmni(init.self); }
}
class AttackOmni : AttackBase, INotifyBuildComplete
{
bool buildComplete = false;
public void BuildingComplete(Actor self) { buildComplete = true; }
public AttackOmni(Actor self) : base(self) { }
protected override bool CanAttack( Actor self, Target target )
{
var isBuilding = ( self.HasTrait<Building>() && !buildComplete );
return base.CanAttack( self, target ) && !isBuilding;
}
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
return new SetTarget( newTarget );
}
class SetTarget : CancelableActivity
{
readonly Target target;
public SetTarget( Target target ) { this.target = target; }
public override IActivity Tick( Actor self )
{
if( IsCanceled || !target.IsValid )
return NextActivity;
self.Trait<AttackOmni>().DoAttack(self, target);
return this;
}
}
}
}

View File

@@ -1,91 +1,91 @@
#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 OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA
{
class AttackTeslaInfo : AttackOmniInfo
{
public readonly int MaxCharges = 3;
public readonly int ReloadTime = 120;
public override object Create(ActorInitializer init) { return new AttackTesla(init.self); }
}
class AttackTesla : AttackOmni, ITick, INotifyAttack
{
int charges;
int timeToRecharge;
public AttackTesla( Actor self )
: base( self )
{
charges = self.Info.Traits.Get<AttackTeslaInfo>().MaxCharges;
}
public override void Tick( Actor self )
{
if( --timeToRecharge <= 0 )
charges = self.Info.Traits.Get<AttackTeslaInfo>().MaxCharges;
base.Tick( self );
}
public void Attacking(Actor self, Target target)
{
--charges;
timeToRecharge = self.Info.Traits.Get<AttackTeslaInfo>().ReloadTime;
}
public override IActivity GetAttackActivity( Actor self, Target newTarget, bool allowMove )
{
return new TeslaAttack( newTarget );
}
class TeslaAttack : CancelableActivity
{
readonly Target target;
public TeslaAttack( Target target ) { this.target = target; }
public override IActivity Tick( Actor self )
{
if( IsCanceled || !target.IsValid ) return NextActivity;
var attack = self.Trait<AttackTesla>();
if( attack.charges == 0 || !attack.CanAttack( self, target ) )
return this;
self.Trait<RenderBuildingCharge>().PlayCharge(self);
return Util.SequenceActivities( new Wait( 8 ), new TeslaZap( target ), this );
}
}
class TeslaZap : CancelableActivity
{
readonly Target target;
public TeslaZap( Target target ) { this.target = target; }
public override IActivity Tick( Actor self )
{
if( IsCanceled || !target.IsValid ) return NextActivity;
var attack = self.Trait<AttackTesla>();
if( attack.charges == 0 ) return NextActivity;
attack.DoAttack( self, target );
return Util.SequenceActivities( new Wait( 3 ), this );
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA
{
class AttackTeslaInfo : AttackOmniInfo
{
public readonly int MaxCharges = 3;
public readonly int ReloadTime = 120;
public override object Create(ActorInitializer init) { return new AttackTesla(init.self); }
}
class AttackTesla : AttackOmni, ITick, INotifyAttack
{
int charges;
int timeToRecharge;
public AttackTesla( Actor self )
: base( self )
{
charges = self.Info.Traits.Get<AttackTeslaInfo>().MaxCharges;
}
public override void Tick( Actor self )
{
if( --timeToRecharge <= 0 )
charges = self.Info.Traits.Get<AttackTeslaInfo>().MaxCharges;
base.Tick( self );
}
public void Attacking(Actor self, Target target)
{
--charges;
timeToRecharge = self.Info.Traits.Get<AttackTeslaInfo>().ReloadTime;
}
public override IActivity GetAttackActivity( Actor self, Target newTarget, bool allowMove )
{
return new TeslaAttack( newTarget );
}
class TeslaAttack : CancelableActivity
{
readonly Target target;
public TeslaAttack( Target target ) { this.target = target; }
public override IActivity Tick( Actor self )
{
if( IsCanceled || !target.IsValid ) return NextActivity;
var attack = self.Trait<AttackTesla>();
if( attack.charges == 0 || !attack.CanAttack( self, target ) )
return this;
self.Trait<RenderBuildingCharge>().PlayCharge(self);
return Util.SequenceActivities( new Wait( 8 ), new TeslaZap( target ), this );
}
}
class TeslaZap : CancelableActivity
{
readonly Target target;
public TeslaZap( Target target ) { this.target = target; }
public override IActivity Tick( Actor self )
{
if( IsCanceled || !target.IsValid ) return NextActivity;
var attack = self.Trait<AttackTesla>();
if( attack.charges == 0 ) return NextActivity;
attack.DoAttack( self, target );
return Util.SequenceActivities( new Wait( 3 ), this );
}
}
}
}

View File

@@ -1,95 +1,95 @@
#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 System.Linq;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Move;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA
{
class AttackTurretedInfo : AttackBaseInfo
{
public override object Create(ActorInitializer init) { return new AttackTurreted( init.self ); }
}
class AttackTurreted : AttackBase, INotifyBuildComplete
{
protected Target target;
public AttackTurreted(Actor self) : base(self) { }
protected override bool CanAttack( Actor self, Target target )
{
if( self.HasTrait<Building>() && !buildComplete )
return false;
if (!target.IsValid) return false;
var turreted = self.Trait<Turreted>();
turreted.desiredFacing = Util.GetFacing( target.CenterLocation - self.CenterLocation, turreted.turretFacing );
if( turreted.desiredFacing != turreted.turretFacing )
return false;
return base.CanAttack( self, target );
}
public override void Tick(Actor self)
{
base.Tick(self);
DoAttack( self, target );
}
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
return new AttackActivity( newTarget );
}
public override void ResolveOrder(Actor self, Order order)
{
base.ResolveOrder(self, order);
if (order.OrderString == "Stop")
target = Target.None;
}
bool buildComplete = false;
public void BuildingComplete(Actor self) { buildComplete = true; }
class AttackActivity : CancelableActivity
{
readonly Target target;
public AttackActivity( Target newTarget ) { this.target = newTarget; }
public override IActivity Tick( Actor self )
{
if( IsCanceled || !target.IsValid ) return NextActivity;
if (self.TraitsImplementing<IDisable>().Any(d => d.Disabled))
return this;
var attack = self.Trait<AttackTurreted>();
const int RangeTolerance = 1; /* how far inside our maximum range we should try to sit */
var weapon = attack.ChooseWeaponForTarget(target);
if (weapon != null)
{
attack.target = target;
if (self.HasTrait<Mobile>() && !self.Info.Traits.Get<MobileInfo>().OnRails)
return Util.SequenceActivities(
new Follow( target, Math.Max( 0, (int)weapon.Info.Range - RangeTolerance ) ),
this );
}
return NextActivity;
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Move;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA
{
class AttackTurretedInfo : AttackBaseInfo
{
public override object Create(ActorInitializer init) { return new AttackTurreted( init.self ); }
}
class AttackTurreted : AttackBase, INotifyBuildComplete
{
protected Target target;
public AttackTurreted(Actor self) : base(self) { }
protected override bool CanAttack( Actor self, Target target )
{
if( self.HasTrait<Building>() && !buildComplete )
return false;
if (!target.IsValid) return false;
var turreted = self.Trait<Turreted>();
turreted.desiredFacing = Util.GetFacing( target.CenterLocation - self.CenterLocation, turreted.turretFacing );
if( turreted.desiredFacing != turreted.turretFacing )
return false;
return base.CanAttack( self, target );
}
public override void Tick(Actor self)
{
base.Tick(self);
DoAttack( self, target );
}
public override IActivity GetAttackActivity(Actor self, Target newTarget, bool allowMove)
{
return new AttackActivity( newTarget );
}
public override void ResolveOrder(Actor self, Order order)
{
base.ResolveOrder(self, order);
if (order.OrderString == "Stop")
target = Target.None;
}
bool buildComplete = false;
public void BuildingComplete(Actor self) { buildComplete = true; }
class AttackActivity : CancelableActivity
{
readonly Target target;
public AttackActivity( Target newTarget ) { this.target = newTarget; }
public override IActivity Tick( Actor self )
{
if( IsCanceled || !target.IsValid ) return NextActivity;
if (self.TraitsImplementing<IDisable>().Any(d => d.Disabled))
return this;
var attack = self.Trait<AttackTurreted>();
const int RangeTolerance = 1; /* how far inside our maximum range we should try to sit */
var weapon = attack.ChooseWeaponForTarget(target);
if (weapon != null)
{
attack.target = target;
if (self.HasTrait<Mobile>() && !self.Info.Traits.Get<MobileInfo>().OnRails)
return Util.SequenceActivities(
new Follow( target, Math.Max( 0, (int)weapon.Info.Range - RangeTolerance ) ),
this );
}
return NextActivity;
}
}
}
}

View File

@@ -1,39 +1,39 @@
#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 OpenRA.Traits;
using OpenRA.Traits.Activities;
using System.Drawing;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA
{
class AttackWanderInfo : ITraitInfo
{
public readonly int MoveRadius = 4;
public object Create(ActorInitializer init) { return new AttackWander(init.self, this); }
}
class AttackWander : INotifyIdle
{
readonly AttackWanderInfo Info;
public AttackWander(Actor self, AttackWanderInfo info)
{
Info = info;
}
public void TickIdle(Actor self)
{
var target = Util.SubPxVector[self.World.SharedRandom.Next(255)]* Info.MoveRadius / 1024 + self.Location;
self.Trait<AttackMove>().ResolveOrder(self, new Order("AttackMove", self, false) { TargetLocation = target });
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using System.Drawing;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA
{
class AttackWanderInfo : ITraitInfo
{
public readonly int MoveRadius = 4;
public object Create(ActorInitializer init) { return new AttackWander(init.self, this); }
}
class AttackWander : INotifyIdle
{
readonly AttackWanderInfo Info;
public AttackWander(Actor self, AttackWanderInfo info)
{
Info = info;
}
public void TickIdle(Actor self)
{
var target = Util.SubPxVector[self.World.SharedRandom.Next(255)]* Info.MoveRadius / 1024 + self.Location;
self.Trait<AttackMove>().ResolveOrder(self, new Order("AttackMove", self, false) { TargetLocation = target });
}
}
}

View File

@@ -1,38 +1,38 @@
#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.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA
{
class AutoHealInfo : TraitInfo<AutoHeal> { }
class AutoHeal : INotifyIdle
{
public void TickIdle( Actor self )
{
var attack = self.Trait<AttackBase>();
var inRange = self.World.FindUnitsInCircle(self.CenterLocation, Game.CellSize * attack.GetMaximumRange());
var target = inRange
.Where(a => a != self && self.Owner.Stances[a.Owner] == Stance.Ally)
.Where(a => a.IsInWorld && !a.IsDead())
.Where(a => a.HasTrait<Health>() && a.GetDamageState() > DamageState.Undamaged)
.Where(a => attack.HasAnyValidWeapons(Target.FromActor(a)))
.OrderBy(a => (a.CenterLocation - self.CenterLocation).LengthSquared)
.FirstOrDefault();
if( target != null )
self.QueueActivity(self.Trait<AttackBase>().GetAttackActivity(self, Target.FromActor( target ), false ));
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA
{
class AutoHealInfo : TraitInfo<AutoHeal> { }
class AutoHeal : INotifyIdle
{
public void TickIdle( Actor self )
{
var attack = self.Trait<AttackBase>();
var inRange = self.World.FindUnitsInCircle(self.CenterLocation, Game.CellSize * attack.GetMaximumRange());
var target = inRange
.Where(a => a != self && self.Owner.Stances[a.Owner] == Stance.Ally)
.Where(a => a.IsInWorld && !a.IsDead())
.Where(a => a.HasTrait<Health>() && a.GetDamageState() > DamageState.Undamaged)
.Where(a => attack.HasAnyValidWeapons(Target.FromActor(a)))
.OrderBy(a => (a.CenterLocation - self.CenterLocation).LengthSquared)
.FirstOrDefault();
if( target != null )
self.QueueActivity(self.Trait<AttackBase>().GetAttackActivity(self, Target.FromActor( target ), false ));
}
}
}

View File

@@ -1,57 +1,57 @@
#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 OpenRA.Traits;
using OpenRA.Traits.Activities;
using System.Drawing;
namespace OpenRA.Mods.RA
{
class AutoTargetInfo : TraitInfo<AutoTarget>
{
public readonly bool AllowMovement = true;
}
class AutoTarget : INotifyIdle, INotifyDamage
{
public void Damaged(Actor self, AttackInfo e)
{
if (!self.IsIdle) return;
if (e.Attacker.Destroyed) return;
// not a lot we can do about things we can't hurt... although maybe we should automatically run away?
var attack = self.Trait<AttackBase>();
if (!attack.HasAnyValidWeapons(Target.FromActor(e.Attacker))) return;
// don't retaliate against own units force-firing on us. it's usually not what the player wanted.
if (self.Owner.Stances[e.Attacker.Owner] == Stance.Ally) return;
if (e.Damage < 0) return; // don't retaliate against healers
self.Trait<AttackBase>().AttackTarget(Target.FromActor(e.Attacker), false, self.Info.Traits.Get<AutoTargetInfo>().AllowMovement);
}
public void TickIdle(Actor self)
{
var attack = self.Trait<AttackBase>();
var target = attack.ScanForTarget(self, null);
if (target != null)
{
self.SetTargetLine(Target.FromActor(target), Color.Red, false);
self.QueueActivity(attack.GetAttackActivity(self,
Target.FromActor(target),
self.Info.Traits.Get<AutoTargetInfo>().AllowMovement));
}
}
}
class AutoTargetIgnoreInfo : TraitInfo<AutoTargetIgnore> { }
class AutoTargetIgnore { }
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using System.Drawing;
namespace OpenRA.Mods.RA
{
class AutoTargetInfo : TraitInfo<AutoTarget>
{
public readonly bool AllowMovement = true;
}
class AutoTarget : INotifyIdle, INotifyDamage
{
public void Damaged(Actor self, AttackInfo e)
{
if (!self.IsIdle) return;
if (e.Attacker.Destroyed) return;
// not a lot we can do about things we can't hurt... although maybe we should automatically run away?
var attack = self.Trait<AttackBase>();
if (!attack.HasAnyValidWeapons(Target.FromActor(e.Attacker))) return;
// don't retaliate against own units force-firing on us. it's usually not what the player wanted.
if (self.Owner.Stances[e.Attacker.Owner] == Stance.Ally) return;
if (e.Damage < 0) return; // don't retaliate against healers
self.Trait<AttackBase>().AttackTarget(Target.FromActor(e.Attacker), false, self.Info.Traits.Get<AutoTargetInfo>().AllowMovement);
}
public void TickIdle(Actor self)
{
var attack = self.Trait<AttackBase>();
var target = attack.ScanForTarget(self, null);
if (target != null)
{
self.SetTargetLine(Target.FromActor(target), Color.Red, false);
self.QueueActivity(attack.GetAttackActivity(self,
Target.FromActor(target),
self.Info.Traits.Get<AutoTargetInfo>().AllowMovement));
}
}
}
class AutoTargetIgnoreInfo : TraitInfo<AutoTargetIgnore> { }
class AutoTargetIgnore { }
}

View File

@@ -1,26 +1,26 @@
#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.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class BelowUnitsInfo : TraitInfo<BelowUnits> { }
class BelowUnits : IRenderModifier
{
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
{
return r.Select(a => a.WithZOffset((int) -a.Sprite.size.Y));
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class BelowUnitsInfo : TraitInfo<BelowUnits> { }
class BelowUnits : IRenderModifier
{
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
{
return r.Select(a => a.WithZOffset((int) -a.Sprite.size.Y));
}
}
}

View File

@@ -1,205 +1,205 @@
#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.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class BridgeInfo : ITraitInfo, ITraitPrerequisite<HealthInfo>
{
public readonly bool Long = false;
#pragma warning disable 0649
public readonly ushort Template;
public readonly ushort DamagedTemplate;
public readonly ushort DestroyedTemplate;
// For long bridges
public readonly ushort DestroyedPlusNorthTemplate;
public readonly ushort DestroyedPlusSouthTemplate;
public readonly ushort DestroyedPlusBothTemplate;
#pragma warning restore 0649
public readonly string[] ShorePieces = {"br1", "br2"};
public readonly int[] NorthOffset = null;
public readonly int[] SouthOffset = null;
public object Create(ActorInitializer init) { return new Bridge(init.self, this); }
public IEnumerable<Pair<ushort, float>> Templates
{
get
{
if (Template != 0)
yield return Pair.New(Template, 1f);
if (DamagedTemplate != 0)
yield return Pair.New(DamagedTemplate, .5f);
if (DestroyedTemplate != 0)
yield return Pair.New(DestroyedTemplate, 0f);
if (DestroyedPlusNorthTemplate != 0)
yield return Pair.New(DestroyedPlusNorthTemplate, 0f);
if (DestroyedPlusSouthTemplate != 0)
yield return Pair.New(DestroyedPlusSouthTemplate, 0f);
if (DestroyedPlusBothTemplate != 0)
yield return Pair.New(DestroyedPlusBothTemplate, 0f);
}
}
}
class Bridge: IRenderAsTerrain, INotifyDamage
{
static string cachedTileset;
static Cache<TileReference<ushort,byte>, Sprite> sprites;
Dictionary<ushort, Dictionary<int2, Sprite>> TileSprites = new Dictionary<ushort, Dictionary<int2, Sprite>>();
Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
ushort currentTemplate;
Actor self;
BridgeInfo Info;
public string Type;
Bridge northNeighbour, southNeighbour;
Health Health;
public Bridge(Actor self, BridgeInfo info)
{
this.self = self;
Health = self.Trait<Health>();
Health.RemoveOnDeath = false;
this.Info = info;
this.Type = self.Info.Name;
}
public void Create(ushort template, Dictionary<int2, byte> subtiles)
{
currentTemplate = template;
// Create a new cache to store the tile data
if (cachedTileset != self.World.Map.Tileset)
{
cachedTileset = self.World.Map.Tileset;
sprites = new Cache<TileReference<ushort,byte>, Sprite>(
x => Game.modData.SheetBuilder.Add(self.World.TileSet.GetBytes(x),
new Size(Game.CellSize, Game.CellSize)));
}
// Cache templates and tiles for the different states
foreach (var t in Info.Templates)
{
Templates.Add(t.First,self.World.TileSet.Templates[t.First]);
TileSprites.Add(t.First,subtiles.ToDictionary(
a => a.Key,
a => sprites[new TileReference<ushort,byte>(t.First, (byte)a.Value)]));
}
}
public string GetTerrainType(int2 cell)
{
var dx = cell - self.Location;
var index = dx.X + Templates[currentTemplate].Size.X*dx.Y;
return self.World.TileSet.GetTerrainType(new TileReference<ushort, byte>(currentTemplate,(byte)index));
}
public void LinkNeighbouringBridges(World world, BridgeLayer bridges)
{
// go looking for our neighbors if this is a long bridge.
if (Info.NorthOffset != null)
northNeighbour = GetNeighbor(Info.NorthOffset, bridges);
if (Info.SouthOffset != null)
southNeighbour = GetNeighbor(Info.SouthOffset, bridges);
}
public Bridge GetNeighbor(int[] offset, BridgeLayer bridges)
{
if (offset == null) return null;
return bridges.GetBridge(self.Location + new int2(offset[0], offset[1]));
}
public IEnumerable<Renderable> RenderAsTerrain(Actor self)
{
foreach (var t in TileSprites[currentTemplate])
yield return new Renderable(t.Value, Game.CellSize * t.Key, "terrain", Game.CellSize * t.Key.Y);
}
bool IsIntact(Bridge b)
{
return b != null && !b.self.IsDead();
}
void KillUnitsOnBridge()
{
var uim = self.World.WorldActor.Trait<UnitInfluence>();
foreach (var c in TileSprites[currentTemplate].Keys)
foreach (var a in uim.GetUnitsAt(c))
if (a.HasTrait<IMove>() && !a.Trait<IMove>().CanEnterCell(c))
a.Kill(self);
}
bool dead = false;
void UpdateState()
{
// If this is a long bridge next to a destroyed shore piece, we need die to give clean edges to the break
if (Info.Long && Health.DamageState != DamageState.Dead &&
((southNeighbour != null && Info.ShorePieces.Contains(southNeighbour.Type) && !IsIntact(southNeighbour)) ||
(northNeighbour != null && Info.ShorePieces.Contains(northNeighbour.Type) && !IsIntact(northNeighbour))))
{
self.Kill(self); // this changes the damagestate
}
var ds = Health.DamageState;
currentTemplate = (ds == DamageState.Dead && Info.DestroyedTemplate > 0) ? Info.DestroyedTemplate :
(ds >= DamageState.Heavy && Info.DamagedTemplate > 0) ? Info.DamagedTemplate : Info.Template;
if (Info.Long && ds == DamageState.Dead)
{
// Long bridges have custom art for multiple segments being destroyed
bool waterToSouth = !IsIntact(southNeighbour);
bool waterToNorth = !IsIntact(northNeighbour);
if (waterToSouth && waterToNorth)
currentTemplate = Info.DestroyedPlusBothTemplate;
else if (waterToNorth)
currentTemplate = Info.DestroyedPlusNorthTemplate;
else if (waterToSouth)
currentTemplate = Info.DestroyedPlusSouthTemplate;
}
if (ds == DamageState.Dead && !dead)
{
dead = true;
KillUnitsOnBridge();
}
// Update map
foreach (var c in TileSprites[currentTemplate].Keys)
self.World.Map.CustomTerrain[c.X, c.Y] = GetTerrainType(c);
}
public void Damaged(Actor self, AttackInfo e)
{
if (e.DamageStateChanged)
{
UpdateState();
if (northNeighbour != null) northNeighbour.UpdateState();
if (southNeighbour != null) southNeighbour.UpdateState();
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class BridgeInfo : ITraitInfo, ITraitPrerequisite<HealthInfo>
{
public readonly bool Long = false;
#pragma warning disable 0649
public readonly ushort Template;
public readonly ushort DamagedTemplate;
public readonly ushort DestroyedTemplate;
// For long bridges
public readonly ushort DestroyedPlusNorthTemplate;
public readonly ushort DestroyedPlusSouthTemplate;
public readonly ushort DestroyedPlusBothTemplate;
#pragma warning restore 0649
public readonly string[] ShorePieces = {"br1", "br2"};
public readonly int[] NorthOffset = null;
public readonly int[] SouthOffset = null;
public object Create(ActorInitializer init) { return new Bridge(init.self, this); }
public IEnumerable<Pair<ushort, float>> Templates
{
get
{
if (Template != 0)
yield return Pair.New(Template, 1f);
if (DamagedTemplate != 0)
yield return Pair.New(DamagedTemplate, .5f);
if (DestroyedTemplate != 0)
yield return Pair.New(DestroyedTemplate, 0f);
if (DestroyedPlusNorthTemplate != 0)
yield return Pair.New(DestroyedPlusNorthTemplate, 0f);
if (DestroyedPlusSouthTemplate != 0)
yield return Pair.New(DestroyedPlusSouthTemplate, 0f);
if (DestroyedPlusBothTemplate != 0)
yield return Pair.New(DestroyedPlusBothTemplate, 0f);
}
}
}
class Bridge: IRenderAsTerrain, INotifyDamage
{
static string cachedTileset;
static Cache<TileReference<ushort,byte>, Sprite> sprites;
Dictionary<ushort, Dictionary<int2, Sprite>> TileSprites = new Dictionary<ushort, Dictionary<int2, Sprite>>();
Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
ushort currentTemplate;
Actor self;
BridgeInfo Info;
public string Type;
Bridge northNeighbour, southNeighbour;
Health Health;
public Bridge(Actor self, BridgeInfo info)
{
this.self = self;
Health = self.Trait<Health>();
Health.RemoveOnDeath = false;
this.Info = info;
this.Type = self.Info.Name;
}
public void Create(ushort template, Dictionary<int2, byte> subtiles)
{
currentTemplate = template;
// Create a new cache to store the tile data
if (cachedTileset != self.World.Map.Tileset)
{
cachedTileset = self.World.Map.Tileset;
sprites = new Cache<TileReference<ushort,byte>, Sprite>(
x => Game.modData.SheetBuilder.Add(self.World.TileSet.GetBytes(x),
new Size(Game.CellSize, Game.CellSize)));
}
// Cache templates and tiles for the different states
foreach (var t in Info.Templates)
{
Templates.Add(t.First,self.World.TileSet.Templates[t.First]);
TileSprites.Add(t.First,subtiles.ToDictionary(
a => a.Key,
a => sprites[new TileReference<ushort,byte>(t.First, (byte)a.Value)]));
}
}
public string GetTerrainType(int2 cell)
{
var dx = cell - self.Location;
var index = dx.X + Templates[currentTemplate].Size.X*dx.Y;
return self.World.TileSet.GetTerrainType(new TileReference<ushort, byte>(currentTemplate,(byte)index));
}
public void LinkNeighbouringBridges(World world, BridgeLayer bridges)
{
// go looking for our neighbors if this is a long bridge.
if (Info.NorthOffset != null)
northNeighbour = GetNeighbor(Info.NorthOffset, bridges);
if (Info.SouthOffset != null)
southNeighbour = GetNeighbor(Info.SouthOffset, bridges);
}
public Bridge GetNeighbor(int[] offset, BridgeLayer bridges)
{
if (offset == null) return null;
return bridges.GetBridge(self.Location + new int2(offset[0], offset[1]));
}
public IEnumerable<Renderable> RenderAsTerrain(Actor self)
{
foreach (var t in TileSprites[currentTemplate])
yield return new Renderable(t.Value, Game.CellSize * t.Key, "terrain", Game.CellSize * t.Key.Y);
}
bool IsIntact(Bridge b)
{
return b != null && !b.self.IsDead();
}
void KillUnitsOnBridge()
{
var uim = self.World.WorldActor.Trait<UnitInfluence>();
foreach (var c in TileSprites[currentTemplate].Keys)
foreach (var a in uim.GetUnitsAt(c))
if (a.HasTrait<IMove>() && !a.Trait<IMove>().CanEnterCell(c))
a.Kill(self);
}
bool dead = false;
void UpdateState()
{
// If this is a long bridge next to a destroyed shore piece, we need die to give clean edges to the break
if (Info.Long && Health.DamageState != DamageState.Dead &&
((southNeighbour != null && Info.ShorePieces.Contains(southNeighbour.Type) && !IsIntact(southNeighbour)) ||
(northNeighbour != null && Info.ShorePieces.Contains(northNeighbour.Type) && !IsIntact(northNeighbour))))
{
self.Kill(self); // this changes the damagestate
}
var ds = Health.DamageState;
currentTemplate = (ds == DamageState.Dead && Info.DestroyedTemplate > 0) ? Info.DestroyedTemplate :
(ds >= DamageState.Heavy && Info.DamagedTemplate > 0) ? Info.DamagedTemplate : Info.Template;
if (Info.Long && ds == DamageState.Dead)
{
// Long bridges have custom art for multiple segments being destroyed
bool waterToSouth = !IsIntact(southNeighbour);
bool waterToNorth = !IsIntact(northNeighbour);
if (waterToSouth && waterToNorth)
currentTemplate = Info.DestroyedPlusBothTemplate;
else if (waterToNorth)
currentTemplate = Info.DestroyedPlusNorthTemplate;
else if (waterToSouth)
currentTemplate = Info.DestroyedPlusSouthTemplate;
}
if (ds == DamageState.Dead && !dead)
{
dead = true;
KillUnitsOnBridge();
}
// Update map
foreach (var c in TileSprites[currentTemplate].Keys)
self.World.Map.CustomTerrain[c.X, c.Y] = GetTerrainType(c);
}
public void Damaged(Actor self, AttackInfo e)
{
if (e.DamageStateChanged)
{
UpdateState();
if (northNeighbour != null) northNeighbour.UpdateState();
if (southNeighbour != null) southNeighbour.UpdateState();
}
}
}
}

View File

@@ -1,115 +1,115 @@
#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.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class BridgeLayerInfo : ITraitInfo
{
[ActorReference]
public readonly string[] Bridges = {"bridge1", "bridge2"};
public object Create(ActorInitializer init) { return new BridgeLayer(init.self, this); }
}
class BridgeLayer : IWorldLoaded
{
readonly BridgeLayerInfo Info;
readonly World world;
Dictionary<ushort, Pair<string, float>> BridgeTypes = new Dictionary<ushort, Pair<string,float>>();
Bridge[,] Bridges;
public BridgeLayer(Actor self, BridgeLayerInfo Info)
{
this.Info = Info;
this.world = self.World;
}
public void WorldLoaded(World w)
{
Bridges = new Bridge[w.Map.MapSize.X, w.Map.MapSize.Y];
// Build a list of templates that should be overlayed with bridges
foreach(var bridge in Info.Bridges)
{
var bi = Rules.Info[bridge].Traits.Get<BridgeInfo>();
foreach (var template in bi.Templates)
BridgeTypes.Add(template.First, Pair.New(bridge, template.Second));
}
// Loop through the map looking for templates to overlay
for (int i = w.Map.Bounds.Left; i < w.Map.Bounds.Right; i++)
for (int j = w.Map.Bounds.Top; j < w.Map.Bounds.Bottom; j++)
if (BridgeTypes.Keys.Contains(w.Map.MapTiles.Value[i, j].type))
ConvertBridgeToActor(w, i, j);
// Link adjacent (long)-bridges so that artwork is updated correctly
foreach (var b in w.Actors.SelectMany(a => a.TraitsImplementing<Bridge>()))
b.LinkNeighbouringBridges(w,this);
}
void ConvertBridgeToActor(World w, int i, int j)
{
// This cell already has a bridge overlaying it from a previous iteration
if (Bridges[i,j] != null)
return;
// Correlate the tile "image" aka subtile with its position to find the template origin
var tile = w.Map.MapTiles.Value[i, j].type;
var index = w.Map.MapTiles.Value[i, j].index;
var template = w.TileSet.Templates[tile];
var ni = i - index % template.Size.X;
var nj = j - index / template.Size.X;
// Create a new actor for this bridge and keep track of which subtiles this bridge includes
var bridge = w.CreateActor(BridgeTypes[tile].First, new TypeDictionary
{
new LocationInit( new int2(ni, nj) ),
new OwnerInit( w.WorldActor.Owner ),
new HealthInit( BridgeTypes[tile].Second ),
}).Trait<Bridge>();
Dictionary<int2, byte> subTiles = new Dictionary<int2, byte>();
// For each subtile in the template
for (byte ind = 0; ind < template.Size.X*template.Size.Y; ind++)
{
// Is this tile actually included in the bridge template?
if (!template.Tiles.Keys.Contains(ind))
continue;
// Where do we expect to find the subtile
var x = ni + ind % template.Size.X;
var y = nj + ind / template.Size.X;
// This isn't the bridge you're looking for
if (!w.Map.IsInMap(x, y) || w.Map.MapTiles.Value[x, y].index != ind)
continue;
subTiles.Add(new int2(x,y),ind);
Bridges[x,y] = bridge;
}
bridge.Create(tile, subTiles);
}
// Used to check for neighbouring bridges
public Bridge GetBridge(int2 cell)
{
if (!world.Map.IsInMap(cell.X, cell.Y))
return null;
return Bridges[ cell.X, cell.Y ];
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class BridgeLayerInfo : ITraitInfo
{
[ActorReference]
public readonly string[] Bridges = {"bridge1", "bridge2"};
public object Create(ActorInitializer init) { return new BridgeLayer(init.self, this); }
}
class BridgeLayer : IWorldLoaded
{
readonly BridgeLayerInfo Info;
readonly World world;
Dictionary<ushort, Pair<string, float>> BridgeTypes = new Dictionary<ushort, Pair<string,float>>();
Bridge[,] Bridges;
public BridgeLayer(Actor self, BridgeLayerInfo Info)
{
this.Info = Info;
this.world = self.World;
}
public void WorldLoaded(World w)
{
Bridges = new Bridge[w.Map.MapSize.X, w.Map.MapSize.Y];
// Build a list of templates that should be overlayed with bridges
foreach(var bridge in Info.Bridges)
{
var bi = Rules.Info[bridge].Traits.Get<BridgeInfo>();
foreach (var template in bi.Templates)
BridgeTypes.Add(template.First, Pair.New(bridge, template.Second));
}
// Loop through the map looking for templates to overlay
for (int i = w.Map.Bounds.Left; i < w.Map.Bounds.Right; i++)
for (int j = w.Map.Bounds.Top; j < w.Map.Bounds.Bottom; j++)
if (BridgeTypes.Keys.Contains(w.Map.MapTiles.Value[i, j].type))
ConvertBridgeToActor(w, i, j);
// Link adjacent (long)-bridges so that artwork is updated correctly
foreach (var b in w.Actors.SelectMany(a => a.TraitsImplementing<Bridge>()))
b.LinkNeighbouringBridges(w,this);
}
void ConvertBridgeToActor(World w, int i, int j)
{
// This cell already has a bridge overlaying it from a previous iteration
if (Bridges[i,j] != null)
return;
// Correlate the tile "image" aka subtile with its position to find the template origin
var tile = w.Map.MapTiles.Value[i, j].type;
var index = w.Map.MapTiles.Value[i, j].index;
var template = w.TileSet.Templates[tile];
var ni = i - index % template.Size.X;
var nj = j - index / template.Size.X;
// Create a new actor for this bridge and keep track of which subtiles this bridge includes
var bridge = w.CreateActor(BridgeTypes[tile].First, new TypeDictionary
{
new LocationInit( new int2(ni, nj) ),
new OwnerInit( w.WorldActor.Owner ),
new HealthInit( BridgeTypes[tile].Second ),
}).Trait<Bridge>();
Dictionary<int2, byte> subTiles = new Dictionary<int2, byte>();
// For each subtile in the template
for (byte ind = 0; ind < template.Size.X*template.Size.Y; ind++)
{
// Is this tile actually included in the bridge template?
if (!template.Tiles.Keys.Contains(ind))
continue;
// Where do we expect to find the subtile
var x = ni + ind % template.Size.X;
var y = nj + ind / template.Size.X;
// This isn't the bridge you're looking for
if (!w.Map.IsInMap(x, y) || w.Map.MapTiles.Value[x, y].index != ind)
continue;
subTiles.Add(new int2(x,y),ind);
Bridges[x,y] = bridge;
}
bridge.Create(tile, subTiles);
}
// Used to check for neighbouring bridges
public Bridge GetBridge(int2 cell)
{
if (!world.Map.IsInMap(cell.X, cell.Y))
return null;
return Bridges[ cell.X, cell.Y ];
}
}
}

View File

@@ -1,28 +1,28 @@
#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 OpenRA.Traits;
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class BuildableInfo : ITraitInfo
{
[ActorReference]
[ActorReference]
public readonly string[] Prerequisites = { };
[ActorReference]
[ActorReference]
public readonly string[] BuiltAt = { };
public readonly string[] Owner = { };
public readonly string Queue;
public readonly bool Hidden = false;
public readonly string[] Owner = { };
public readonly string Queue;
public readonly bool Hidden = false;
// todo: UI fluff; doesn't belong here
public readonly int BuildPaletteOrder = 9999;
@@ -30,5 +30,5 @@ namespace OpenRA.Mods.RA
public object Create(ActorInitializer init) { return new Buildable(); }
}
class Buildable { }
class Buildable { }
}

View File

@@ -1,10 +1,10 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion

View File

@@ -1,19 +1,19 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA.Buildings
class BibLayer: IRenderOverlay, IWorldLoaded
{
World world;
BibLayerInfo info;
BibLayerInfo info;
Dictionary<int2, TileReference<byte, byte>> tiles;
Sprite[][] bibSprites;
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA.Buildings
public void WorldLoaded(World w)
{
world = w;
world = w;
tiles = new Dictionary<int2, TileReference<byte, byte>>();
}
@@ -64,26 +64,26 @@ namespace OpenRA.Mods.RA.Buildings
for (int i = 0; i < 2 * size; i++)
{
var p = b.Location + new int2(i % size, i / size + bibOffset);
if (isAdd)
tiles[p] = new TileReference<byte, byte>((byte)((isAdd) ? bib + 1 : 0), (byte)i);
else
var p = b.Location + new int2(i % size, i / size + bibOffset);
if (isAdd)
tiles[p] = new TileReference<byte, byte>((byte)((isAdd) ? bib + 1 : 0), (byte)i);
else
tiles.Remove(p);
}
}
public void Render( WorldRenderer wr )
{
{
var cliprect = Game.viewport.WorldBounds(world);
foreach (var kv in tiles)
{
if (!cliprect.Contains(kv.Key.X, kv.Key.Y))
continue;
if (!world.LocalShroud.IsExplored(kv.Key))
continue;
bibSprites[kv.Value.type - 1][kv.Value.index].DrawAt( wr,
Game.CellSize * kv.Key, "terrain");
foreach (var kv in tiles)
{
if (!cliprect.Contains(kv.Key.X, kv.Key.Y))
continue;
if (!world.LocalShroud.IsExplored(kv.Key))
continue;
bibSprites[kv.Value.type - 1][kv.Value.index].DrawAt( wr,
Game.CellSize * kv.Key, "terrain");
}
}
}

View File

@@ -1,124 +1,124 @@
#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 System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
using OpenRA.FileFormats;
namespace OpenRA.Mods.RA.Buildings
{
public class BuildingInfo : ITraitInfo
{
public readonly int Power = 0;
public readonly bool BaseNormal = true;
public readonly bool WaterBound = false;
public readonly int Adjacent = 2;
public readonly bool Capturable = false;
public readonly string Footprint = "x";
public readonly int2 Dimensions = new int2(1, 1);
public readonly bool Unsellable = false;
public readonly int RefundPercent = 50;
public readonly string[] BuildSounds = {"placbldg.aud", "build5.aud"};
public readonly string[] SellSounds = {"cashturn.aud"};
public object Create(ActorInitializer init) { return new Building(init, this); }
public bool IsCloseEnoughToBase(World world, Player p, string buildingName, int2 topLeft)
{
var buildingMaxBounds = Dimensions;
if( Rules.Info[ buildingName ].Traits.Contains<BibInfo>() )
buildingMaxBounds.Y += 1;
var scanStart = world.ClampToWorld( topLeft - new int2( Adjacent, Adjacent ) );
var scanEnd = world.ClampToWorld( topLeft + buildingMaxBounds + new int2( Adjacent, Adjacent ) );
var nearnessCandidates = new List<int2>();
for( int y = scanStart.Y ; y < scanEnd.Y ; y++ )
{
for( int x = scanStart.X ; x < scanEnd.X ; x++ )
{
var at = world.WorldActor.Trait<BuildingInfluence>().GetBuildingAt( new int2( x, y ) );
if( at != null && at.Owner.Stances[ p ] == Stance.Ally && at.Info.Traits.Get<BuildingInfo>().BaseNormal )
nearnessCandidates.Add( new int2( x, y ) );
}
}
var buildingTiles = FootprintUtils.Tiles( buildingName, this, topLeft ).ToList();
return nearnessCandidates
.Any( a => buildingTiles
.Any( b => Math.Abs( a.X - b.X ) <= Adjacent
&& Math.Abs( a.Y - b.Y ) <= Adjacent ) );
}
}
public class Building : INotifyDamage, IResolveOrder, IOccupySpace, INotifyCapture, ISync
{
readonly Actor self;
public readonly BuildingInfo Info;
[Sync]
readonly int2 topLeft;
PowerManager PlayerPower;
public int2 PxPosition { get { return ( 2 * topLeft + Info.Dimensions ) * Game.CellSize / 2; } }
public Building(ActorInitializer init, BuildingInfo info)
{
this.self = init.self;
this.topLeft = init.Get<LocationInit,int2>();
this.Info = info;
this.PlayerPower = init.self.Owner.PlayerActor.Trait<PowerManager>();
}
public int GetPowerUsage()
{
if (Info.Power <= 0)
return Info.Power;
var health = self.TraitOrDefault<Health>();
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)
PlayerPower.UpdateActor(self, GetPowerUsage());
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Sell")
{
self.CancelActivity();
self.QueueActivity(new Sell());
}
}
public int2 TopLeft
{
get { return topLeft; }
}
public IEnumerable<Pair<int2, SubCell>> OccupiedCells()
{
return FootprintUtils.UnpathableTiles( self.Info.Name, Info, TopLeft ).Select(c => Pair.New(c, SubCell.FullCell));
}
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
{
PlayerPower = newOwner.PlayerActor.Trait<PowerManager>();
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
using OpenRA.FileFormats;
namespace OpenRA.Mods.RA.Buildings
{
public class BuildingInfo : ITraitInfo
{
public readonly int Power = 0;
public readonly bool BaseNormal = true;
public readonly bool WaterBound = false;
public readonly int Adjacent = 2;
public readonly bool Capturable = false;
public readonly string Footprint = "x";
public readonly int2 Dimensions = new int2(1, 1);
public readonly bool Unsellable = false;
public readonly int RefundPercent = 50;
public readonly string[] BuildSounds = {"placbldg.aud", "build5.aud"};
public readonly string[] SellSounds = {"cashturn.aud"};
public object Create(ActorInitializer init) { return new Building(init, this); }
public bool IsCloseEnoughToBase(World world, Player p, string buildingName, int2 topLeft)
{
var buildingMaxBounds = Dimensions;
if( Rules.Info[ buildingName ].Traits.Contains<BibInfo>() )
buildingMaxBounds.Y += 1;
var scanStart = world.ClampToWorld( topLeft - new int2( Adjacent, Adjacent ) );
var scanEnd = world.ClampToWorld( topLeft + buildingMaxBounds + new int2( Adjacent, Adjacent ) );
var nearnessCandidates = new List<int2>();
for( int y = scanStart.Y ; y < scanEnd.Y ; y++ )
{
for( int x = scanStart.X ; x < scanEnd.X ; x++ )
{
var at = world.WorldActor.Trait<BuildingInfluence>().GetBuildingAt( new int2( x, y ) );
if( at != null && at.Owner.Stances[ p ] == Stance.Ally && at.Info.Traits.Get<BuildingInfo>().BaseNormal )
nearnessCandidates.Add( new int2( x, y ) );
}
}
var buildingTiles = FootprintUtils.Tiles( buildingName, this, topLeft ).ToList();
return nearnessCandidates
.Any( a => buildingTiles
.Any( b => Math.Abs( a.X - b.X ) <= Adjacent
&& Math.Abs( a.Y - b.Y ) <= Adjacent ) );
}
}
public class Building : INotifyDamage, IResolveOrder, IOccupySpace, INotifyCapture, ISync
{
readonly Actor self;
public readonly BuildingInfo Info;
[Sync]
readonly int2 topLeft;
PowerManager PlayerPower;
public int2 PxPosition { get { return ( 2 * topLeft + Info.Dimensions ) * Game.CellSize / 2; } }
public Building(ActorInitializer init, BuildingInfo info)
{
this.self = init.self;
this.topLeft = init.Get<LocationInit,int2>();
this.Info = info;
this.PlayerPower = init.self.Owner.PlayerActor.Trait<PowerManager>();
}
public int GetPowerUsage()
{
if (Info.Power <= 0)
return Info.Power;
var health = self.TraitOrDefault<Health>();
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)
PlayerPower.UpdateActor(self, GetPowerUsage());
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Sell")
{
self.CancelActivity();
self.QueueActivity(new Sell());
}
}
public int2 TopLeft
{
get { return topLeft; }
}
public IEnumerable<Pair<int2, SubCell>> OccupiedCells()
{
return FootprintUtils.UnpathableTiles( self.Info.Name, Info, TopLeft ).Select(c => Pair.New(c, SubCell.FullCell));
}
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
{
PlayerPower = newOwner.PlayerActor.Trait<PowerManager>();
}
}
}

View File

@@ -1,52 +1,52 @@
#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 OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public class BuildingInfluenceInfo : ITraitInfo
{
public object Create( ActorInitializer init ) { return new BuildingInfluence( init.world ); }
}
public class BuildingInfluence
{
Actor[,] influence;
Map map;
public BuildingInfluence( World world )
{
map = world.Map;
influence = new Actor[map.MapSize.X, map.MapSize.Y];
world.ActorAdded +=
a => { if (a.HasTrait<Building>())
ChangeInfluence(a, a.Trait<Building>(), true); };
world.ActorRemoved +=
a => { if (a.HasTrait<Building>())
ChangeInfluence(a, a.Trait<Building>(), false); };
}
void ChangeInfluence( Actor a, Building building, bool isAdd )
{
foreach( var u in FootprintUtils.Tiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location ) )
if( map.IsInMap( u ) )
influence[ u.X, u.Y ] = isAdd ? a : null;
}
public Actor GetBuildingAt(int2 cell)
{
if (!map.IsInMap(cell)) return null;
return influence[cell.X, cell.Y];
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public class BuildingInfluenceInfo : ITraitInfo
{
public object Create( ActorInitializer init ) { return new BuildingInfluence( init.world ); }
}
public class BuildingInfluence
{
Actor[,] influence;
Map map;
public BuildingInfluence( World world )
{
map = world.Map;
influence = new Actor[map.MapSize.X, map.MapSize.Y];
world.ActorAdded +=
a => { if (a.HasTrait<Building>())
ChangeInfluence(a, a.Trait<Building>(), true); };
world.ActorRemoved +=
a => { if (a.HasTrait<Building>())
ChangeInfluence(a, a.Trait<Building>(), false); };
}
void ChangeInfluence( Actor a, Building building, bool isAdd )
{
foreach( var u in FootprintUtils.Tiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location ) )
if( map.IsInMap( u ) )
influence[ u.X, u.Y ] = isAdd ? a : null;
}
public Actor GetBuildingAt(int2 cell)
{
if (!map.IsInMap(cell)) return null;
return influence[cell.X, cell.Y];
}
}
}

View File

@@ -1,57 +1,57 @@
#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 OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public class CanPowerDownInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new CanPowerDown(init); }
}
public class CanPowerDown : IResolveOrder, IDisable, INotifyCapture, ISync
{
[Sync]
bool disabled = false;
int normalPower = 0;
PowerManager PowerManager;
TechTree TechTree;
public CanPowerDown(ActorInitializer init)
{
PowerManager = init.self.Owner.PlayerActor.Trait<PowerManager>();
TechTree = init.self.Owner.PlayerActor.Trait<TechTree>();
normalPower = init.self.Info.Traits.Get<BuildingInfo>().Power;
}
public bool Disabled { get { return disabled; } }
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "PowerDown")
{
disabled = !disabled;
var eva = self.World.WorldActor.Info.Traits.Get<EvaAlertsInfo>();
Sound.PlayToPlayer(self.Owner, disabled ? eva.EnablePower : eva.DisablePower);
PowerManager.UpdateActor(self, disabled ? 0 : normalPower);
// Rebuild the tech tree; some support powers require active buildings
TechTree.Update();
}
}
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
{
PowerManager = newOwner.PlayerActor.Trait<PowerManager>();
TechTree = newOwner.PlayerActor.Trait<TechTree>();
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public class CanPowerDownInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new CanPowerDown(init); }
}
public class CanPowerDown : IResolveOrder, IDisable, INotifyCapture, ISync
{
[Sync]
bool disabled = false;
int normalPower = 0;
PowerManager PowerManager;
TechTree TechTree;
public CanPowerDown(ActorInitializer init)
{
PowerManager = init.self.Owner.PlayerActor.Trait<PowerManager>();
TechTree = init.self.Owner.PlayerActor.Trait<TechTree>();
normalPower = init.self.Info.Traits.Get<BuildingInfo>().Power;
}
public bool Disabled { get { return disabled; } }
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "PowerDown")
{
disabled = !disabled;
var eva = self.World.WorldActor.Info.Traits.Get<EvaAlertsInfo>();
Sound.PlayToPlayer(self.Owner, disabled ? eva.EnablePower : eva.DisablePower);
PowerManager.UpdateActor(self, disabled ? 0 : normalPower);
// Rebuild the tech tree; some support powers require active buildings
TechTree.Update();
}
}
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
{
PowerManager = newOwner.PlayerActor.Trait<PowerManager>();
TechTree = newOwner.PlayerActor.Trait<TechTree>();
}
}
}

View File

@@ -1,24 +1,24 @@
#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 OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
// allow a nonstandard sell/repair value to avoid
// buy-sell exploits like c&c's PROC.
public class CustomSellValueInfo : TraitInfo<CustomSellValue>
{
public readonly int Value = 0;
}
public class CustomSellValue { }
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
// allow a nonstandard sell/repair value to avoid
// buy-sell exploits like c&c's PROC.
public class CustomSellValueInfo : TraitInfo<CustomSellValue>
{
public readonly int Value = 0;
}
public class CustomSellValue { }
}

View File

@@ -1,64 +1,64 @@
#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 System.Collections.Generic;
using System.Linq;
namespace OpenRA.Mods.RA.Buildings
{
public static class FootprintUtils
{
public static IEnumerable<int2> Tiles( string name, BuildingInfo buildingInfo, int2 topLeft )
{
var dim = buildingInfo.Dimensions;
var footprint = buildingInfo.Footprint.Where(x => !char.IsWhiteSpace(x));
if (Rules.Info[ name ].Traits.Contains<BibInfo>())
{
dim.Y += 1;
footprint = footprint.Concat(new char[dim.X]);
}
return TilesWhere( name, dim, footprint.ToArray(), a => a != '_' ).Select( t => t + topLeft );
}
public static IEnumerable<int2> Tiles(Actor a)
{
return Tiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location );
}
public static IEnumerable<int2> UnpathableTiles( string name, BuildingInfo buildingInfo, int2 position )
{
var footprint = buildingInfo.Footprint.Where( x => !char.IsWhiteSpace( x ) ).ToArray();
foreach( var tile in TilesWhere( name, buildingInfo.Dimensions, footprint, a => a == 'x' ) )
yield return tile + position;
}
static IEnumerable<int2> TilesWhere( string name, int2 dim, char[] footprint, Func<char, bool> cond )
{
if( footprint.Length != dim.X * dim.Y )
throw new InvalidOperationException( "Invalid footprint for " + name );
int index = 0;
for( int y = 0 ; y < dim.Y ; y++ )
for( int x = 0 ; x < dim.X ; x++ )
if( cond( footprint[ index++ ] ) )
yield return new int2( x, y );
}
public static int2 AdjustForBuildingSize( BuildingInfo buildingInfo )
{
var dim = buildingInfo.Dimensions;
return new int2( dim.X / 2, dim.Y > 1 ? ( dim.Y + 1 ) / 2 : 0 );
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
namespace OpenRA.Mods.RA.Buildings
{
public static class FootprintUtils
{
public static IEnumerable<int2> Tiles( string name, BuildingInfo buildingInfo, int2 topLeft )
{
var dim = buildingInfo.Dimensions;
var footprint = buildingInfo.Footprint.Where(x => !char.IsWhiteSpace(x));
if (Rules.Info[ name ].Traits.Contains<BibInfo>())
{
dim.Y += 1;
footprint = footprint.Concat(new char[dim.X]);
}
return TilesWhere( name, dim, footprint.ToArray(), a => a != '_' ).Select( t => t + topLeft );
}
public static IEnumerable<int2> Tiles(Actor a)
{
return Tiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location );
}
public static IEnumerable<int2> UnpathableTiles( string name, BuildingInfo buildingInfo, int2 position )
{
var footprint = buildingInfo.Footprint.Where( x => !char.IsWhiteSpace( x ) ).ToArray();
foreach( var tile in TilesWhere( name, buildingInfo.Dimensions, footprint, a => a == 'x' ) )
yield return tile + position;
}
static IEnumerable<int2> TilesWhere( string name, int2 dim, char[] footprint, Func<char, bool> cond )
{
if( footprint.Length != dim.X * dim.Y )
throw new InvalidOperationException( "Invalid footprint for " + name );
int index = 0;
for( int y = 0 ; y < dim.Y ; y++ )
for( int x = 0 ; x < dim.X ; x++ )
if( cond( footprint[ index++ ] ) )
yield return new int2( x, y );
}
public static int2 AdjustForBuildingSize( BuildingInfo buildingInfo )
{
var dim = buildingInfo.Dimensions;
return new int2( dim.X / 2, dim.Y > 1 ? ( dim.Y + 1 ) / 2 : 0 );
}
}
}

View File

@@ -1,21 +1,21 @@
#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 OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public class LineBuildInfo : TraitInfo<LineBuild>
{
public readonly int Range = 5;
}
public class LineBuild {}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public class LineBuildInfo : TraitInfo<LineBuild>
{
public readonly int Range = 5;
}
public class LineBuild {}
}

View File

@@ -1,14 +1,14 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion
using System.Collections.Generic;
#endregion
using System.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
@@ -17,12 +17,12 @@ namespace OpenRA.Mods.RA.Buildings
{
public readonly int AdviceInterval = 250;
public object Create(ActorInitializer init) { return new PowerManager(init, this); }
}
}
public class PowerManager : ITick, ISync
{
PowerManagerInfo Info;
Player Player;
Player Player;
DeveloperMode devMode;
Dictionary<Actor, int> PowerDrain = new Dictionary<Actor, int>();
@@ -38,9 +38,9 @@ namespace OpenRA.Mods.RA.Buildings
Player = init.self.Owner;
init.world.ActorAdded += ActorAdded;
init.world.ActorRemoved += ActorRemoved;
devMode = init.self.Trait<DeveloperMode>();
init.world.ActorRemoved += ActorRemoved;
devMode = init.self.Trait<DeveloperMode>();
wasHackEnabled = devMode.UnlimitedPower;
}
@@ -71,9 +71,9 @@ namespace OpenRA.Mods.RA.Buildings
totalProvided += p;
else
totalDrained -= p;
}
if (devMode.UnlimitedPower)
}
if (devMode.UnlimitedPower)
totalProvided = 1000000;
}
@@ -87,15 +87,15 @@ namespace OpenRA.Mods.RA.Buildings
}
int nextPowerAdviceTime = 0;
bool wasLowPower = false;
bool wasLowPower = false;
bool wasHackEnabled;
public void Tick(Actor self)
{
if (wasHackEnabled != devMode.UnlimitedPower)
{
UpdateTotals();
wasHackEnabled = devMode.UnlimitedPower;
{
if (wasHackEnabled != devMode.UnlimitedPower)
{
UpdateTotals();
wasHackEnabled = devMode.UnlimitedPower;
}
var lowPower = totalProvided < totalDrained;

View File

@@ -1,15 +1,15 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion
using System;
using OpenRA.Mods.RA.Effects;
#endregion
using System;
using OpenRA.Mods.RA.Effects;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
@@ -20,8 +20,8 @@ namespace OpenRA.Mods.RA.Buildings
public readonly float RepairRate = 0.016f;
public readonly int RepairStep = 7;
public object Create(ActorInitializer init) { return new RepairableBuilding(init.self, this); }
}
}
public class RepairableBuilding : ITick, IResolveOrder, ISync
{
[Sync]

View File

@@ -1,38 +1,38 @@
#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 OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
class RequiresPowerInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new RequiresPower(init.self); }
}
class RequiresPower : IDisable, INotifyCapture
{
PowerManager power;
public RequiresPower( Actor self )
{
power = self.Owner.PlayerActor.Trait<PowerManager>();
}
public bool Disabled
{
get { return power.PowerProvided < power.PowerDrained; }
}
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
{
power = newOwner.PlayerActor.Trait<PowerManager>();
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
class RequiresPowerInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new RequiresPower(init.self); }
}
class RequiresPower : IDisable, INotifyCapture
{
PowerManager power;
public RequiresPower( Actor self )
{
power = self.Owner.PlayerActor.Trait<PowerManager>();
}
public bool Disabled
{
get { return power.PowerProvided < power.PowerDrained; }
}
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
{
power = newOwner.PlayerActor.Trait<PowerManager>();
}
}
}

View File

@@ -1,77 +1,77 @@
#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.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
class Sell : IActivity
{
IActivity NextActivity { get; set; }
bool started;
int framesRemaining;
void DoSell(Actor self)
{
var h = self.TraitOrDefault<Health>();
var bi = self.Info.Traits.Get<BuildingInfo>();
var pr = self.Owner.PlayerActor.Trait<PlayerResources>();
var csv = self.Info.Traits.GetOrDefault<CustomSellValueInfo>();
var cost = csv != null ? csv.Value : self.Info.Traits.Get<ValuedInfo>().Cost;
var refund = (cost * bi.RefundPercent * (h == null ? 1 : h.HP)) / (100 * (h == null ? 1 : h.MaxHP));
pr.GiveCash(refund);
foreach (var ns in self.TraitsImplementing<INotifySold>())
ns.Sold(self);
self.Destroy();
}
public IActivity Tick(Actor self)
{
if( !started )
{
framesRemaining = self.Trait<RenderSimple>().anim.HasSequence("make")
? self.Trait<RenderSimple>().anim.GetSequence( "make" ).Length : 0;
foreach( var ns in self.TraitsImplementing<INotifySold>() )
ns.Selling( self );
started = true;
}
else if( framesRemaining <= 0 )
DoSell( self );
else
--framesRemaining;
return this;
}
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;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
class Sell : IActivity
{
IActivity NextActivity { get; set; }
bool started;
int framesRemaining;
void DoSell(Actor self)
{
var h = self.TraitOrDefault<Health>();
var bi = self.Info.Traits.Get<BuildingInfo>();
var pr = self.Owner.PlayerActor.Trait<PlayerResources>();
var csv = self.Info.Traits.GetOrDefault<CustomSellValueInfo>();
var cost = csv != null ? csv.Value : self.Info.Traits.Get<ValuedInfo>().Cost;
var refund = (cost * bi.RefundPercent * (h == null ? 1 : h.HP)) / (100 * (h == null ? 1 : h.MaxHP));
pr.GiveCash(refund);
foreach (var ns in self.TraitsImplementing<INotifySold>())
ns.Sold(self);
self.Destroy();
}
public IActivity Tick(Actor self)
{
if( !started )
{
framesRemaining = self.Trait<RenderSimple>().anim.HasSequence("make")
? self.Trait<RenderSimple>().anim.GetSequence( "make" ).Length : 0;
foreach( var ns in self.TraitsImplementing<INotifySold>() )
ns.Selling( self );
started = true;
}
else if( framesRemaining <= 0 )
DoSell( self );
else
--framesRemaining;
return this;
}
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

@@ -1,10 +1,10 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion

View File

@@ -1,10 +1,10 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion

View File

@@ -1,116 +1,116 @@
#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.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public class TechTreeInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new TechTree(init);}
}
public class TechTree
{
readonly List<Watcher> watchers = new List<Watcher>();
readonly Player player;
public TechTree(ActorInitializer init)
{
player = init.self.Owner;
init.world.ActorAdded += ActorChanged;
init.world.ActorRemoved += ActorChanged;
}
public void ActorChanged(Actor a)
{
if (a.Owner == player && a.HasTrait<Building>())
Update();
}
public void Update()
{
var buildings = GatherBuildings(player);
foreach(var w in watchers)
w.Update(buildings);
}
public void Add(string key, List<string> prerequisites, ITechTreeElement tte)
{
watchers.Add(new Watcher( key, prerequisites, tte ));
}
public void Remove(string key)
{
watchers.RemoveAll(x => x.key == key);
}
static Cache<string, List<Actor>> GatherBuildings( Player player )
{
var ret = new Cache<string, List<Actor>>( x => new List<Actor>() );
if (player == null)
return ret;
foreach( var b in player.World.Queries.OwnedBy[player].Where( x=>x.Info.Traits.Contains<BuildingInfo>() ) )
{
ret[ b.Info.Name ].Add( b );
var tt = b.Info.Traits.GetOrDefault<TooltipInfo>();
if( tt != null )
foreach( var alt in tt.AlternateName )
ret[ alt ].Add( b );
}
return ret;
}
class Watcher
{
public readonly string key;
// strings may be either actor type, or "alternate name" key
public readonly List<string> prerequisites;
public readonly ITechTreeElement watcher;
bool hasPrerequisites;
public Watcher(string key, List<string> prerequisites, ITechTreeElement watcher)
{
this.key = key;
this.prerequisites = prerequisites;
this.watcher = watcher;
this.hasPrerequisites = false;
}
public void Update(Cache<string, List<Actor>> buildings)
{
var nowHasPrerequisites = true;
foreach (var p in prerequisites)
if (!buildings.Keys.Contains(p))
{
nowHasPrerequisites = false;
break;
}
if( nowHasPrerequisites && !hasPrerequisites )
watcher.PrerequisitesAvailable(key);
if( !nowHasPrerequisites && hasPrerequisites )
watcher.PrerequisitesUnavailable(key);
hasPrerequisites = nowHasPrerequisites;
}
}
}
public interface ITechTreeElement
{
void PrerequisitesAvailable(string key);
void PrerequisitesUnavailable(string key);
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public class TechTreeInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new TechTree(init);}
}
public class TechTree
{
readonly List<Watcher> watchers = new List<Watcher>();
readonly Player player;
public TechTree(ActorInitializer init)
{
player = init.self.Owner;
init.world.ActorAdded += ActorChanged;
init.world.ActorRemoved += ActorChanged;
}
public void ActorChanged(Actor a)
{
if (a.Owner == player && a.HasTrait<Building>())
Update();
}
public void Update()
{
var buildings = GatherBuildings(player);
foreach(var w in watchers)
w.Update(buildings);
}
public void Add(string key, List<string> prerequisites, ITechTreeElement tte)
{
watchers.Add(new Watcher( key, prerequisites, tte ));
}
public void Remove(string key)
{
watchers.RemoveAll(x => x.key == key);
}
static Cache<string, List<Actor>> GatherBuildings( Player player )
{
var ret = new Cache<string, List<Actor>>( x => new List<Actor>() );
if (player == null)
return ret;
foreach( var b in player.World.Queries.OwnedBy[player].Where( x=>x.Info.Traits.Contains<BuildingInfo>() ) )
{
ret[ b.Info.Name ].Add( b );
var tt = b.Info.Traits.GetOrDefault<TooltipInfo>();
if( tt != null )
foreach( var alt in tt.AlternateName )
ret[ alt ].Add( b );
}
return ret;
}
class Watcher
{
public readonly string key;
// strings may be either actor type, or "alternate name" key
public readonly List<string> prerequisites;
public readonly ITechTreeElement watcher;
bool hasPrerequisites;
public Watcher(string key, List<string> prerequisites, ITechTreeElement watcher)
{
this.key = key;
this.prerequisites = prerequisites;
this.watcher = watcher;
this.hasPrerequisites = false;
}
public void Update(Cache<string, List<Actor>> buildings)
{
var nowHasPrerequisites = true;
foreach (var p in prerequisites)
if (!buildings.Keys.Contains(p))
{
nowHasPrerequisites = false;
break;
}
if( nowHasPrerequisites && !hasPrerequisites )
watcher.PrerequisitesAvailable(key);
if( !nowHasPrerequisites && hasPrerequisites )
watcher.PrerequisitesUnavailable(key);
hasPrerequisites = nowHasPrerequisites;
}
}
}
public interface ITechTreeElement
{
void PrerequisitesAvailable(string key);
void PrerequisitesUnavailable(string key);
}
}

View File

@@ -1,80 +1,80 @@
#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.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public static class BuildingUtils
{
public static bool IsCellBuildable(this World world, int2 a, bool waterBound)
{
return world.IsCellBuildable(a, waterBound, null);
}
public static bool IsCellBuildable(this World world, int2 a, bool waterBound, Actor toIgnore)
{
if (world.WorldActor.Trait<BuildingInfluence>().GetBuildingAt(a) != null) return false;
if (world.WorldActor.Trait<UnitInfluence>().GetUnitsAt(a).Any(b => b != toIgnore)) return false;
if (waterBound)
return world.Map.IsInMap(a.X,a.Y) && world.GetTerrainInfo(a).IsWater;
return world.Map.IsInMap(a.X, a.Y) && world.GetTerrainInfo(a).Buildable;
}
public static bool CanPlaceBuilding(this World world, string name, BuildingInfo building, int2 topLeft, Actor toIgnore)
{
var res = world.WorldActor.Trait<ResourceLayer>();
return FootprintUtils.Tiles(name, building, topLeft).All(
t => world.Map.IsInMap(t.X, t.Y) && res.GetResource(t) == null &&
world.IsCellBuildable(t, building.WaterBound, toIgnore));
}
public static IEnumerable<int2> GetLineBuildCells(World world, int2 location, string name, BuildingInfo bi)
{
int range = Rules.Info[name].Traits.Get<LineBuildInfo>().Range;
var topLeft = location; // 1x1 assumption!
if (world.IsCellBuildable(topLeft, bi.WaterBound))
yield return topLeft;
// Start at place location, search outwards
// TODO: First make it work, then make it nice
var vecs = new[] { new int2(1, 0), new int2(0, 1), new int2(-1, 0), new int2(0, -1) };
int[] dirs = { 0, 0, 0, 0 };
for (int d = 0; d < 4; d++)
{
for (int i = 1; i < range; i++)
{
if (dirs[d] != 0)
continue;
int2 cell = topLeft + i * vecs[d];
if (world.IsCellBuildable(cell, bi.WaterBound))
continue; // Cell is empty; continue search
// Cell contains an actor. Is it the type we want?
if (world.Queries.WithTrait<LineBuild>().Any(a => (a.Actor.Info.Name == name && a.Actor.Location.X == cell.X && a.Actor.Location.Y == cell.Y)))
dirs[d] = i; // Cell contains actor of correct type
else
dirs[d] = -1; // Cell is blocked by another actor type
}
// Place intermediate-line sections
if (dirs[d] > 0)
for (int i = 1; i < dirs[d]; i++)
yield return topLeft + i * vecs[d];
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public static class BuildingUtils
{
public static bool IsCellBuildable(this World world, int2 a, bool waterBound)
{
return world.IsCellBuildable(a, waterBound, null);
}
public static bool IsCellBuildable(this World world, int2 a, bool waterBound, Actor toIgnore)
{
if (world.WorldActor.Trait<BuildingInfluence>().GetBuildingAt(a) != null) return false;
if (world.WorldActor.Trait<UnitInfluence>().GetUnitsAt(a).Any(b => b != toIgnore)) return false;
if (waterBound)
return world.Map.IsInMap(a.X,a.Y) && world.GetTerrainInfo(a).IsWater;
return world.Map.IsInMap(a.X, a.Y) && world.GetTerrainInfo(a).Buildable;
}
public static bool CanPlaceBuilding(this World world, string name, BuildingInfo building, int2 topLeft, Actor toIgnore)
{
var res = world.WorldActor.Trait<ResourceLayer>();
return FootprintUtils.Tiles(name, building, topLeft).All(
t => world.Map.IsInMap(t.X, t.Y) && res.GetResource(t) == null &&
world.IsCellBuildable(t, building.WaterBound, toIgnore));
}
public static IEnumerable<int2> GetLineBuildCells(World world, int2 location, string name, BuildingInfo bi)
{
int range = Rules.Info[name].Traits.Get<LineBuildInfo>().Range;
var topLeft = location; // 1x1 assumption!
if (world.IsCellBuildable(topLeft, bi.WaterBound))
yield return topLeft;
// Start at place location, search outwards
// TODO: First make it work, then make it nice
var vecs = new[] { new int2(1, 0), new int2(0, 1), new int2(-1, 0), new int2(0, -1) };
int[] dirs = { 0, 0, 0, 0 };
for (int d = 0; d < 4; d++)
{
for (int i = 1; i < range; i++)
{
if (dirs[d] != 0)
continue;
int2 cell = topLeft + i * vecs[d];
if (world.IsCellBuildable(cell, bi.WaterBound))
continue; // Cell is empty; continue search
// Cell contains an actor. Is it the type we want?
if (world.Queries.WithTrait<LineBuild>().Any(a => (a.Actor.Info.Name == name && a.Actor.Location.X == cell.X && a.Actor.Location.Y == cell.Y)))
dirs[d] = i; // Cell contains actor of correct type
else
dirs[d] = -1; // Cell is blocked by another actor type
}
// Place intermediate-line sections
if (dirs[d] > 0)
for (int i = 1; i < dirs[d]; i++)
yield return topLeft + i * vecs[d];
}
}
}
}

View File

@@ -1,41 +1,41 @@
#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.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public class WallInfo : ITraitInfo, ITraitPrerequisite<BuildingInfo>
{
public readonly string[] CrushClasses = { };
public readonly string CrushSound;
public object Create(ActorInitializer init) { return new Wall(init.self, this); }
}
public class Wall : ICrushable, IBlocksBullets
{
readonly Actor self;
readonly WallInfo info;
public Wall(Actor self, WallInfo info)
{
this.self = self;
this.info = info;
}
public IEnumerable<string> CrushClasses { get { return info.CrushClasses; } }
public void OnCrush(Actor crusher)
{
self.Kill(crusher);
Sound.Play(info.CrushSound, self.CenterLocation);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public class WallInfo : ITraitInfo, ITraitPrerequisite<BuildingInfo>
{
public readonly string[] CrushClasses = { };
public readonly string CrushSound;
public object Create(ActorInitializer init) { return new Wall(init.self, this); }
}
public class Wall : ICrushable, IBlocksBullets
{
readonly Actor self;
readonly WallInfo info;
public Wall(Actor self, WallInfo info)
{
this.self = self;
this.info = info;
}
public IEnumerable<string> CrushClasses { get { return info.CrushClasses; } }
public void OnCrush(Actor crusher)
{
self.Kill(crusher);
Sound.Play(info.CrushSound, self.CenterLocation);
}
}
}

View File

@@ -1,48 +1,48 @@
#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 OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class BurnsInfo : TraitInfo<Burns>
{
public readonly string Anim = "1";
public readonly int Damage = 1;
public readonly int Interval = 8;
}
class Burns : ITick, ISync
{
[Sync]
int ticks;
bool isSetup;
public void Tick(Actor self)
{
if (!isSetup)
{
isSetup = true;
var anim = new Animation("fire", () => 0);
anim.PlayRepeating(self.Info.Traits.Get<BurnsInfo>().Anim);
self.Trait<RenderSimple>().anims.Add("fire",
new RenderSimple.AnimationWithOffset(anim, () => new float2(0, -3), null));
}
if (--ticks <= 0)
{
self.InflictDamage(self, self.Info.Traits.Get<BurnsInfo>().Damage, null);
ticks = self.Info.Traits.Get<BurnsInfo>().Interval;
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class BurnsInfo : TraitInfo<Burns>
{
public readonly string Anim = "1";
public readonly int Damage = 1;
public readonly int Interval = 8;
}
class Burns : ITick, ISync
{
[Sync]
int ticks;
bool isSetup;
public void Tick(Actor self)
{
if (!isSetup)
{
isSetup = true;
var anim = new Animation("fire", () => 0);
anim.PlayRepeating(self.Info.Traits.Get<BurnsInfo>().Anim);
self.Trait<RenderSimple>().anims.Add("fire",
new RenderSimple.AnimationWithOffset(anim, () => new float2(0, -3), null));
}
if (--ticks <= 0)
{
self.InflictDamage(self, self.Info.Traits.Get<BurnsInfo>().Damage, null);
ticks = self.Info.Traits.Get<BurnsInfo>().Interval;
}
}
}
}

View File

@@ -1,62 +1,62 @@
#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.Collections.Generic;
using System.Drawing;
using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Move;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class C4DemolitionInfo : TraitInfo<C4Demolition>
{
public readonly float C4Delay = 0;
}
class C4Demolition : IIssueOrder, IResolveOrder, IOrderVoice
{
public IEnumerable<IOrderTargeter> Orders
{
get { yield return new UnitTraitOrderTargeter<Building>( "C4", 6, "c4", true, false ); }
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{
if( order.OrderID == "C4" )
return new Order("C4", self, queued) { TargetActor = target.Actor };
return null;
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "C4")
{
self.SetTargetLine(Target.FromOrder(order), Color.Red);
var mobile = self.Trait<Mobile>();
self.CancelActivity();
self.QueueActivity(new Enter(order.TargetActor));
//self.QueueActivity(new Move(order.TargetActor.Location, order.TargetActor));
self.QueueActivity(new Demolish(order.TargetActor));
self.QueueActivity(mobile.MoveTo(self.Location, 0));
}
}
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "C4") ? "Attack" : null;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Move;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class C4DemolitionInfo : TraitInfo<C4Demolition>
{
public readonly float C4Delay = 0;
}
class C4Demolition : IIssueOrder, IResolveOrder, IOrderVoice
{
public IEnumerable<IOrderTargeter> Orders
{
get { yield return new UnitTraitOrderTargeter<Building>( "C4", 6, "c4", true, false ); }
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{
if( order.OrderID == "C4" )
return new Order("C4", self, queued) { TargetActor = target.Actor };
return null;
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "C4")
{
self.SetTargetLine(Target.FromOrder(order), Color.Red);
var mobile = self.Trait<Mobile>();
self.CancelActivity();
self.QueueActivity(new Enter(order.TargetActor));
//self.QueueActivity(new Move(order.TargetActor.Location, order.TargetActor));
self.QueueActivity(new Demolish(order.TargetActor));
self.QueueActivity(mobile.MoveTo(self.Location, 0));
}
}
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "C4") ? "Attack" : null;
}
}
}

View File

@@ -1,158 +1,158 @@
#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.Collections.Generic;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CargoInfo : ITraitInfo
{
public readonly int Passengers = 0;
public readonly string[] Types = { };
public readonly int UnloadFacing = 0;
public object Create( ActorInitializer init ) { return new Cargo( init.self ); }
}
public class Cargo : IPips, IIssueOrder, IResolveOrder, IOrderVoice, INotifyDamage
{
readonly Actor self;
List<Actor> cargo = new List<Actor>();
public IEnumerable<Actor> Passengers { get { return cargo; } }
public Cargo( Actor self )
{
this.self = self;
}
public IEnumerable<IOrderTargeter> Orders
{
get
{
yield return new DeployOrderTargeter( "Unload", 10, () => CanUnload( self ) );
yield return new UnitTraitOrderTargeter<Passenger>( "ReverseEnterTransport", 6, null, false, true );
}
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{
if( order.OrderID == "Unload" )
return new Order( order.OrderID, self, queued );
if( order.OrderID == "ReverseEnterTransport" )
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
return null;
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Unload")
{
if (!CanUnload(self))
return;
self.CancelActivity();
self.QueueActivity(new UnloadCargo());
}
if( order.OrderString == "ReverseEnterTransport" )
{
if( order.TargetActor != null && order.Subject.Owner == order.TargetActor.Owner )
{
var passenger = order.TargetActor.Trait<Passenger>();
passenger.ResolveOrder(order.TargetActor,
new Order("EnterTransport", order.TargetActor, false) { TargetActor = self });
}
}
}
bool CanUnload(Actor self)
{
if (IsEmpty(self))
return false;
// Cannot unload mid-air
var move = self.TraitOrDefault<IMove>();
if (move != null && move.Altitude > 0)
return false;
// Todo: Check if there is a free tile to unload to
return true;
}
public string CursorForOrder(Actor self, Order order)
{
if (order.OrderString != "Unload") return null;
return CanUnload(self) ? "deploy" : "deploy-blocked";
}
public string VoicePhraseForOrder(Actor self, Order order)
{
if (order.OrderString != "Unload" || IsEmpty(self)) return null;
return "Move";
}
public bool IsFull(Actor self)
{
return cargo.Count == self.Info.Traits.Get<CargoInfo>().Passengers;
}
public bool IsEmpty(Actor self)
{
return cargo.Count == 0;
}
public Actor Peek(Actor self)
{
return cargo[0];
}
public Actor Unload(Actor self)
{
var a = cargo[0];
cargo.RemoveAt(0);
return a;
}
public IEnumerable<PipType> GetPips( Actor self )
{
var numPips = self.Info.Traits.Get<CargoInfo>().Passengers;
for (var i = 0; i < numPips; i++)
if (i >= cargo.Count)
yield return PipType.Transparent;
else
yield return GetPipForPassenger(cargo[i]);
}
static PipType GetPipForPassenger(Actor a)
{
return a.Trait<Passenger>().ColorOfCargoPip( a );
}
public void Load(Actor self, Actor a)
{
cargo.Add(a);
}
public void Damaged(Actor self, AttackInfo e)
{
if( e.DamageStateChanged && e.DamageState == DamageState.Dead )
{
foreach( var c in cargo )
c.Destroy();
cargo.Clear();
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CargoInfo : ITraitInfo
{
public readonly int Passengers = 0;
public readonly string[] Types = { };
public readonly int UnloadFacing = 0;
public object Create( ActorInitializer init ) { return new Cargo( init.self ); }
}
public class Cargo : IPips, IIssueOrder, IResolveOrder, IOrderVoice, INotifyDamage
{
readonly Actor self;
List<Actor> cargo = new List<Actor>();
public IEnumerable<Actor> Passengers { get { return cargo; } }
public Cargo( Actor self )
{
this.self = self;
}
public IEnumerable<IOrderTargeter> Orders
{
get
{
yield return new DeployOrderTargeter( "Unload", 10, () => CanUnload( self ) );
yield return new UnitTraitOrderTargeter<Passenger>( "ReverseEnterTransport", 6, null, false, true );
}
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{
if( order.OrderID == "Unload" )
return new Order( order.OrderID, self, queued );
if( order.OrderID == "ReverseEnterTransport" )
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
return null;
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Unload")
{
if (!CanUnload(self))
return;
self.CancelActivity();
self.QueueActivity(new UnloadCargo());
}
if( order.OrderString == "ReverseEnterTransport" )
{
if( order.TargetActor != null && order.Subject.Owner == order.TargetActor.Owner )
{
var passenger = order.TargetActor.Trait<Passenger>();
passenger.ResolveOrder(order.TargetActor,
new Order("EnterTransport", order.TargetActor, false) { TargetActor = self });
}
}
}
bool CanUnload(Actor self)
{
if (IsEmpty(self))
return false;
// Cannot unload mid-air
var move = self.TraitOrDefault<IMove>();
if (move != null && move.Altitude > 0)
return false;
// Todo: Check if there is a free tile to unload to
return true;
}
public string CursorForOrder(Actor self, Order order)
{
if (order.OrderString != "Unload") return null;
return CanUnload(self) ? "deploy" : "deploy-blocked";
}
public string VoicePhraseForOrder(Actor self, Order order)
{
if (order.OrderString != "Unload" || IsEmpty(self)) return null;
return "Move";
}
public bool IsFull(Actor self)
{
return cargo.Count == self.Info.Traits.Get<CargoInfo>().Passengers;
}
public bool IsEmpty(Actor self)
{
return cargo.Count == 0;
}
public Actor Peek(Actor self)
{
return cargo[0];
}
public Actor Unload(Actor self)
{
var a = cargo[0];
cargo.RemoveAt(0);
return a;
}
public IEnumerable<PipType> GetPips( Actor self )
{
var numPips = self.Info.Traits.Get<CargoInfo>().Passengers;
for (var i = 0; i < numPips; i++)
if (i >= cargo.Count)
yield return PipType.Transparent;
else
yield return GetPipForPassenger(cargo[i]);
}
static PipType GetPipForPassenger(Actor a)
{
return a.Trait<Passenger>().ColorOfCargoPip( a );
}
public void Load(Actor self, Actor a)
{
cargo.Add(a);
}
public void Damaged(Actor self, AttackInfo e)
{
if( e.DamageStateChanged && e.DamageState == DamageState.Dead )
{
foreach( var c in cargo )
c.Destroy();
cargo.Clear();
}
}
}
}

View File

@@ -1,64 +1,64 @@
#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 OpenRA.GameRules;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class CarpetBombInfo : TraitInfo<CarpetBomb>
{
[WeaponReference]
public readonly string Weapon = null;
public readonly int Range = 3;
}
class CarpetBomb : ITick // todo: maybe integrate this better with the normal weapons system?
{
int2 Target;
int dropDelay;
public void SetTarget(int2 targetCell) { Target = targetCell; }
public void Tick(Actor self)
{
var info = self.Info.Traits.Get<CarpetBombInfo>();
if( !Combat.IsInRange( self.CenterLocation, info.Range, Target * Game.CellSize ) )
return;
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if (limitedAmmo != null && !limitedAmmo.HasAmmo())
return;
if (--dropDelay <= 0)
{
var weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()];
dropDelay = weapon.ROF;
var args = new ProjectileArgs
{
srcAltitude = self.Trait<IMove>().Altitude,
destAltitude = 0,
src = self.CenterLocation,
dest = self.CenterLocation,
facing = self.Trait<IFacing>().Facing,
firedBy = self,
weapon = weapon
};
self.World.Add(args.weapon.Projectile.Create(args));
if (!string.IsNullOrEmpty(args.weapon.Report))
Sound.Play(args.weapon.Report + ".aud", self.CenterLocation);
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.GameRules;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class CarpetBombInfo : TraitInfo<CarpetBomb>
{
[WeaponReference]
public readonly string Weapon = null;
public readonly int Range = 3;
}
class CarpetBomb : ITick // todo: maybe integrate this better with the normal weapons system?
{
int2 Target;
int dropDelay;
public void SetTarget(int2 targetCell) { Target = targetCell; }
public void Tick(Actor self)
{
var info = self.Info.Traits.Get<CarpetBombInfo>();
if( !Combat.IsInRange( self.CenterLocation, info.Range, Target * Game.CellSize ) )
return;
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if (limitedAmmo != null && !limitedAmmo.HasAmmo())
return;
if (--dropDelay <= 0)
{
var weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()];
dropDelay = weapon.ROF;
var args = new ProjectileArgs
{
srcAltitude = self.Trait<IMove>().Altitude,
destAltitude = 0,
src = self.CenterLocation,
dest = self.CenterLocation,
facing = self.Trait<IFacing>().Facing,
firedBy = self,
weapon = weapon
};
self.World.Add(args.weapon.Projectile.Create(args));
if (!string.IsNullOrEmpty(args.weapon.Report))
Sound.Play(args.weapon.Report + ".aud", self.CenterLocation);
}
}
}
}

View File

@@ -1,36 +1,36 @@
#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 OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class CashTricklerInfo : TraitInfo<CashTrickler>
{
public readonly int Period = 10;
public readonly int Amount = 3;
}
class CashTrickler : ITick, ISync
{
[Sync]
int ticks;
public void Tick(Actor self)
{
if (--ticks < 0)
{
var info = self.Info.Traits.Get<CashTricklerInfo>();
self.Owner.PlayerActor.Trait<PlayerResources>().GiveCash(info.Amount);
ticks = info.Period;
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class CashTricklerInfo : TraitInfo<CashTrickler>
{
public readonly int Period = 10;
public readonly int Amount = 3;
}
class CashTrickler : ITick, ISync
{
[Sync]
int ticks;
public void Tick(Actor self)
{
if (--ticks < 0)
{
var info = self.Info.Traits.Get<CashTricklerInfo>();
self.Owner.PlayerActor.Trait<PlayerResources>().GiveCash(info.Amount);
ticks = info.Period;
}
}
}
}

View File

@@ -1,105 +1,105 @@
#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.Collections.Generic;
using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class ChronoshiftDeployInfo : TraitInfo<ChronoshiftDeploy>
{
public readonly int ChargeTime = 120; // Seconds
}
class ChronoshiftDeploy : IIssueOrder, IResolveOrder, ITick, IPips, IOrderVoice, ISync
{
// Recharge logic
[Sync]
int chargeTick = 0; // How long until we can chronoshift again?
public void Tick(Actor self)
{
if (chargeTick > 0)
chargeTick--;
}
public IEnumerable<IOrderTargeter> Orders
{
get { yield return new DeployOrderTargeter( "ChronoshiftDeploy", 5, () => chargeTick <= 0 ); }
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{
if( order.OrderID == "ChronoshiftDeploy" )
if (chargeTick <= 0)
self.World.OrderGenerator = new SetChronoTankDestination( self );
return null;
}
public void ResolveOrder(Actor self, Order order)
{
var movement = self.TraitOrDefault<IMove>();
if (order.OrderString == "ChronoshiftSelf" && movement.CanEnterCell(order.TargetLocation))
{
if (self.Owner == self.World.LocalPlayer)
{
self.World.CancelInputMode();
}
self.CancelActivity();
self.QueueActivity(new Teleport(order.TargetLocation));
Sound.Play("chrotnk1.aud", self.CenterLocation);
Sound.Play("chrotnk1.aud", Game.CellSize * order.TargetLocation.ToFloat2());
chargeTick = 25 * self.Info.Traits.Get<ChronoshiftDeployInfo>().ChargeTime;
foreach (var a in self.World.Queries.WithTrait<ChronoshiftPaletteEffect>())
a.Trait.Enable();
}
}
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "ChronoshiftDeploy" && chargeTick <= 0) ? "Move" : null;
}
// Display 5 pips indicating the current charge status
public IEnumerable<PipType> GetPips(Actor self)
{
const int numPips = 5;
for (int i = 0; i < numPips; i++)
{
if ((1 - chargeTick * 1.0f / (25 * self.Info.Traits.Get<ChronoshiftDeployInfo>().ChargeTime)) * numPips < i + 1)
{
yield return PipType.Transparent;
continue;
}
switch (i)
{
case 0:
case 1:
yield return PipType.Red;
break;
case 2:
case 3:
yield return PipType.Yellow;
break;
case 4:
yield return PipType.Green;
break;
}
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class ChronoshiftDeployInfo : TraitInfo<ChronoshiftDeploy>
{
public readonly int ChargeTime = 120; // Seconds
}
class ChronoshiftDeploy : IIssueOrder, IResolveOrder, ITick, IPips, IOrderVoice, ISync
{
// Recharge logic
[Sync]
int chargeTick = 0; // How long until we can chronoshift again?
public void Tick(Actor self)
{
if (chargeTick > 0)
chargeTick--;
}
public IEnumerable<IOrderTargeter> Orders
{
get { yield return new DeployOrderTargeter( "ChronoshiftDeploy", 5, () => chargeTick <= 0 ); }
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{
if( order.OrderID == "ChronoshiftDeploy" )
if (chargeTick <= 0)
self.World.OrderGenerator = new SetChronoTankDestination( self );
return null;
}
public void ResolveOrder(Actor self, Order order)
{
var movement = self.TraitOrDefault<IMove>();
if (order.OrderString == "ChronoshiftSelf" && movement.CanEnterCell(order.TargetLocation))
{
if (self.Owner == self.World.LocalPlayer)
{
self.World.CancelInputMode();
}
self.CancelActivity();
self.QueueActivity(new Teleport(order.TargetLocation));
Sound.Play("chrotnk1.aud", self.CenterLocation);
Sound.Play("chrotnk1.aud", Game.CellSize * order.TargetLocation.ToFloat2());
chargeTick = 25 * self.Info.Traits.Get<ChronoshiftDeployInfo>().ChargeTime;
foreach (var a in self.World.Queries.WithTrait<ChronoshiftPaletteEffect>())
a.Trait.Enable();
}
}
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "ChronoshiftDeploy" && chargeTick <= 0) ? "Move" : null;
}
// Display 5 pips indicating the current charge status
public IEnumerable<PipType> GetPips(Actor self)
{
const int numPips = 5;
for (int i = 0; i < numPips; i++)
{
if ((1 - chargeTick * 1.0f / (25 * self.Info.Traits.Get<ChronoshiftDeployInfo>().ChargeTime)) * numPips < i + 1)
{
yield return PipType.Transparent;
continue;
}
switch (i)
{
case 0:
case 1:
yield return PipType.Red;
break;
case 2:
case 3:
yield return PipType.Yellow;
break;
case 4:
yield return PipType.Green;
break;
}
}
}
}
}

View File

@@ -1,58 +1,58 @@
#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.Collections.Generic;
using System.Drawing;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class ChronoshiftPaletteEffectInfo : TraitInfo<ChronoshiftPaletteEffect> { }
public class ChronoshiftPaletteEffect : IPaletteModifier, ITick
{
const int chronoEffectLength = 20;
int remainingFrames;
public void Enable()
{
remainingFrames = chronoEffectLength;
}
public void Tick(Actor self)
{
if (remainingFrames > 0)
remainingFrames--;
}
public void AdjustPalette(Dictionary<string,Palette> palettes)
{
if (remainingFrames == 0)
return;
var frac = (float)remainingFrames / chronoEffectLength;
var excludePalettes = new List<string>(){"cursor", "chrome", "colorpicker", "shroud", "fog"};
foreach (var pal in palettes)
{
if (excludePalettes.Contains(pal.Key))
continue;
for (var x = 0; x < 256; x++)
{
var orig = pal.Value.GetColor(x);
var lum = (int)(255 * orig.GetBrightness());
var desat = Color.FromArgb(orig.A, lum, lum, lum);
pal.Value.SetColor(x, OpenRA.Graphics.Util.Lerp(frac, orig, desat));
}
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class ChronoshiftPaletteEffectInfo : TraitInfo<ChronoshiftPaletteEffect> { }
public class ChronoshiftPaletteEffect : IPaletteModifier, ITick
{
const int chronoEffectLength = 20;
int remainingFrames;
public void Enable()
{
remainingFrames = chronoEffectLength;
}
public void Tick(Actor self)
{
if (remainingFrames > 0)
remainingFrames--;
}
public void AdjustPalette(Dictionary<string,Palette> palettes)
{
if (remainingFrames == 0)
return;
var frac = (float)remainingFrames / chronoEffectLength;
var excludePalettes = new List<string>(){"cursor", "chrome", "colorpicker", "shroud", "fog"};
foreach (var pal in palettes)
{
if (excludePalettes.Contains(pal.Key))
continue;
for (var x = 0; x < 256; x++)
{
var orig = pal.Value.GetColor(x);
var lum = (int)(255 * orig.GetBrightness());
var desat = Color.FromArgb(orig.A, lum, lum, lum);
pal.Value.SetColor(x, OpenRA.Graphics.Util.Lerp(frac, orig, desat));
}
}
}
}
}

View File

@@ -1,77 +1,77 @@
#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 OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class ChronoshiftableInfo : TraitInfo<Chronoshiftable> { }
public class Chronoshiftable : ITick, ISync
{
// Return-to-sender logic
[Sync]
int2 chronoshiftOrigin;
[Sync]
int chronoshiftReturnTicks = 0;
public void Tick(Actor self)
{
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 Teleport(chronoshiftOrigin));
}
}
// Can't be used in synced code, except with ignoreVis.
public virtual bool CanChronoshiftTo(Actor self, int2 targetLocation, bool ignoreVis)
{
// Todo: Allow enemy units to be chronoshifted into bad terrain to kill them
return self.HasTrait<ITeleportable>() &&
self.Trait<ITeleportable>().CanEnterCell(targetLocation) &&
(ignoreVis || self.World.LocalShroud.IsExplored(targetLocation));
}
public virtual bool Teleport(Actor self, int2 targetLocation, int duration, bool killCargo, Actor chronosphere)
{
/// Set up return-to-sender info
chronoshiftOrigin = self.Location;
chronoshiftReturnTicks = duration;
// Kill cargo
if (killCargo && self.HasTrait<Cargo>())
{
var cargo = self.Trait<Cargo>();
while (!cargo.IsEmpty(self))
{
chronosphere.Owner.Kills++;
var a = cargo.Unload(self);
a.Owner.Deaths++;
}
}
// Set up the teleport
self.CancelActivity();
self.QueueActivity(new Teleport(targetLocation));
return true;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class ChronoshiftableInfo : TraitInfo<Chronoshiftable> { }
public class Chronoshiftable : ITick, ISync
{
// Return-to-sender logic
[Sync]
int2 chronoshiftOrigin;
[Sync]
int chronoshiftReturnTicks = 0;
public void Tick(Actor self)
{
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 Teleport(chronoshiftOrigin));
}
}
// Can't be used in synced code, except with ignoreVis.
public virtual bool CanChronoshiftTo(Actor self, int2 targetLocation, bool ignoreVis)
{
// Todo: Allow enemy units to be chronoshifted into bad terrain to kill them
return self.HasTrait<ITeleportable>() &&
self.Trait<ITeleportable>().CanEnterCell(targetLocation) &&
(ignoreVis || self.World.LocalShroud.IsExplored(targetLocation));
}
public virtual bool Teleport(Actor self, int2 targetLocation, int duration, bool killCargo, Actor chronosphere)
{
/// Set up return-to-sender info
chronoshiftOrigin = self.Location;
chronoshiftReturnTicks = duration;
// Kill cargo
if (killCargo && self.HasTrait<Cargo>())
{
var cargo = self.Trait<Cargo>();
while (!cargo.IsEmpty(self))
{
chronosphere.Owner.Kills++;
var a = cargo.Unload(self);
a.Owner.Deaths++;
}
}
// Set up the teleport
self.CancelActivity();
self.QueueActivity(new Teleport(targetLocation));
return true;
}
}
}

View File

@@ -1,126 +1,126 @@
#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 System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CloakInfo : ITraitInfo
{
public readonly float InitialDelay = .4f; // seconds
public readonly float CloakDelay = 1.2f; // Seconds
public readonly string CloakSound = "subshow1.aud";
public readonly string UncloakSound = "subshow1.aud";
public CloakInfo() { } /* only because we have other ctors */
/* for CloakCrateAction */
public CloakInfo(float initialDelay, float cloakDelay, string cloakSound, string uncloakSound)
{
InitialDelay = initialDelay;
CloakDelay = cloakDelay;
CloakSound = cloakSound;
UncloakSound = uncloakSound;
}
public object Create(ActorInitializer init) { return new Cloak(init.self, this); }
}
public class Cloak : IRenderModifier, INotifyDamage, INotifyAttack, ITick, IVisibilityModifier, IRadarColorModifier, ISync
{
[Sync]
int remainingTime;
[Sync]
bool canCloak = true;
Actor self;
CloakInfo info;
public Cloak(Actor self, CloakInfo info)
{
this.info = info;
this.self = self;
remainingTime = (int)(info.InitialDelay * 25);
}
void DoUncloak()
{
if (remainingTime <= 0)
OnCloak();
remainingTime = Math.Max(remainingTime, (int)(info.CloakDelay * 25));
}
public void Attacking(Actor self, Target target) { DoUncloak(); }
public void Damaged(Actor self, AttackInfo e)
{
canCloak = (e.DamageState < DamageState.Critical);
if (Cloaked && !canCloak)
DoUncloak();
}
public IEnumerable<Renderable>
ModifyRender(Actor self, IEnumerable<Renderable> rs)
{
if (remainingTime > 0)
return rs;
if (Cloaked && IsVisible(self))
return rs.Select(a => a.WithPalette("shadow"));
else
return new Renderable[] { };
}
public void Tick(Actor self)
{
if (remainingTime > 0 && canCloak)
if (--remainingTime <= 0)
OnCloak();
}
void OnUncloak()
{
Sound.Play(info.UncloakSound, self.CenterLocation);
}
void OnCloak()
{
Sound.Play(info.CloakSound, self.CenterLocation);
}
public bool Cloaked { get { return remainingTime == 0; } }
public bool IsVisible(Actor self)
{
if (!Cloaked || self.Owner == self.World.LocalPlayer || self.Owner.Stances[self.World.LocalPlayer] == Stance.Ally)
return true;
return self.World.Queries.WithTrait<DetectCloaked>().Any(a => (self.Location - a.Actor.Location).Length < a.Actor.Info.Traits.Get<DetectCloakedInfo>().Range);
}
public Color RadarColorOverride(Actor self)
{
var c = self.Owner.ColorRamp.GetColor(0);
if (self.Owner == self.World.LocalPlayer && Cloaked)
c = Color.FromArgb(128, c);
return c;
}
public void Decloak(int time)
{
DoUncloak();
remainingTime = Math.Max(remainingTime, time);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CloakInfo : ITraitInfo
{
public readonly float InitialDelay = .4f; // seconds
public readonly float CloakDelay = 1.2f; // Seconds
public readonly string CloakSound = "subshow1.aud";
public readonly string UncloakSound = "subshow1.aud";
public CloakInfo() { } /* only because we have other ctors */
/* for CloakCrateAction */
public CloakInfo(float initialDelay, float cloakDelay, string cloakSound, string uncloakSound)
{
InitialDelay = initialDelay;
CloakDelay = cloakDelay;
CloakSound = cloakSound;
UncloakSound = uncloakSound;
}
public object Create(ActorInitializer init) { return new Cloak(init.self, this); }
}
public class Cloak : IRenderModifier, INotifyDamage, INotifyAttack, ITick, IVisibilityModifier, IRadarColorModifier, ISync
{
[Sync]
int remainingTime;
[Sync]
bool canCloak = true;
Actor self;
CloakInfo info;
public Cloak(Actor self, CloakInfo info)
{
this.info = info;
this.self = self;
remainingTime = (int)(info.InitialDelay * 25);
}
void DoUncloak()
{
if (remainingTime <= 0)
OnCloak();
remainingTime = Math.Max(remainingTime, (int)(info.CloakDelay * 25));
}
public void Attacking(Actor self, Target target) { DoUncloak(); }
public void Damaged(Actor self, AttackInfo e)
{
canCloak = (e.DamageState < DamageState.Critical);
if (Cloaked && !canCloak)
DoUncloak();
}
public IEnumerable<Renderable>
ModifyRender(Actor self, IEnumerable<Renderable> rs)
{
if (remainingTime > 0)
return rs;
if (Cloaked && IsVisible(self))
return rs.Select(a => a.WithPalette("shadow"));
else
return new Renderable[] { };
}
public void Tick(Actor self)
{
if (remainingTime > 0 && canCloak)
if (--remainingTime <= 0)
OnCloak();
}
void OnUncloak()
{
Sound.Play(info.UncloakSound, self.CenterLocation);
}
void OnCloak()
{
Sound.Play(info.CloakSound, self.CenterLocation);
}
public bool Cloaked { get { return remainingTime == 0; } }
public bool IsVisible(Actor self)
{
if (!Cloaked || self.Owner == self.World.LocalPlayer || self.Owner.Stances[self.World.LocalPlayer] == Stance.Ally)
return true;
return self.World.Queries.WithTrait<DetectCloaked>().Any(a => (self.Location - a.Actor.Location).Length < a.Actor.Info.Traits.Get<DetectCloakedInfo>().Range);
}
public Color RadarColorOverride(Actor self)
{
var c = self.Owner.ColorRamp.GetColor(0);
if (self.Owner == self.World.LocalPlayer && Cloaked)
c = Color.FromArgb(128, c);
return c;
}
public void Decloak(int time)
{
DoUncloak();
remainingTime = Math.Max(remainingTime, time);
}
}
}

View File

@@ -1,18 +1,18 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Widgets.Delegates;
using OpenRA.Traits;
#endregion
using System.Collections.Generic;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Widgets.Delegates;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
@@ -21,17 +21,17 @@ namespace OpenRA.Mods.RA
class ColorPickerPaletteModifier : IPalette, IPaletteModifier
{
PaletteFormat format;
public void InitPalette( WorldRenderer wr )
{
public void InitPalette( WorldRenderer wr )
{
var info = Rules.Info["player"].Traits.Get<PlayerColorPaletteInfo>();
format = info.PaletteFormat;
wr.AddPalette("colorpicker", wr.GetPalette(info.BasePalette));
}
public void AdjustPalette(Dictionary<string, Palette> palettes)
{
palettes["colorpicker"] = new Palette(palettes["colorpicker"],
new PlayerColorRemap(LobbyDelegate.CurrentColorPreview, format));
}
}
public void AdjustPalette(Dictionary<string, Palette> palettes)
{
palettes["colorpicker"] = new Palette(palettes["colorpicker"],
new PlayerColorRemap(LobbyDelegate.CurrentColorPreview, format));
}
}
}

View File

@@ -1,248 +1,248 @@
#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 System.Linq;
using OpenRA.Effects;
using OpenRA.GameRules;
using OpenRA.Mods.RA.Effects;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public static class Combat /* some utility bits that are shared between various things */
{
static string GetImpactSound(WarheadInfo warhead, bool isWater)
{
if (isWater && warhead.WaterImpactSound != null)
return warhead.WaterImpactSound + ".aud";
if (warhead.ImpactSound != null)
return warhead.ImpactSound + ".aud";
return null;
}
public static void DoImpact(WarheadInfo warhead, ProjectileArgs args)
{
var world = args.firedBy.World;
var targetTile = Util.CellContaining(args.dest);
if (!world.Map.IsInMap(targetTile))
return;
var isWater = world.GetTerrainInfo(targetTile).IsWater;
var explosionType = isWater ? warhead.WaterExplosion : warhead.Explosion;
if (explosionType != null)
world.AddFrameEndTask(
w => w.Add(new Explosion(w, args.dest, explosionType, isWater, args.destAltitude)));
Sound.Play(GetImpactSound(warhead, isWater), args.dest);
if (warhead.SmudgeType != null)
{
var smudgeLayer = world.WorldActor.TraitsImplementing<SmudgeLayer>()
.FirstOrDefault(x => x.Info.Type == warhead.SmudgeType);
if (smudgeLayer == null)
throw new NotImplementedException("Unknown smudge type `{0}`".F(warhead.SmudgeType));
if (warhead.Size[0] > 0)
{
var smudgeCells = world.FindTilesInCircle(targetTile, warhead.Size[0]);
if (warhead.Size.Length == 2 )
smudgeCells = smudgeCells.Except(world.FindTilesInCircle(targetTile, warhead.Size[1])) ;
foreach (var sc in smudgeCells)
{
smudgeLayer.AddSmudge(sc);
if (warhead.Ore)
world.WorldActor.Trait<ResourceLayer>().Destroy(sc);
}
}
else
smudgeLayer.AddSmudge(targetTile);
}
if (warhead.Ore)
world.WorldActor.Trait<ResourceLayer>().Destroy(targetTile);
switch (warhead.DamageModel)
{
case DamageModel.Normal:
{
var maxSpread = warhead.Spread * (float)Math.Log(Math.Abs(warhead.Damage), 2);
var hitActors = world.FindUnitsInCircle(args.dest, maxSpread);
foreach (var victim in hitActors)
{
var damage = (int)GetDamageToInflict(victim, args, warhead, args.firepowerModifier);
victim.InflictDamage(args.firedBy, damage, warhead);
}
} break;
case DamageModel.PerCell:
{
foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
foreach (var unit in world.FindUnits(Game.CellSize * t, Game.CellSize * (t + new float2(1,1))))
unit.InflictDamage(args.firedBy,
(int)(warhead.Damage * warhead.EffectivenessAgainst(unit)), warhead);
} break;
}
}
public static void DoImpacts(ProjectileArgs args)
{
foreach (var warhead in args.weapon.Warheads)
{
Action a = () => DoImpact(warhead, args);
if (warhead.Delay > 0)
args.firedBy.World.AddFrameEndTask(
w => w.Add(new DelayedAction(warhead.Delay, a)));
else
a();
}
}
public static void DoExplosion(Actor attacker, string weapontype, int2 pos, int altitude)
{
var args = new ProjectileArgs
{
src = pos,
dest = pos,
srcAltitude = altitude,
destAltitude = altitude,
firedBy = attacker,
target = Target.FromPos(pos),
weapon = Rules.Weapons[ weapontype.ToLowerInvariant() ],
facing = 0
};
if (args.weapon.Report != null)
Sound.Play(args.weapon.Report + ".aud", pos);
DoImpacts(args);
}
static readonly float[] falloff =
{
1f, 0.3678795f, 0.1353353f, 0.04978707f,
0.01831564f, 0.006737947f, 0.002478752f, 0.000911882f
};
static float GetDamageFalloff(float x)
{
var u = (int)x;
if (u >= falloff.Length - 1) return 0;
var t = x - u;
return (falloff[u] * (1 - t)) + (falloff[u + 1] * t);
}
static float GetDamageToInflict(Actor target, ProjectileArgs args, WarheadInfo warhead, float modifier)
{
// don't hit air units with splash from ground explosions, etc
if (!WeaponValidForTarget(args.weapon, target)) return 0f;
var health = target.Info.Traits.GetOrDefault<HealthInfo>();
if( health == null ) return 0f;
var distance = (int)Math.Max(0, (target.CenterLocation - args.dest).Length - health.Radius);
var falloff = (float)GetDamageFalloff(distance / warhead.Spread);
var rawDamage = (float)(warhead.Damage * modifier * falloff);
var multiplier = (float)warhead.EffectivenessAgainst(target);
return (float)(rawDamage * multiplier);
}
public static bool WeaponValidForTarget(WeaponInfo weapon, Actor target)
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Effects;
using OpenRA.GameRules;
using OpenRA.Mods.RA.Effects;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public static class Combat /* some utility bits that are shared between various things */
{
static string GetImpactSound(WarheadInfo warhead, bool isWater)
{
var targetable = target.TraitOrDefault<ITargetable>();
if (targetable == null || !weapon.ValidTargets.Intersect(targetable.TargetTypes).Any())
return false;
if (weapon.Warheads.All( w => w.EffectivenessAgainst(target) <= 0))
return false;
return true;
}
public static bool WeaponValidForTarget( WeaponInfo weapon, World world, int2 location )
{
if( weapon.ValidTargets.Contains( "Ground" ) && world.GetTerrainType( location ) != "Water" ) return true;
if( weapon.ValidTargets.Contains( "Water" ) && world.GetTerrainType( location ) == "Water" ) return true;
return false;
}
static float2 GetRecoil(Actor self, float recoil)
{
var abInfo = self.Info.Traits.GetOrDefault<AttackBaseInfo>();
if (abInfo == null || abInfo.Recoil == 0) return float2.Zero;
var rut = self.TraitOrDefault<RenderUnitTurreted>();
if (rut == null) return float2.Zero;
var facing = self.Trait<Turreted>().turretFacing;
var localRecoil = new float2(0, recoil * abInfo.Recoil); // vector in turret-space.
return Util.RotateVectorByFacing(localRecoil, facing, .7f);
}
public static float2 GetTurretPosition(Actor self, IFacing facing, Turret turret)
{
if(facing == null) return turret.ScreenSpacePosition; /* things that don't have a rotating base don't need the turrets repositioned */
var ru = self.TraitOrDefault<RenderUnit>();
var numDirs = (ru != null) ? ru.anim.CurrentSequence.Facings : 8;
var bodyFacing = facing.Facing;
var quantizedFacing = Util.QuantizeFacing(bodyFacing, numDirs) * (256 / numDirs);
return (Util.RotateVectorByFacing(turret.UnitSpacePosition, quantizedFacing, .7f)
+ GetRecoil(self, turret.Recoil))
+ turret.ScreenSpacePosition;
}
// gets the screen-space position of a barrel.
public static float2 GetBarrelPosition(Actor self, IFacing facing, Turret turret, Barrel barrel)
{
var turreted = self.TraitOrDefault<Turreted>();
if (turreted == null && facing == null)
return float2.Zero;
var turretFacing = turreted != null ? turreted.turretFacing : facing.Facing;
return Util.RotateVectorByFacing(barrel.Position, turretFacing, .7f);
}
public static bool IsInRange( float2 attackOrigin, float range, Actor target )
{
var rsq = range * range * Game.CellSize * Game.CellSize;
foreach( var cell in target.Trait<ITargetable>().TargetableCells( target ) )
if( ( attackOrigin - cell * Game.CellSize ).LengthSquared <= rsq )
return true;
return false;
}
public static bool IsInRange( float2 attackOrigin, float range, float2 targetLocation )
{
var rsq = range * range * Game.CellSize * Game.CellSize;
return ( attackOrigin - targetLocation ).LengthSquared <= rsq;
}
public static bool IsInRange( float2 attackOrigin, float range, Target target )
{
if( !target.IsValid ) return false;
if( target.IsActor )
return IsInRange( attackOrigin, range, target.Actor );
else
return IsInRange( attackOrigin, range, target.CenterLocation );
}
}
}
if (isWater && warhead.WaterImpactSound != null)
return warhead.WaterImpactSound + ".aud";
if (warhead.ImpactSound != null)
return warhead.ImpactSound + ".aud";
return null;
}
public static void DoImpact(WarheadInfo warhead, ProjectileArgs args)
{
var world = args.firedBy.World;
var targetTile = Util.CellContaining(args.dest);
if (!world.Map.IsInMap(targetTile))
return;
var isWater = world.GetTerrainInfo(targetTile).IsWater;
var explosionType = isWater ? warhead.WaterExplosion : warhead.Explosion;
if (explosionType != null)
world.AddFrameEndTask(
w => w.Add(new Explosion(w, args.dest, explosionType, isWater, args.destAltitude)));
Sound.Play(GetImpactSound(warhead, isWater), args.dest);
if (warhead.SmudgeType != null)
{
var smudgeLayer = world.WorldActor.TraitsImplementing<SmudgeLayer>()
.FirstOrDefault(x => x.Info.Type == warhead.SmudgeType);
if (smudgeLayer == null)
throw new NotImplementedException("Unknown smudge type `{0}`".F(warhead.SmudgeType));
if (warhead.Size[0] > 0)
{
var smudgeCells = world.FindTilesInCircle(targetTile, warhead.Size[0]);
if (warhead.Size.Length == 2 )
smudgeCells = smudgeCells.Except(world.FindTilesInCircle(targetTile, warhead.Size[1])) ;
foreach (var sc in smudgeCells)
{
smudgeLayer.AddSmudge(sc);
if (warhead.Ore)
world.WorldActor.Trait<ResourceLayer>().Destroy(sc);
}
}
else
smudgeLayer.AddSmudge(targetTile);
}
if (warhead.Ore)
world.WorldActor.Trait<ResourceLayer>().Destroy(targetTile);
switch (warhead.DamageModel)
{
case DamageModel.Normal:
{
var maxSpread = warhead.Spread * (float)Math.Log(Math.Abs(warhead.Damage), 2);
var hitActors = world.FindUnitsInCircle(args.dest, maxSpread);
foreach (var victim in hitActors)
{
var damage = (int)GetDamageToInflict(victim, args, warhead, args.firepowerModifier);
victim.InflictDamage(args.firedBy, damage, warhead);
}
} break;
case DamageModel.PerCell:
{
foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
foreach (var unit in world.FindUnits(Game.CellSize * t, Game.CellSize * (t + new float2(1,1))))
unit.InflictDamage(args.firedBy,
(int)(warhead.Damage * warhead.EffectivenessAgainst(unit)), warhead);
} break;
}
}
public static void DoImpacts(ProjectileArgs args)
{
foreach (var warhead in args.weapon.Warheads)
{
Action a = () => DoImpact(warhead, args);
if (warhead.Delay > 0)
args.firedBy.World.AddFrameEndTask(
w => w.Add(new DelayedAction(warhead.Delay, a)));
else
a();
}
}
public static void DoExplosion(Actor attacker, string weapontype, int2 pos, int altitude)
{
var args = new ProjectileArgs
{
src = pos,
dest = pos,
srcAltitude = altitude,
destAltitude = altitude,
firedBy = attacker,
target = Target.FromPos(pos),
weapon = Rules.Weapons[ weapontype.ToLowerInvariant() ],
facing = 0
};
if (args.weapon.Report != null)
Sound.Play(args.weapon.Report + ".aud", pos);
DoImpacts(args);
}
static readonly float[] falloff =
{
1f, 0.3678795f, 0.1353353f, 0.04978707f,
0.01831564f, 0.006737947f, 0.002478752f, 0.000911882f
};
static float GetDamageFalloff(float x)
{
var u = (int)x;
if (u >= falloff.Length - 1) return 0;
var t = x - u;
return (falloff[u] * (1 - t)) + (falloff[u + 1] * t);
}
static float GetDamageToInflict(Actor target, ProjectileArgs args, WarheadInfo warhead, float modifier)
{
// don't hit air units with splash from ground explosions, etc
if (!WeaponValidForTarget(args.weapon, target)) return 0f;
var health = target.Info.Traits.GetOrDefault<HealthInfo>();
if( health == null ) return 0f;
var distance = (int)Math.Max(0, (target.CenterLocation - args.dest).Length - health.Radius);
var falloff = (float)GetDamageFalloff(distance / warhead.Spread);
var rawDamage = (float)(warhead.Damage * modifier * falloff);
var multiplier = (float)warhead.EffectivenessAgainst(target);
return (float)(rawDamage * multiplier);
}
public static bool WeaponValidForTarget(WeaponInfo weapon, Actor target)
{
var targetable = target.TraitOrDefault<ITargetable>();
if (targetable == null || !weapon.ValidTargets.Intersect(targetable.TargetTypes).Any())
return false;
if (weapon.Warheads.All( w => w.EffectivenessAgainst(target) <= 0))
return false;
return true;
}
public static bool WeaponValidForTarget( WeaponInfo weapon, World world, int2 location )
{
if( weapon.ValidTargets.Contains( "Ground" ) && world.GetTerrainType( location ) != "Water" ) return true;
if( weapon.ValidTargets.Contains( "Water" ) && world.GetTerrainType( location ) == "Water" ) return true;
return false;
}
static float2 GetRecoil(Actor self, float recoil)
{
var abInfo = self.Info.Traits.GetOrDefault<AttackBaseInfo>();
if (abInfo == null || abInfo.Recoil == 0) return float2.Zero;
var rut = self.TraitOrDefault<RenderUnitTurreted>();
if (rut == null) return float2.Zero;
var facing = self.Trait<Turreted>().turretFacing;
var localRecoil = new float2(0, recoil * abInfo.Recoil); // vector in turret-space.
return Util.RotateVectorByFacing(localRecoil, facing, .7f);
}
public static float2 GetTurretPosition(Actor self, IFacing facing, Turret turret)
{
if(facing == null) return turret.ScreenSpacePosition; /* things that don't have a rotating base don't need the turrets repositioned */
var ru = self.TraitOrDefault<RenderUnit>();
var numDirs = (ru != null) ? ru.anim.CurrentSequence.Facings : 8;
var bodyFacing = facing.Facing;
var quantizedFacing = Util.QuantizeFacing(bodyFacing, numDirs) * (256 / numDirs);
return (Util.RotateVectorByFacing(turret.UnitSpacePosition, quantizedFacing, .7f)
+ GetRecoil(self, turret.Recoil))
+ turret.ScreenSpacePosition;
}
// gets the screen-space position of a barrel.
public static float2 GetBarrelPosition(Actor self, IFacing facing, Turret turret, Barrel barrel)
{
var turreted = self.TraitOrDefault<Turreted>();
if (turreted == null && facing == null)
return float2.Zero;
var turretFacing = turreted != null ? turreted.turretFacing : facing.Facing;
return Util.RotateVectorByFacing(barrel.Position, turretFacing, .7f);
}
public static bool IsInRange( float2 attackOrigin, float range, Actor target )
{
var rsq = range * range * Game.CellSize * Game.CellSize;
foreach( var cell in target.Trait<ITargetable>().TargetableCells( target ) )
if( ( attackOrigin - cell * Game.CellSize ).LengthSquared <= rsq )
return true;
return false;
}
public static bool IsInRange( float2 attackOrigin, float range, float2 targetLocation )
{
var rsq = range * range * Game.CellSize * Game.CellSize;
return ( attackOrigin - targetLocation ).LengthSquared <= rsq;
}
public static bool IsInRange( float2 attackOrigin, float range, Target target )
{
if( !target.IsValid ) return false;
if( target.IsActor )
return IsInRange( attackOrigin, range, target.Actor );
else
return IsInRange( attackOrigin, range, target.CenterLocation );
}
}
}

View File

@@ -1,71 +1,71 @@
#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.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class ConquestVictoryConditionsInfo : TraitInfo<ConquestVictoryConditions> { }
public class ConquestVictoryConditions : ITick, IResolveOrder
{
public void Tick(Actor self)
{
if (self.Owner.WinState != WinState.Undefined || self.Owner.NonCombatant) return;
var hasAnything = self.World.Queries.OwnedBy[self.Owner]
.WithTrait<MustBeDestroyed>().Any();
if (!hasAnything && !self.Owner.NonCombatant)
Surrender(self);
var others = self.World.players.Where( p => !p.Value.NonCombatant && p.Value != self.Owner && p.Value.Stances[self.Owner] != Stance.Ally );
if (others.Count() == 0) return;
if(others.All(p => p.Value.WinState == WinState.Lost))
Win(self);
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Surrender")
Surrender(self);
}
public void Surrender(Actor self)
{
if (self.Owner.WinState == WinState.Lost) return;
self.Owner.WinState = WinState.Lost;
Game.Debug("{0} is defeated.".F(self.Owner.PlayerName));
foreach (var a in self.World.Queries.OwnedBy[self.Owner])
a.Kill(a);
if (self.Owner == self.World.LocalPlayer)
self.World.LocalShroud.Disabled = true;
}
public void Win(Actor self)
{
if (self.Owner.WinState == WinState.Won) return;
self.Owner.WinState = WinState.Won;
Game.Debug("{0} is victorious.".F(self.Owner.PlayerName));
if (self.Owner == self.World.LocalPlayer)
self.World.LocalShroud.Disabled = true;
}
}
/* tag trait for things that must be destroyed for a short game to end */
class MustBeDestroyedInfo : TraitInfo<MustBeDestroyed> { }
class MustBeDestroyed { }
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class ConquestVictoryConditionsInfo : TraitInfo<ConquestVictoryConditions> { }
public class ConquestVictoryConditions : ITick, IResolveOrder
{
public void Tick(Actor self)
{
if (self.Owner.WinState != WinState.Undefined || self.Owner.NonCombatant) return;
var hasAnything = self.World.Queries.OwnedBy[self.Owner]
.WithTrait<MustBeDestroyed>().Any();
if (!hasAnything && !self.Owner.NonCombatant)
Surrender(self);
var others = self.World.players.Where( p => !p.Value.NonCombatant && p.Value != self.Owner && p.Value.Stances[self.Owner] != Stance.Ally );
if (others.Count() == 0) return;
if(others.All(p => p.Value.WinState == WinState.Lost))
Win(self);
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Surrender")
Surrender(self);
}
public void Surrender(Actor self)
{
if (self.Owner.WinState == WinState.Lost) return;
self.Owner.WinState = WinState.Lost;
Game.Debug("{0} is defeated.".F(self.Owner.PlayerName));
foreach (var a in self.World.Queries.OwnedBy[self.Owner])
a.Kill(a);
if (self.Owner == self.World.LocalPlayer)
self.World.LocalShroud.Disabled = true;
}
public void Win(Actor self)
{
if (self.Owner.WinState == WinState.Won) return;
self.Owner.WinState = WinState.Won;
Game.Debug("{0} is victorious.".F(self.Owner.PlayerName));
if (self.Owner == self.World.LocalPlayer)
self.World.LocalShroud.Disabled = true;
}
}
/* tag trait for things that must be destroyed for a short game to end */
class MustBeDestroyedInfo : TraitInfo<MustBeDestroyed> { }
class MustBeDestroyed { }
}

View File

@@ -1,121 +1,121 @@
#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.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
/*
* Crates left to implement:
HealBase=1,INVUN ; all buildings to full strength
ICBM=1,MISSILE2 ; nuke missile one time shot
Sonar=3,SONARBOX ; one time sonar pulse
Squad=20,NONE ; squad of random infantry
Unit=20,NONE ; vehicle
Invulnerability=3,INVULBOX,1.0 ; invulnerability (duration in minutes)
TimeQuake=3,TQUAKE ; time quake
*/
namespace OpenRA.Mods.RA
{
class CrateInfo : ITraitInfo, ITraitPrerequisite<RenderSimpleInfo>
{
public readonly int Lifetime = 5; // Seconds
public readonly string[] TerrainTypes = { };
public object Create(ActorInitializer init) { return new Crate(init, this); }
}
// ITeleportable is required for paradrop
class Crate : ITick, IOccupySpace, ITeleportable, ICrushable, ISync
{
readonly Actor self;
[Sync]
int ticks;
[Sync]
public int2 Location;
CrateInfo Info;
public Crate(ActorInitializer init, CrateInfo info)
{
this.self = init.self;
if (init.Contains<LocationInit>())
{
this.Location = init.Get<LocationInit, int2>();
PxPosition = Util.CenterOfCell(Location);
}
this.Info = info;
}
public void OnCrush(Actor crusher)
{
var shares = self.TraitsImplementing<CrateAction>().Select(
a => Pair.New(a, a.GetSelectionSharesOuter(crusher)));
var totalShares = shares.Sum(a => a.Second);
var n = self.World.SharedRandom.Next(totalShares);
self.Destroy();
foreach (var s in shares)
if (n < s.Second)
{
s.First.Activate(crusher);
return;
}
else
n -= s.Second;
}
public void Tick(Actor self)
{
if( ++ticks >= self.Info.Traits.Get<CrateInfo>().Lifetime * 25 )
self.Destroy();
}
public int2 TopLeft { get { return Location; } }
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { yield return Pair.New( Location, SubCell.FullCell); }
public int2 PxPosition { get; private set; }
public void SetPxPosition( Actor self, int2 px )
{
SetPosition( self, Util.CellContaining( px ) );
}
public void AdjustPxPosition(Actor self, int2 px) { SetPxPosition(self, px); }
public bool CanEnterCell(int2 cell)
{
if (!self.World.Map.IsInMap(cell.X, cell.Y)) return false;
var type = self.World.GetTerrainType(cell);
return Info.TerrainTypes.Contains(type);
}
public void SetPosition(Actor self, int2 cell)
{
var uim = self.World.WorldActor.Trait<UnitInfluence>();
if( self.IsInWorld )
uim.Remove(self, this);
Location = cell;
PxPosition = Util.CenterOfCell(cell);
var seq = self.World.GetTerrainInfo(cell).IsWater ? "water" : "idle";
if (seq != self.Trait<RenderSimple>().anim.CurrentSequence.Name)
self.Trait<RenderSimple>().anim.PlayRepeating(seq);
if( self.IsInWorld )
uim.Add(self, this);
}
public IEnumerable<string> CrushClasses { get { yield return "crate"; } }
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
/*
* Crates left to implement:
HealBase=1,INVUN ; all buildings to full strength
ICBM=1,MISSILE2 ; nuke missile one time shot
Sonar=3,SONARBOX ; one time sonar pulse
Squad=20,NONE ; squad of random infantry
Unit=20,NONE ; vehicle
Invulnerability=3,INVULBOX,1.0 ; invulnerability (duration in minutes)
TimeQuake=3,TQUAKE ; time quake
*/
namespace OpenRA.Mods.RA
{
class CrateInfo : ITraitInfo, ITraitPrerequisite<RenderSimpleInfo>
{
public readonly int Lifetime = 5; // Seconds
public readonly string[] TerrainTypes = { };
public object Create(ActorInitializer init) { return new Crate(init, this); }
}
// ITeleportable is required for paradrop
class Crate : ITick, IOccupySpace, ITeleportable, ICrushable, ISync
{
readonly Actor self;
[Sync]
int ticks;
[Sync]
public int2 Location;
CrateInfo Info;
public Crate(ActorInitializer init, CrateInfo info)
{
this.self = init.self;
if (init.Contains<LocationInit>())
{
this.Location = init.Get<LocationInit, int2>();
PxPosition = Util.CenterOfCell(Location);
}
this.Info = info;
}
public void OnCrush(Actor crusher)
{
var shares = self.TraitsImplementing<CrateAction>().Select(
a => Pair.New(a, a.GetSelectionSharesOuter(crusher)));
var totalShares = shares.Sum(a => a.Second);
var n = self.World.SharedRandom.Next(totalShares);
self.Destroy();
foreach (var s in shares)
if (n < s.Second)
{
s.First.Activate(crusher);
return;
}
else
n -= s.Second;
}
public void Tick(Actor self)
{
if( ++ticks >= self.Info.Traits.Get<CrateInfo>().Lifetime * 25 )
self.Destroy();
}
public int2 TopLeft { get { return Location; } }
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { yield return Pair.New( Location, SubCell.FullCell); }
public int2 PxPosition { get; private set; }
public void SetPxPosition( Actor self, int2 px )
{
SetPosition( self, Util.CellContaining( px ) );
}
public void AdjustPxPosition(Actor self, int2 px) { SetPxPosition(self, px); }
public bool CanEnterCell(int2 cell)
{
if (!self.World.Map.IsInMap(cell.X, cell.Y)) return false;
var type = self.World.GetTerrainType(cell);
return Info.TerrainTypes.Contains(type);
}
public void SetPosition(Actor self, int2 cell)
{
var uim = self.World.WorldActor.Trait<UnitInfluence>();
if( self.IsInWorld )
uim.Remove(self, this);
Location = cell;
PxPosition = Util.CenterOfCell(cell);
var seq = self.World.GetTerrainInfo(cell).IsWater ? "water" : "idle";
if (seq != self.Trait<RenderSimple>().anim.CurrentSequence.Name)
self.Trait<RenderSimple>().anim.PlayRepeating(seq);
if( self.IsInWorld )
uim.Add(self, this);
}
public IEnumerable<string> CrushClasses { get { yield return "crate"; } }
}
}

View File

@@ -1,60 +1,60 @@
#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.Linq;
using OpenRA.Mods.RA.Effects;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CrateActionInfo : ITraitInfo
{
public int SelectionShares = 10;
public string Effect = null;
public string Notification = null;
public string[] ExcludedActorTypes = { };
public virtual object Create(ActorInitializer init) { return new CrateAction(init.self, this); }
}
public class CrateAction
{
public Actor self;
public CrateActionInfo info;
public CrateAction(Actor self, CrateActionInfo info)
{
this.self = self;
this.info = info;
}
public int GetSelectionSharesOuter(Actor collector)
{
if (info.ExcludedActorTypes.Contains(collector.Info.Name))
return 0;
return GetSelectionShares(collector);
}
public virtual int GetSelectionShares(Actor collector)
{
return info.SelectionShares;
}
public virtual void Activate(Actor collector)
{
Sound.PlayToPlayer(collector.Owner, info.Notification);
if (info.Effect != null)
collector.World.AddFrameEndTask(
w => w.Add(new CrateEffect(collector, info.Effect)));
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Mods.RA.Effects;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CrateActionInfo : ITraitInfo
{
public int SelectionShares = 10;
public string Effect = null;
public string Notification = null;
public string[] ExcludedActorTypes = { };
public virtual object Create(ActorInitializer init) { return new CrateAction(init.self, this); }
}
public class CrateAction
{
public Actor self;
public CrateActionInfo info;
public CrateAction(Actor self, CrateActionInfo info)
{
this.self = self;
this.info = info;
}
public int GetSelectionSharesOuter(Actor collector)
{
if (info.ExcludedActorTypes.Contains(collector.Info.Name))
return 0;
return GetSelectionShares(collector);
}
public virtual int GetSelectionShares(Actor collector)
{
return info.SelectionShares;
}
public virtual void Activate(Actor collector)
{
Sound.PlayToPlayer(collector.Owner, info.Notification);
if (info.Effect != null)
collector.World.AddFrameEndTask(
w => w.Add(new CrateEffect(collector, info.Effect)));
}
}
}

View File

@@ -1,92 +1,92 @@
#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 System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Mods.RA.Air;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CrateDropInfo : TraitInfo<CrateDrop>
{
public readonly int Minimum = 1; // Minumum number of crates
public readonly int Maximum = 255; // Maximum number of crates
public readonly string[] ValidGround = {"Clear", "Rough", "Road", "Ore", "Beach"}; // Which terrain types can we drop on?
public readonly string[] ValidWater = {"Water"};
public readonly int SpawnInterval = 180; // Average time (seconds) between crate spawn
public readonly float WaterChance = .2f; // Chance of generating a water crate instead of a land crate
}
public class CrateDrop : ITick
{
List<Actor> crates = new List<Actor>();
int ticks = 0;
public void Tick(Actor self)
{
if (--ticks <= 0)
{
var info = self.Info.Traits.Get<CrateDropInfo>();
ticks = info.SpawnInterval * 25; // todo: randomize
crates.RemoveAll(x => !x.IsInWorld); // BUG: this removes crates that are cargo of a BADR!
var toSpawn = Math.Max(0, info.Minimum - crates.Count)
+ (crates.Count < info.Maximum ? 1 : 0);
for (var n = 0; n < toSpawn; n++)
SpawnCrate(self, info);
}
}
void SpawnCrate(Actor self, CrateDropInfo info)
{
var threshold = 100;
var inWater = self.World.SharedRandom.NextDouble() < info.WaterChance;
for (var n = 0; n < threshold; n++ )
{
var p = self.World.ChooseRandomCell(self.World.SharedRandom);
// Is this valid terrain?
var terrainType = self.World.GetTerrainType(p);
if (!(inWater ? info.ValidWater : info.ValidGround).Contains(terrainType)) continue;
// Don't drop on any actors
if (self.World.WorldActor.Trait<BuildingInfluence>().GetBuildingAt(p) != null) continue;
if (self.World.WorldActor.Trait<UnitInfluence>().GetUnitsAt(p).Any()) continue;
self.World.AddFrameEndTask(w =>
{
var crate = w.CreateActor(false, "crate", new TypeDictionary { new OwnerInit(w.WorldActor.Owner) });
crates.Add(crate);
var startPos = w.ChooseRandomEdgeCell();
var plane = w.CreateActor("badr", new TypeDictionary
{
new LocationInit( startPos ),
new OwnerInit( w.WorldActor.Owner),
new FacingInit( Util.GetFacing(p - startPos, 0) ),
new AltitudeInit( Rules.Info["badr"].Traits.Get<AircraftInfo>().CruiseAltitude ),
});
plane.CancelActivity();
plane.QueueActivity(new FlyCircle(p));
plane.Trait<ParaDrop>().SetLZ(p, null);
plane.Trait<Cargo>().Load(plane, crate);
});
return;
}
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Mods.RA.Air;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CrateDropInfo : TraitInfo<CrateDrop>
{
public readonly int Minimum = 1; // Minumum number of crates
public readonly int Maximum = 255; // Maximum number of crates
public readonly string[] ValidGround = {"Clear", "Rough", "Road", "Ore", "Beach"}; // Which terrain types can we drop on?
public readonly string[] ValidWater = {"Water"};
public readonly int SpawnInterval = 180; // Average time (seconds) between crate spawn
public readonly float WaterChance = .2f; // Chance of generating a water crate instead of a land crate
}
public class CrateDrop : ITick
{
List<Actor> crates = new List<Actor>();
int ticks = 0;
public void Tick(Actor self)
{
if (--ticks <= 0)
{
var info = self.Info.Traits.Get<CrateDropInfo>();
ticks = info.SpawnInterval * 25; // todo: randomize
crates.RemoveAll(x => !x.IsInWorld); // BUG: this removes crates that are cargo of a BADR!
var toSpawn = Math.Max(0, info.Minimum - crates.Count)
+ (crates.Count < info.Maximum ? 1 : 0);
for (var n = 0; n < toSpawn; n++)
SpawnCrate(self, info);
}
}
void SpawnCrate(Actor self, CrateDropInfo info)
{
var threshold = 100;
var inWater = self.World.SharedRandom.NextDouble() < info.WaterChance;
for (var n = 0; n < threshold; n++ )
{
var p = self.World.ChooseRandomCell(self.World.SharedRandom);
// Is this valid terrain?
var terrainType = self.World.GetTerrainType(p);
if (!(inWater ? info.ValidWater : info.ValidGround).Contains(terrainType)) continue;
// Don't drop on any actors
if (self.World.WorldActor.Trait<BuildingInfluence>().GetBuildingAt(p) != null) continue;
if (self.World.WorldActor.Trait<UnitInfluence>().GetUnitsAt(p).Any()) continue;
self.World.AddFrameEndTask(w =>
{
var crate = w.CreateActor(false, "crate", new TypeDictionary { new OwnerInit(w.WorldActor.Owner) });
crates.Add(crate);
var startPos = w.ChooseRandomEdgeCell();
var plane = w.CreateActor("badr", new TypeDictionary
{
new LocationInit( startPos ),
new OwnerInit( w.WorldActor.Owner),
new FacingInit( Util.GetFacing(p - startPos, 0) ),
new AltitudeInit( Rules.Info["badr"].Traits.Get<AircraftInfo>().CruiseAltitude ),
});
plane.CancelActivity();
plane.QueueActivity(new FlyCircle(p));
plane.Trait<ParaDrop>().SetLZ(p, null);
plane.Trait<Cargo>().Load(plane, crate);
});
return;
}
}
}
}

View File

@@ -1,18 +1,18 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Mods.RA.Buildings;
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Traits;
namespace OpenRA.Mods.RA

View File

@@ -1,59 +1,59 @@
#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 OpenRA.FileFormats;
using OpenRA.Mods.RA;
namespace OpenRA.Mods.RA.Crates
{
class CloakCrateActionInfo : CrateActionInfo
{
public readonly float InitialDelay = .4f;
public readonly float CloakDelay = 1.2f;
public readonly string CloakSound = "subshow1.aud";
public readonly string UncloakSound = "subshow1.aud";
public override object Create(ActorInitializer init) { return new CloakCrateAction(init.self, this); }
}
class CloakCrateAction : CrateAction
{
CloakCrateActionInfo Info;
public CloakCrateAction(Actor self, CloakCrateActionInfo info)
: base(self, info) { Info = info; }
public override int GetSelectionShares(Actor collector)
{
return collector.HasTrait<Cloak>()
? 0 : base.GetSelectionShares(collector);
}
public override void Activate(Actor collector)
{
var cloakInfo = new CloakInfo(Info.InitialDelay, Info.CloakDelay,
Info.CloakSound, Info.UncloakSound);
var cloak = cloakInfo.Create(new ActorInitializer(collector, new TypeDictionary() ));
collector.World.AddFrameEndTask(w =>
{
w.Remove(collector);
collector.AddTrait(cloak);
if (collector.HasTrait<TargetableUnit<TargetableUnitInfo>>())
collector.Trait<TargetableUnit<TargetableUnitInfo>>().RecievedCloak(collector);
w.Add(collector);
});
base.Activate(collector);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.FileFormats;
using OpenRA.Mods.RA;
namespace OpenRA.Mods.RA.Crates
{
class CloakCrateActionInfo : CrateActionInfo
{
public readonly float InitialDelay = .4f;
public readonly float CloakDelay = 1.2f;
public readonly string CloakSound = "subshow1.aud";
public readonly string UncloakSound = "subshow1.aud";
public override object Create(ActorInitializer init) { return new CloakCrateAction(init.self, this); }
}
class CloakCrateAction : CrateAction
{
CloakCrateActionInfo Info;
public CloakCrateAction(Actor self, CloakCrateActionInfo info)
: base(self, info) { Info = info; }
public override int GetSelectionShares(Actor collector)
{
return collector.HasTrait<Cloak>()
? 0 : base.GetSelectionShares(collector);
}
public override void Activate(Actor collector)
{
var cloakInfo = new CloakInfo(Info.InitialDelay, Info.CloakDelay,
Info.CloakSound, Info.UncloakSound);
var cloak = cloakInfo.Create(new ActorInitializer(collector, new TypeDictionary() ));
collector.World.AddFrameEndTask(w =>
{
w.Remove(collector);
collector.AddTrait(cloak);
if (collector.HasTrait<TargetableUnit<TargetableUnitInfo>>())
collector.Trait<TargetableUnit<TargetableUnitInfo>>().RecievedCloak(collector);
w.Add(collector);
});
base.Activate(collector);
}
}
}

View File

@@ -1,34 +1,34 @@
#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 OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class ExplodeCrateActionInfo : CrateActionInfo
{
[WeaponReference]
public string Weapon = null;
public override object Create(ActorInitializer init) { return new ExplodeCrateAction(init.self, this); }
}
class ExplodeCrateAction : CrateAction
{
public ExplodeCrateAction(Actor self, ExplodeCrateActionInfo info)
: base(self, info) {}
public override void Activate(Actor collector)
{
Combat.DoExplosion(self, (info as ExplodeCrateActionInfo).Weapon, collector.CenterLocation, 0);
base.Activate(collector);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class ExplodeCrateActionInfo : CrateActionInfo
{
[WeaponReference]
public string Weapon = null;
public override object Create(ActorInitializer init) { return new ExplodeCrateAction(init.self, this); }
}
class ExplodeCrateAction : CrateAction
{
public ExplodeCrateAction(Actor self, ExplodeCrateActionInfo info)
: base(self, info) {}
public override void Activate(Actor collector)
{
Combat.DoExplosion(self, (info as ExplodeCrateActionInfo).Weapon, collector.CenterLocation, 0);
base.Activate(collector);
}
}
}

View File

@@ -1,36 +1,36 @@
#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 OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class GiveCashCrateActionInfo : CrateActionInfo
{
public int Amount = 2000;
public override object Create(ActorInitializer init) { return new GiveCashCrateAction(init.self, this); }
}
class GiveCashCrateAction : CrateAction
{
public GiveCashCrateAction(Actor self, GiveCashCrateActionInfo info)
: base(self, info) {}
public override void Activate(Actor collector)
{
collector.World.AddFrameEndTask(w =>
{
var amount = (info as GiveCashCrateActionInfo).Amount;
collector.Owner.PlayerActor.Trait<PlayerResources>().GiveCash(amount);
});
base.Activate(collector);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class GiveCashCrateActionInfo : CrateActionInfo
{
public int Amount = 2000;
public override object Create(ActorInitializer init) { return new GiveCashCrateAction(init.self, this); }
}
class GiveCashCrateAction : CrateAction
{
public GiveCashCrateAction(Actor self, GiveCashCrateActionInfo info)
: base(self, info) {}
public override void Activate(Actor collector)
{
collector.World.AddFrameEndTask(w =>
{
var amount = (info as GiveCashCrateActionInfo).Amount;
collector.Owner.PlayerActor.Trait<PlayerResources>().GiveCash(amount);
});
base.Activate(collector);
}
}
}

View File

@@ -1,36 +1,36 @@
#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.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Crates
{
class GiveMcvCrateActionInfo : GiveUnitCrateActionInfo
{
public int NoBaseSelectionShares = 1000;
public override object Create(ActorInitializer init) { return new GiveMcvCrateAction(init.self, this); }
}
class GiveMcvCrateAction : GiveUnitCrateAction
{
public GiveMcvCrateAction(Actor self, GiveMcvCrateActionInfo info)
: base(self, info) { }
public override int GetSelectionShares(Actor collector)
{
if (base.GetSelectionShares(collector) == 0)
return 0; // there's some other really good reason why we shouldn't give this.
var hasBase = self.World.Queries.OwnedBy[collector.Owner].WithTrait<BaseBuilding>().Any();
return hasBase ? info.SelectionShares : (info as GiveMcvCrateActionInfo).NoBaseSelectionShares;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Crates
{
class GiveMcvCrateActionInfo : GiveUnitCrateActionInfo
{
public int NoBaseSelectionShares = 1000;
public override object Create(ActorInitializer init) { return new GiveMcvCrateAction(init.self, this); }
}
class GiveMcvCrateAction : GiveUnitCrateAction
{
public GiveMcvCrateAction(Actor self, GiveMcvCrateActionInfo info)
: base(self, info) { }
public override int GetSelectionShares(Actor collector)
{
if (base.GetSelectionShares(collector) == 0)
return 0; // there's some other really good reason why we shouldn't give this.
var hasBase = self.World.Queries.OwnedBy[collector.Owner].WithTrait<BaseBuilding>().Any();
return hasBase ? info.SelectionShares : (info as GiveMcvCrateActionInfo).NoBaseSelectionShares;
}
}
}

View File

@@ -1,79 +1,79 @@
#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.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Crates
{
class GiveUnitCrateActionInfo : CrateActionInfo
{
[ActorReference]
public readonly string Unit = null;
public override object Create(ActorInitializer init) { return new GiveUnitCrateAction(init.self, this); }
}
class GiveUnitCrateAction : CrateAction
{
GiveUnitCrateActionInfo Info;
public GiveUnitCrateAction(Actor self, GiveUnitCrateActionInfo info)
: base(self, info) { Info = info; }
public override int GetSelectionShares(Actor collector)
{
var bi = Rules.Info[Info.Unit].Traits.Get<BuildableInfo>();
// this unit is not buildable by the collector's country, so
// don't give them free ones either.
if (!bi.Owner.Contains(collector.Owner.Country.Race)) return 0;
// avoid dumping tanks in the sea, and ships on dry land.
if (!GetSuitableCells(collector.Location).Any()) return 0;
return base.GetSelectionShares(collector);
}
public override void Activate(Actor collector)
{
var location = ChooseEmptyCellNear(collector);
if (location != null)
collector.World.AddFrameEndTask(
w => w.CreateActor(Info.Unit, new TypeDictionary
{
new LocationInit( location.Value ),
new OwnerInit( collector.Owner )
}));
base.Activate(collector);
}
IEnumerable<int2> GetSuitableCells(int2 near)
{
var mi = Rules.Info[Info.Unit].Traits.GetOrDefault<MobileInfo>();
for (var i = -1; i < 2; i++)
for (var j = -1; j < 2; j++)
if (mi.CanEnterCell(self.World, near + new int2(i, j), null, true))
yield return near + new int2(i, j);
}
int2? ChooseEmptyCellNear(Actor a)
{
var possibleCells = GetSuitableCells(a.Location).ToArray();
if (possibleCells.Length == 0)
return null;
return possibleCells.Random(self.World.SharedRandom);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Crates
{
class GiveUnitCrateActionInfo : CrateActionInfo
{
[ActorReference]
public readonly string Unit = null;
public override object Create(ActorInitializer init) { return new GiveUnitCrateAction(init.self, this); }
}
class GiveUnitCrateAction : CrateAction
{
GiveUnitCrateActionInfo Info;
public GiveUnitCrateAction(Actor self, GiveUnitCrateActionInfo info)
: base(self, info) { Info = info; }
public override int GetSelectionShares(Actor collector)
{
var bi = Rules.Info[Info.Unit].Traits.Get<BuildableInfo>();
// this unit is not buildable by the collector's country, so
// don't give them free ones either.
if (!bi.Owner.Contains(collector.Owner.Country.Race)) return 0;
// avoid dumping tanks in the sea, and ships on dry land.
if (!GetSuitableCells(collector.Location).Any()) return 0;
return base.GetSelectionShares(collector);
}
public override void Activate(Actor collector)
{
var location = ChooseEmptyCellNear(collector);
if (location != null)
collector.World.AddFrameEndTask(
w => w.CreateActor(Info.Unit, new TypeDictionary
{
new LocationInit( location.Value ),
new OwnerInit( collector.Owner )
}));
base.Activate(collector);
}
IEnumerable<int2> GetSuitableCells(int2 near)
{
var mi = Rules.Info[Info.Unit].Traits.GetOrDefault<MobileInfo>();
for (var i = -1; i < 2; i++)
for (var j = -1; j < 2; j++)
if (mi.CanEnterCell(self.World, near + new int2(i, j), null, true))
yield return near + new int2(i, j);
}
int2? ChooseEmptyCellNear(Actor a)
{
var possibleCells = GetSuitableCells(a.Location).ToArray();
if (possibleCells.Length == 0)
return null;
return possibleCells.Random(self.World.SharedRandom);
}
}
}

View File

@@ -1,35 +1,35 @@
#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
namespace OpenRA.Mods.RA
{
class LevelUpCrateActionInfo : CrateActionInfo
{
public override object Create(ActorInitializer init) { return new LevelUpCrateAction(init.self, this); }
}
class LevelUpCrateAction : CrateAction
{
public LevelUpCrateAction(Actor self, LevelUpCrateActionInfo info)
: base(self,info) {}
public override void Activate(Actor collector)
{
collector.World.AddFrameEndTask(w =>
{
var gainsExperience = collector.TraitOrDefault<GainsExperience>();
if (gainsExperience != null)
gainsExperience.GiveOneLevel();
});
base.Activate(collector);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
namespace OpenRA.Mods.RA
{
class LevelUpCrateActionInfo : CrateActionInfo
{
public override object Create(ActorInitializer init) { return new LevelUpCrateAction(init.self, this); }
}
class LevelUpCrateAction : CrateAction
{
public LevelUpCrateAction(Actor self, LevelUpCrateActionInfo info)
: base(self,info) {}
public override void Activate(Actor collector)
{
collector.World.AddFrameEndTask(w =>
{
var gainsExperience = collector.TraitOrDefault<GainsExperience>();
if (gainsExperience != null)
gainsExperience.GiveOneLevel();
});
base.Activate(collector);
}
}
}

View File

@@ -1,32 +1,32 @@
#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 OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class HideMapCrateActionInfo : CrateActionInfo
{
public override object Create(ActorInitializer init) { return new HideMapCrateAction(init.self, this); }
}
class HideMapCrateAction : CrateAction
{
public HideMapCrateAction(Actor self, HideMapCrateActionInfo info)
: base(self, info) {}
public override void Activate(Actor collector)
{
base.Activate(collector);
if (collector.Owner == collector.World.LocalPlayer)
collector.World.WorldActor.Trait<Shroud>().ResetExploration();
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class HideMapCrateActionInfo : CrateActionInfo
{
public override object Create(ActorInitializer init) { return new HideMapCrateAction(init.self, this); }
}
class HideMapCrateAction : CrateAction
{
public HideMapCrateAction(Actor self, HideMapCrateActionInfo info)
: base(self, info) {}
public override void Activate(Actor collector)
{
base.Activate(collector);
if (collector.Owner == collector.World.LocalPlayer)
collector.World.WorldActor.Trait<Shroud>().ResetExploration();
}
}
}

View File

@@ -1,20 +1,20 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion
#endregion
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class RevealMapCrateActionInfo : CrateActionInfo
{
{
public readonly bool IncludeAllies = false;
public override object Create(ActorInitializer init) { return new RevealMapCrateAction(init.self, this); }
}
@@ -22,22 +22,22 @@ namespace OpenRA.Mods.RA
class RevealMapCrateAction : CrateAction
{
public RevealMapCrateAction(Actor self, RevealMapCrateActionInfo info)
: base(self, info) {}
bool ShouldReveal(Player collectingPlayer)
{
if ((info as RevealMapCrateActionInfo).IncludeAllies)
return collectingPlayer.World.LocalPlayer != null &&
collectingPlayer.Stances[collectingPlayer.World.LocalPlayer] == Stance.Ally;
return collectingPlayer == collectingPlayer.World.LocalPlayer;
: base(self, info) {}
bool ShouldReveal(Player collectingPlayer)
{
if ((info as RevealMapCrateActionInfo).IncludeAllies)
return collectingPlayer.World.LocalPlayer != null &&
collectingPlayer.Stances[collectingPlayer.World.LocalPlayer] == Stance.Ally;
return collectingPlayer == collectingPlayer.World.LocalPlayer;
}
public override void Activate(Actor collector)
{
base.Activate(collector);
if (ShouldReveal( collector.Owner ))
base.Activate(collector);
if (ShouldReveal( collector.Owner ))
collector.World.WorldActor.Trait<Shroud>().ExploreAll(collector.World);
}
}

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