This commit is contained in:
ScottNZ
2012-07-02 13:46:28 +12:00
101 changed files with 1629 additions and 624 deletions

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2012 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,
@@ -10,6 +10,7 @@
using System.Linq;
using OpenRA.Traits;
using OpenRA.Mods.RA.Move;
namespace OpenRA.Mods.RA.Activities
{
@@ -25,9 +26,6 @@ namespace OpenRA.Mods.RA.Activities
if (target == null || !target.IsInWorld || target.IsDead()) return NextActivity;
if (target.Owner == self.Owner) return NextActivity;
if( !target.OccupiesSpace.OccupiedCells().Any( x => x.First == self.Location ) )
return NextActivity;
var capturable = target.TraitOrDefault<Capturable>();
if (capturable != null && capturable.CaptureInProgress && capturable.Captor.Owner.Stances[self.Owner] == Stance.Ally)
return NextActivity;
@@ -36,8 +34,14 @@ namespace OpenRA.Mods.RA.Activities
if (sellable != null && sellable.Selling)
return NextActivity;
target.Trait<Capturable>().BeginCapture(target, self);
self.World.AddFrameEndTask(w => self.Destroy());
var captures = self.TraitOrDefault<Captures>();
var capturesInfo = self.Info.Traits.Get<CapturesInfo>();
if (captures != null && Combat.IsInRange(self.CenterLocation, capturesInfo.Range, target))
target.Trait<Capturable>().BeginCapture(target, self);
else
return Util.SequenceActivities(self.Trait<Mobile>().MoveWithinRange(Target.FromActor(target), capturesInfo.Range), this);
if (capturesInfo != null && capturesInfo.wastedAfterwards)
self.World.AddFrameEndTask(w => self.Destroy());
return this;
}

View File

@@ -10,18 +10,59 @@
using System.Linq;
using OpenRA.Traits;
using OpenRA.Mods.RA.Render;
namespace OpenRA.Mods.RA.Activities
{
public class Teleport : Activity
{
CPos destination;
bool killCargo;
Actor chronosphere;
public Teleport(CPos destination)
public Teleport(Actor chronosphere, CPos destination, bool killCargo)
{
this.chronosphere = chronosphere;
this.destination = destination;
this.killCargo = killCargo;
}
public override Activity Tick(Actor self)
{
Sound.Play("chrono2.aud", self.Location.ToPPos());
Sound.Play("chrono2.aud", destination.ToPPos());
self.Trait<ITeleportable>().SetPosition(self, destination);
if (killCargo && self.HasTrait<Cargo>())
{
var cargo = self.Trait<Cargo>();
while (!cargo.IsEmpty(self))
{
if (chronosphere != null)
chronosphere.Owner.Kills++;
var a = cargo.Unload(self);
a.Owner.Deaths++;
}
}
// Trigger screen desaturate effect
foreach (var a in self.World.ActorsWithTrait<ChronoshiftPaletteEffect>())
a.Trait.Enable();
if (chronosphere != null && !chronosphere.Destroyed && chronosphere.HasTrait<RenderBuilding>())
chronosphere.Trait<RenderBuilding>().PlayCustomAnim(chronosphere, "active");
return NextActivity;
}
}
public class SimpleTeleport : Activity
{
CPos destination;
public SimpleTeleport(CPos destination) { this.destination = destination; }
public override Activity Tick(Actor self)
{
self.Trait<ITeleportable>().SetPosition(self, destination);

View File

@@ -52,11 +52,11 @@ namespace OpenRA.Mods.RA.Activities
var health = self.TraitOrDefault<Health>();
if (health != null)
{
// TODO: Fix bogus health init
if (ForceHealthPercentage > 0)
init.Add( new HealthInit( ForceHealthPercentage * 1f / 100 ));
else
init.Add( new HealthInit( (float)health.HP / health.MaxHP ));
var newHP = (ForceHealthPercentage > 0)
? ForceHealthPercentage / 100f
: (float)health.HP / health.MaxHP;
init.Add( new HealthInit(newHP) );
}
var cargo = self.TraitOrDefault<Cargo>();

View File

@@ -18,6 +18,10 @@ namespace OpenRA.Mods.RA.Activities
{
public class UnloadCargo : Activity
{
bool unloadAll;
public UnloadCargo(bool unloadAll) { this.unloadAll = unloadAll; }
CPos? ChooseExitTile(Actor self, Actor cargo)
{
// is anyone still hogging this tile?
@@ -35,6 +39,19 @@ namespace OpenRA.Mods.RA.Activities
return null;
}
CPos? ChooseRallyPoint(Actor self)
{
var mobile = self.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 CVec(i, j)))
return self.Location + new CVec(i, j);
return self.Location;
}
public override Activity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
@@ -80,10 +97,13 @@ namespace OpenRA.Mods.RA.Activities
actor.CancelActivity();
actor.QueueActivity(new Drag(currentPx, exitPx, length));
actor.QueueActivity(mobile.MoveTo(exitTile.Value, 0));
actor.SetTargetLine(Target.FromCell(exitTile.Value), Color.Green, false);
var rallyPoint = ChooseRallyPoint(actor).Value;
actor.QueueActivity(mobile.MoveTo(rallyPoint, 0));
actor.SetTargetLine(Target.FromCell(rallyPoint), Color.Green, false);
});
return this;
return unloadAll ? this : NextActivity;
}
}
}

View File

@@ -0,0 +1,43 @@
#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;
using OpenRA.Mods.RA.Activities;
namespace OpenRA.Mods.RA
{
public class AttackLoyaltyInfo : AttackFrontalInfo
{
public override object Create(ActorInitializer init) { return new AttackLoyalty(init.self, this); }
}
public class AttackLoyalty : AttackFrontal
{
public AttackLoyalty(Actor self, AttackLoyaltyInfo 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;
var move = self.TraitOrDefault<IMove>();
var facing = self.TraitOrDefault<IFacing>();
foreach (var w in Weapons)
w.CheckFire(self, this, move, facing, target);
if (target.Actor != null)
target.Actor.ChangeOwner(self.Owner);
}
}
}

View File

@@ -37,9 +37,7 @@ namespace OpenRA.Mods.RA.Buildings
if (order.OrderString == "PowerDown")
{
disabled = !disabled;
var eva = self.World.WorldActor.Info.Traits.Get<EvaAlertsInfo>();
Sound.PlayToPlayer(self.Owner, disabled ? eva.EnablePower : eva.DisablePower);
Sound.PlayNotification(self.Owner, "Sounds", (disabled ? "EnablePower" : "DisablePower"), self.Owner.Country.Race);
PowerManager.UpdateActor(self, disabled ? 0 : normalPower);
if (disabled)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2012 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,
@@ -108,8 +108,7 @@ namespace OpenRA.Mods.RA.Buildings
if (--nextPowerAdviceTime <= 0)
{
if (lowPower)
Player.GiveAdvice(Rules.Info["world"].Traits.Get<EvaAlertsInfo>().LowPower);
Sound.PlayNotification(self.Owner, "Speech", "LowPower", self.Owner.Country.Race);
nextPowerAdviceTime = Info.AdviceInterval;
}
}

View File

@@ -48,7 +48,7 @@ namespace OpenRA.Mods.RA.Buildings
else
{
Repairer = p;
Sound.PlayToPlayer(Repairer, p.World.WorldActor.Info.Traits.Get<EvaAlertsInfo>().Repairing);
Sound.PlayNotification(Repairer, "Speech", "Repairing", self.Owner.Country.Race);
self.World.AddFrameEndTask(
w => w.Add(new RepairIndicator(self, p)));

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2012 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,
@@ -22,6 +22,8 @@ namespace OpenRA.Mods.RA
class CapturesInfo : ITraitInfo
{
public string[] CaptureTypes = {"building"};
public int Range = 3;
public bool wastedAfterwards = true;
public object Create(ActorInitializer init) { return new Captures(init.self, this); }
}
@@ -40,7 +42,7 @@ namespace OpenRA.Mods.RA
{
get
{
yield return new CaptureOrderTargeter(Info.CaptureTypes, target => CanEnter(target));
yield return new CaptureOrderTargeter(Info.CaptureTypes, target => CanCapture(target));
}
}
@@ -55,24 +57,23 @@ namespace OpenRA.Mods.RA
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "CaptureActor"
&& CanEnter(order.TargetActor)) ? "Attack" : null;
&& CanCapture(order.TargetActor)) ? "Attack" : null;
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "CaptureActor")
{
if (!CanEnter(order.TargetActor)) return;
if (!CanCapture(order.TargetActor)) return;
self.SetTargetLine(Target.FromOrder(order), Color.Red);
self.CancelActivity();
self.QueueActivity(new Enter(order.TargetActor));
self.QueueActivity(new CaptureActor(order.TargetActor));
}
}
bool CanEnter(Actor target)
bool CanCapture(Actor target)
{
var c = target.TraitOrDefault<Capturable>();
return c != null && ( !c.CaptureInProgress || c.Captor.Owner.Stances[self.Owner] != Stance.Ally );
@@ -104,9 +105,11 @@ namespace OpenRA.Mods.RA
IsQueued = forceQueued;
var Info = self.Info.Traits.Get<CapturesInfo>();
if (captureTypes.Contains(ci.Type))
{
cursor = useEnterCursor(target) ? "enter" : "enter-blocked";
cursor = (Info.wastedAfterwards) ? (useEnterCursor(target) ? "enter" : "enter-blocked") : "attack";
return true;
}

View File

@@ -81,7 +81,7 @@ namespace OpenRA.Mods.RA
return;
self.CancelActivity();
self.QueueActivity(new UnloadCargo());
self.QueueActivity(new UnloadCargo(true));
}
}

View File

@@ -52,18 +52,11 @@ namespace OpenRA.Mods.RA
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", order.TargetLocation.ToPPos());
self.QueueActivity(new Teleport(null, order.TargetLocation, true));
chargeTick = 25 * self.Info.Traits.Get<ChronoshiftDeployInfo>().ChargeTime;
foreach (var a in self.World.ActorsWithTrait<ChronoshiftPaletteEffect>())
a.Trait.Enable();
}
}

View File

@@ -20,6 +20,8 @@ namespace OpenRA.Mods.RA
// Return-to-sender logic
[Sync] CPos chronoshiftOrigin;
[Sync] int chronoshiftReturnTicks = 0;
Actor chronosphere;
bool killCargo;
public void Tick(Actor self)
{
@@ -34,7 +36,7 @@ namespace OpenRA.Mods.RA
{
self.CancelActivity();
// Todo: need a new Teleport method that will move to the closest available cell
self.QueueActivity(new Teleport(chronoshiftOrigin));
self.QueueActivity(new Teleport(chronosphere, chronoshiftOrigin, killCargo));
}
}
@@ -52,22 +54,12 @@ namespace OpenRA.Mods.RA
/// 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++;
}
}
this.chronosphere = chronosphere;
this.killCargo = killCargo;
// Set up the teleport
self.CancelActivity();
self.QueueActivity(new Teleport(targetLocation));
self.QueueActivity(new Teleport(chronosphere, targetLocation, killCargo));
return true;
}

View File

@@ -15,10 +15,7 @@ namespace OpenRA.Mods.RA
{
public class ConquestVictoryConditionsInfo : ITraitInfo
{
public string WinNotification = null;
public string LoseNotification = null;
public int NotificationDelay = 1500; // Milliseconds
public readonly string Race = null;
public object Create(ActorInitializer init) { return new ConquestVictoryConditions(this); }
}
@@ -55,7 +52,6 @@ namespace OpenRA.Mods.RA
public void Lose(Actor self)
{
if (Info.Race != null && Info.Race != self.Owner.Country.Race) return;
if (self.Owner.WinState == WinState.Lost) return;
self.Owner.WinState = WinState.Lost;
@@ -70,14 +66,13 @@ namespace OpenRA.Mods.RA
Game.RunAfterDelay(Info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(self.World))
Sound.Play(Info.LoseNotification);
Sound.PlayNotification(self.Owner, "Speech", "Lose", self.Owner.Country.Race);
});
}
}
public void Win(Actor self)
{
if (Info.Race != null && Info.Race != self.Owner.Country.Race) return;
if (self.Owner.WinState == WinState.Won) return;
self.Owner.WinState = WinState.Won;
@@ -85,7 +80,7 @@ namespace OpenRA.Mods.RA
if (self.Owner == self.World.LocalPlayer)
{
self.World.LocalShroud.Disabled = true;
Game.RunAfterDelay(Info.NotificationDelay, () => Sound.Play(Info.WinNotification));
Game.RunAfterDelay(Info.NotificationDelay, () => Sound.PlayNotification(self.Owner, "Speech", "Win", self.Owner.Country.Race));
}
}
}

View File

@@ -14,17 +14,6 @@ using OpenRA.FileFormats;
using OpenRA.Traits;
using OpenRA.Mods.RA.Buildings;
/*
* 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, Requires<RenderSimpleInfo>
@@ -35,7 +24,7 @@ namespace OpenRA.Mods.RA
}
// ITeleportable is required for paradrop
class Crate : ITick, IOccupySpace, ITeleportable, ICrushable, ISync
class Crate : ITick, IOccupySpace, ITeleportable, ICrushable, ISync, INotifyParachuteLanded
{
readonly Actor self;
[Sync] int ticks;
@@ -73,6 +62,15 @@ namespace OpenRA.Mods.RA
n -= s.Second;
}
public void OnLanded()
{
var landedOn = self.World.ActorMap.GetUnitsAt(self.Location)
.FirstOrDefault(a => a != self);
if (landedOn != null)
OnCrush(landedOn);
}
public void Tick(Actor self)
{
if( ++ticks >= Info.Lifetime * 25 )

View File

@@ -67,6 +67,9 @@ namespace OpenRA.Mods.RA.Effects
cargo.CancelActivity();
cargo.Trait<ITeleportable>().SetPosition(cargo, loc);
w.Add(cargo);
foreach( var npl in cargo.TraitsImplementing<INotifyParachuteLanded>() )
npl.OnLanded();
});
}

View File

@@ -77,8 +77,7 @@ namespace OpenRA.Mods.RA
while (Level < MaxLevel && Experience >= Levels[Level])
{
Level++;
var eva = self.World.WorldActor.Info.Traits.Get<EvaAlertsInfo>();
Sound.PlayToPlayer(self.Owner, eva.LevelUp, self.CenterLocation);
Sound.PlayNotification(self.Owner, "Sounds", "LevelUp", self.Owner.Country.Race);
self.World.AddFrameEndTask(w => w.Add(new CrateEffect(self, "levelup", new int2(0,-24))));
}
}

View File

@@ -51,6 +51,7 @@ namespace OpenRA.Mods.RA
public CPos? LastOrderLocation = null;
[Sync] public int ContentValue { get { return contents.Sum(c => c.Key.ValuePerUnit * c.Value); } }
readonly HarvesterInfo Info;
bool idleSmart = true;
public Harvester(Actor self, HarvesterInfo info)
{
@@ -61,6 +62,7 @@ namespace OpenRA.Mods.RA
public void SetProcLines(Actor proc)
{
if (proc == null) return;
if (proc.Destroyed) return;
var linkedHarvs = proc.World.ActorsWithTrait<Harvester>()
.Where(a => a.Trait.LinkedProc == proc)
@@ -147,7 +149,7 @@ namespace OpenRA.Mods.RA
{
// Check that we're not in a critical location and being useless (refinery drop-off):
var lastproc = LastLinkedProc ?? LinkedProc;
if (lastproc != null)
if (lastproc != null && !lastproc.Destroyed)
{
var deliveryLoc = lastproc.Location + lastproc.Trait<IAcceptOre>().DeliverOffset;
if (self.Location == deliveryLoc)
@@ -191,6 +193,9 @@ namespace OpenRA.Mods.RA
public void TickIdle(Actor self)
{
// Should we be intelligent while idle?
if (!idleSmart) return;
// Are we not empty? Deliver resources:
if (!IsEmpty)
{
@@ -262,9 +267,11 @@ namespace OpenRA.Mods.RA
{
// NOTE: An explicit harvest order allows the harvester to decide which refinery to deliver to.
LinkProc(self, OwnerLinkedProc = null);
idleSmart = true;
var mobile = self.Trait<Mobile>();
self.CancelActivity();
var mobile = self.Trait<Mobile>();
if (order.TargetLocation != CPos.Zero)
{
var loc = order.TargetLocation;
@@ -290,7 +297,7 @@ namespace OpenRA.Mods.RA
else
{
// A bot order gives us a CPos.Zero TargetLocation, so find some good resources for him:
CPos? loc = FindNextResourceForBot(self);
var loc = FindNextResourceForBot(self);
// No more resources? Oh well.
if (!loc.HasValue)
return;
@@ -301,6 +308,8 @@ namespace OpenRA.Mods.RA
LastOrderLocation = loc;
}
// This prevents harvesters returning to an empty patch when the player orders them to a new patch:
LastHarvestedCell = LastOrderLocation;
self.QueueActivity(new FindResources());
}
else if (order.OrderString == "Deliver")
@@ -316,11 +325,18 @@ namespace OpenRA.Mods.RA
if (IsEmpty)
return;
idleSmart = true;
self.SetTargetLine(Target.FromOrder(order), Color.Green);
self.CancelActivity();
self.QueueActivity(new DeliverResources());
}
else if (order.OrderString == "Stop" || order.OrderString == "Move")
{
// Turn off idle smarts to obey the stop/move:
idleSmart = false;
}
}
CPos? FindNextResourceForBot(Actor self)

View File

@@ -258,6 +258,7 @@ namespace OpenRA.Mods.RA.Missions
chinook.QueueActivity(new Turn(0));
chinook.QueueActivity(new HeliLand(true));
chinook.QueueActivity(new UnloadCargo());
chinook.QueueActivity(new UnloadCargo(true));
chinook.QueueActivity(new CallFunc(() => Sound.Play("laugh1.aud")));
chinook.QueueActivity(new Wait(150));
chinook.QueueActivity(new HeliFly(chinookExitPoint.CenterLocation));

View File

@@ -456,6 +456,10 @@ namespace OpenRA.Mods.RA.Move
{
IsQueued = forceQueued;
cursor = "move";
if (self.World.LocalPlayer.Shroud.IsExplored(location))
cursor = self.World.GetTerrainInfo(location).CustomCursor ?? cursor;
if (!self.World.Map.IsInMap(location) || (self.World.LocalPlayer.Shroud.IsExplored(location) &&
unitType.MovementCostForCell(self.World, location) == int.MaxValue))
cursor = "move-blocked";

View File

@@ -127,6 +127,7 @@
<Compile Include="Attack\AttackBase.cs" />
<Compile Include="Attack\AttackFrontal.cs" />
<Compile Include="Attack\AttackLeap.cs" />
<Compile Include="Attack\AttackLoyalty.cs" />
<Compile Include="Attack\AttackMedic.cs" />
<Compile Include="Attack\AttackOmni.cs" />
<Compile Include="Attack\AttackPopupTurreted.cs" />
@@ -384,6 +385,7 @@
<Compile Include="World\PlayMusicOnMapLoad.cs" />
<Compile Include="World\SmudgeLayer.cs" />
<Compile Include="Player\BaseAttackNotifier.cs" />
<Compile Include="Player\HarvesterAttackNotifier.cs" />
<Compile Include="InfiltrateForExploration.cs" />
<Compile Include="InfiltrateForCash.cs" />
<Compile Include="RenderShroudCircle.cs" />

View File

@@ -58,8 +58,7 @@ namespace OpenRA.Mods.RA.Orders
if (!world.CanPlaceBuilding( Building, BuildingInfo, topLeft, null)
|| !BuildingInfo.IsCloseEnoughToBase(world, Producer.Owner, Building, topLeft))
{
var eva = world.WorldActor.Info.Traits.Get<EvaAlertsInfo>();
Sound.Play(eva.BuildingCannotPlaceAudio);
Sound.PlayNotification(Producer.Owner, "Speech", "BuildingCannotPlaceAudio", Producer.Owner.Country.Race);
yield break;
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2012 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,
@@ -16,7 +16,7 @@ namespace OpenRA.Mods.RA
class PaletteFromCurrentTilesetInfo : ITraitInfo
{
public readonly string Name = null;
public readonly bool Transparent = true;
public readonly int[] ShadowIndex = { };
public object Create(ActorInitializer init) { return new PaletteFromCurrentTileset(init.world, this); }
}
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA
public void InitPalette( OpenRA.Graphics.WorldRenderer wr )
{
wr.AddPalette( info.Name, new Palette( FileSystem.Open( world.TileSet.Palette ), info.Transparent ) );
wr.AddPalette( info.Name, new Palette( FileSystem.Open( world.TileSet.Palette ), info.ShadowIndex ) );
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2012 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,
@@ -19,7 +19,7 @@ namespace OpenRA.Mods.RA
public readonly string Name = null;
public readonly string Tileset = null;
public readonly string Filename = null;
public readonly bool Transparent = true;
public readonly int[] ShadowIndex = { };
public object Create(ActorInitializer init) { return new PaletteFromFile(init.world, this); }
}
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.RA
public void InitPalette( WorldRenderer wr )
{
if( info.Tileset == null || info.Tileset.ToLowerInvariant() == world.Map.Tileset.ToLowerInvariant() )
wr.AddPalette( info.Name, new Palette( FileSystem.Open( info.Filename ), info.Transparent ) );
wr.AddPalette( info.Name, new Palette( FileSystem.Open( info.Filename ), info.ShadowIndex ) );
}
}
}

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA
public class Passenger : IIssueOrder, IResolveOrder, IOrderVoice
{
readonly PassengerInfo info;
public readonly PassengerInfo info;
public Passenger( PassengerInfo info ) { this.info = info; }
public IEnumerable<IOrderTargeter> Orders

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2012 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,
@@ -17,9 +17,7 @@ namespace OpenRA.Mods.RA
{
public class BaseAttackNotifierInfo : ITraitInfo
{
public readonly int NotifyInterval = 30; /* seconds */
public readonly string Audio = "baseatk1.aud";
public readonly string Race = null;
public readonly int NotifyInterval = 30; // seconds
public object Create(ActorInitializer init) { return new BaseAttackNotifier(this); }
}
@@ -35,17 +33,16 @@ namespace OpenRA.Mods.RA
public void Damaged(Actor self, AttackInfo e)
{
if (info.Race != null && info.Race != self.Owner.Country.Race) return;
/* only track last hit against our base */
// only track last hit against our base
if (!self.HasTrait<Building>())
return;
/* don't track self-damage */
// don't track self-damage
if (e.Attacker != null && e.Attacker.Owner == self.Owner)
return;
if (self.World.FrameNumber - lastAttackTime > info.NotifyInterval * 25)
Sound.PlayToPlayer(self.Owner, info.Audio);
Sound.PlayNotification(self.Owner, "Speech", "BaseAttack", self.Owner.Country.Race);
lastAttackLocation = self.CenterLocation.ToCPos();
lastAttackTime = self.World.FrameNumber;

View File

@@ -0,0 +1,52 @@
#region Copyright & License Information
/*
* Copyright 2007-2012 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.Buildings;
using OpenRA.Mods.RA.Effects;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class HarvesterAttackNotifierInfo : ITraitInfo
{
public readonly int NotifyInterval = 30; // seconds
public object Create(ActorInitializer init) { return new HarvesterAttackNotifier(this); }
}
public class HarvesterAttackNotifier : INotifyDamage
{
HarvesterAttackNotifierInfo info;
public int lastAttackTime = -1;
public CPos lastAttackLocation;
public HarvesterAttackNotifier(HarvesterAttackNotifierInfo info) { this.info = info; }
public void Damaged(Actor self, AttackInfo e)
{
// only track last hit against our base
if (!self.HasTrait<Harvester>())
return;
// don't track self-damage
if (e.Attacker != null && e.Attacker.Owner == self.Owner)
return;
if (self.World.FrameNumber - lastAttackTime > info.NotifyInterval * 25)
Sound.PlayNotification(self.Owner, "Speech", "HarvesterAttack", self.Owner.Country.Race);
lastAttackLocation = self.CenterLocation.ToCPos();
lastAttackTime = self.World.FrameNumber;
}
}
}

View File

@@ -82,8 +82,7 @@ namespace OpenRA.Mods.RA
if (GetNumBuildables(self.Owner) > prevItems)
w.Add(new DelayedAction(10,
() => Sound.PlayToPlayer(order.Player,
w.WorldActor.Info.Traits.Get<EvaAlertsInfo>().NewOptions)));
() => Sound.PlayNotification(order.Player, "Speech", "NewOptions", order.Player.Country.Race)));
});
}
}

View File

@@ -66,8 +66,7 @@ namespace OpenRA.Mods.RA
isPrimary = true;
var eva = self.World.WorldActor.Info.Traits.Get<EvaAlertsInfo>();
Sound.PlayToPlayer(self.Owner, eva.PrimaryBuildingSelected);
Sound.PlayNotification(self.Owner, "Speech", "PrimaryBuildingSelected", self.Owner.Country.Race);
}
}

View File

@@ -127,7 +127,7 @@ namespace OpenRA.Mods.RA.Render
self.World.AddFrameEndTask(w =>
{
if (!self.Destroyed)
w.Add(new Corpse(self, "die{0}".F(e.Warhead.InfDeath + 1)));
w.Add(new Corpse(self, "die{0}".F(e.Warhead.InfDeath)));
});
}
}

View File

@@ -20,15 +20,6 @@ namespace OpenRA.Scripting
{
public static void Chronoshift(World world, List<Pair<Actor, CPos>> units, Actor chronosphere, int duration, bool killCargo)
{
if (chronosphere != null)
chronosphere.Trait<RenderBuilding>().PlayCustomAnim(chronosphere, "active");
// Trigger screen desaturate effect
foreach (var a in world.ActorsWithTrait<ChronoshiftPaletteEffect>())
a.Trait.Enable();
Sound.Play("chrono2.aud", units.First().First.CenterLocation);
foreach (var kv in units)
{
var target = kv.First;
@@ -37,8 +28,6 @@ namespace OpenRA.Scripting
if (cs.CanChronoshiftTo(target, targetCell, true))
cs.Teleport(target, targetCell, duration, killCargo,chronosphere);
}
}
}
}

View File

@@ -39,14 +39,6 @@ namespace OpenRA.Mods.RA
public override void Activate(Actor self, Order order)
{
self.Trait<RenderBuilding>().PlayCustomAnim(self, "active");
// Trigger screen desaturate effect
foreach (var a in self.World.ActorsWithTrait<ChronoshiftPaletteEffect>())
a.Trait.Enable();
Sound.Play("chrono2.aud", order.TargetLocation.ToPPos());
Sound.Play("chrono2.aud", order.ExtraLocation.ToPPos());
foreach (var target in UnitsInRange(order.ExtraLocation))
{
var cs = target.Trait<Chronoshiftable>();

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.RA
{
public float GetDamageModifier(Actor attacker, WarheadInfo warhead )
{
if( warhead != null && warhead.InfDeath == 5 )
if( warhead != null && warhead.InfDeath == 6 )
return 1000f;
return 1f;
}

View File

@@ -42,4 +42,6 @@ namespace OpenRA.Mods.RA
{
void OnNotifyResourceClaimLost(Actor self, ResourceClaim claim, Actor claimer);
}
public interface INotifyParachuteLanded { void OnLanded(); }
}

View File

@@ -44,9 +44,6 @@ namespace OpenRA.Mods.RA.Widgets
List<Pair<Rectangle, Action<MouseInput>>> tabs = new List<Pair<Rectangle, Action<MouseInput>>>();
Animation cantBuild;
Animation clock;
public readonly string BuildPaletteOpen = "bleep13.aud";
public readonly string BuildPaletteClose = "bleep13.aud";
public readonly string TabClick = "ramenu1.aud";
readonly WorldRenderer worldRenderer;
readonly World world;
@@ -118,11 +115,11 @@ namespace OpenRA.Mods.RA.Widgets
// Play palette-open sound at the start of the activate anim (open)
if (paletteAnimationFrame == 1 && paletteOpen)
Sound.Play(BuildPaletteOpen);
Sound.PlayNotification(null, "Sounds", "BuildPaletteOpen", null);
// Play palette-close sound at the start of the activate anim (close)
if (paletteAnimationFrame == paletteAnimationLength + -1 && !paletteOpen)
Sound.Play(BuildPaletteClose);
Sound.PlayNotification(null, "Sounds", "BuildPaletteClose", null);
// Animation is complete
if ((paletteAnimationFrame == 0 && !paletteOpen)
@@ -291,7 +288,7 @@ namespace OpenRA.Mods.RA.Widgets
Action<MouseInput> HandleClick(string name, World world)
{
return mi => {
Sound.Play(TabClick);
Sound.PlayNotification(null, "Sounds", "TabClick", null);
if (name != null)
HandleBuildPalette(world, name, (mi.Button == MouseButton.Left));
@@ -304,7 +301,7 @@ namespace OpenRA.Mods.RA.Widgets
if (mi.Button != MouseButton.Left)
return;
Sound.Play(TabClick);
Sound.PlayNotification(null, "Sounds", "TabClick", null);
var wasOpen = paletteOpen;
paletteOpen = (CurrentQueue == queue && wasOpen) ? false : true;
CurrentQueue = queue;
@@ -496,7 +493,7 @@ namespace OpenRA.Mods.RA.Widgets
if ( toBuild != null )
{
Sound.Play(TabClick);
Sound.PlayNotification(null, "Sounds", "TabClick", null);
HandleBuildPalette(world, toBuild.Name, true);
return true;
}
@@ -507,7 +504,7 @@ namespace OpenRA.Mods.RA.Widgets
void TabChange(bool shift)
{
var queues = VisibleQueues.Concat(VisibleQueues);
if (shift) queues.Reverse();
if (shift) queues = queues.Reverse();
var nextQueue = queues.SkipWhile( q => q != CurrentQueue )
.ElementAtOrDefault(1);
if (nextQueue != null)

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
};
cheatsButton.IsVisible = () => world.LocalPlayer != null && world.LobbyInfo.GlobalSettings.AllowCheats;
optionsBG.Get<ButtonWidget>("DISCONNECT").OnClick = () => LeaveGame(optionsBG);
optionsBG.Get<ButtonWidget>("DISCONNECT").OnClick = () => LeaveGame(optionsBG, world);
optionsBG.Get<ButtonWidget>("SETTINGS").OnClick = () => Ui.OpenWindow("SETTINGS_MENU");
optionsBG.Get<ButtonWidget>("MUSIC").OnClick = () => Ui.OpenWindow("MUSIC_MENU");
@@ -57,7 +57,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var postGameObserve = postgameBG.Get<ButtonWidget>("POSTGAME_OBSERVE");
var postgameQuit = postgameBG.Get<ButtonWidget>("POSTGAME_QUIT");
postgameQuit.OnClick = () => LeaveGame(postgameQuit);
postgameQuit.OnClick = () => LeaveGame(postgameQuit, world);
postGameObserve.OnClick = () => postgameQuit.Visible = false;
postGameObserve.IsVisible = () => world.LocalPlayer.WinState != WinState.Won;
@@ -76,8 +76,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic
};
}
void LeaveGame(Widget pane)
void LeaveGame(Widget pane, World world)
{
Sound.PlayNotification(null, "Speech", "Leave", world.LocalPlayer.Country.Race);
pane.Visible = false;
Game.Disconnect();
Game.LoadShellMap();

View File

@@ -237,7 +237,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
chatPanel.AddChild(template);
chatPanel.ScrollToBottom();
Sound.Play("scold1.aud");
Sound.PlayNotification(null, "Sounds", "ChatLine", null);
}
void UpdateCurrentMap()

View File

@@ -175,8 +175,7 @@ namespace OpenRA.Mods.RA.Widgets
if (hasRadarNew != hasRadar)
{
radarAnimating = true;
var eva = Rules.Info["world"].Traits.Get<EvaAlertsInfo>();
Sound.Play(hasRadarNew ? eva.RadarUp : eva.RadarDown);
Sound.PlayNotification(null, "Sounds", (hasRadarNew ? "RadarUp" : "RadarDown"), null);
}
hasRadar = hasRadarNew;