Merge pull request #3450 from pchote/offset-sprites
Allow sequences to define sprite offsets
This commit is contained in:
@@ -52,19 +52,14 @@ namespace OpenRA.Graphics
|
|||||||
readonly int zOffset;
|
readonly int zOffset;
|
||||||
readonly PaletteReference palette;
|
readonly PaletteReference palette;
|
||||||
readonly float scale;
|
readonly float scale;
|
||||||
readonly float2 pxCenter;
|
|
||||||
|
|
||||||
public SpriteRenderable(Sprite sprite, WPos pos, int zOffset, PaletteReference palette, float scale)
|
public SpriteRenderable(Sprite sprite, WPos pos, int zOffset, PaletteReference palette, float scale)
|
||||||
: this(sprite, pos, zOffset, palette, scale, 0.5f*scale*sprite.size) {}
|
|
||||||
|
|
||||||
public SpriteRenderable(Sprite sprite, WPos pos, int zOffset, PaletteReference palette, float scale, float2 pxCenter)
|
|
||||||
{
|
{
|
||||||
this.sprite = sprite;
|
this.sprite = sprite;
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
this.zOffset = zOffset;
|
this.zOffset = zOffset;
|
||||||
this.palette = palette;
|
this.palette = palette;
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
this.pxCenter = pxCenter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provided for legacy support only - Don't use for new things!
|
// Provided for legacy support only - Don't use for new things!
|
||||||
@@ -84,12 +79,12 @@ namespace OpenRA.Graphics
|
|||||||
public void BeforeRender(WorldRenderer wr) {}
|
public void BeforeRender(WorldRenderer wr) {}
|
||||||
public void Render(WorldRenderer wr)
|
public void Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
sprite.DrawAt(wr.ScreenPxPosition(pos) - pxCenter, palette, scale);
|
sprite.DrawAt(wr.ScreenPxPosition(pos) - 0.5f*scale*sprite.size, palette, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RenderDebugGeometry(WorldRenderer wr)
|
public void RenderDebugGeometry(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
var offset = wr.ScreenPxPosition(pos) - pxCenter;
|
var offset = wr.ScreenPxPosition(pos) - 0.5f*scale*sprite.size + sprite.offset;
|
||||||
Game.Renderer.WorldLineRenderer.DrawRect(offset, offset + sprite.size, Color.Red);
|
Game.Renderer.WorldLineRenderer.DrawRect(offset, offset + sprite.size, Color.Red);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using OpenRA.FileFormats;
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
namespace OpenRA.Graphics
|
namespace OpenRA.Graphics
|
||||||
@@ -34,10 +35,18 @@ namespace OpenRA.Graphics
|
|||||||
var srcOverride = info.Value;
|
var srcOverride = info.Value;
|
||||||
Name = name;
|
Name = name;
|
||||||
var d = info.NodesDict;
|
var d = info.NodesDict;
|
||||||
|
var offset = float2.Zero;
|
||||||
|
|
||||||
sprites = Game.modData.SpriteLoader.LoadAllSprites(srcOverride ?? unit);
|
|
||||||
start = int.Parse(d["Start"].Value);
|
start = int.Parse(d["Start"].Value);
|
||||||
|
|
||||||
|
if (d.ContainsKey("Offset"))
|
||||||
|
offset = FieldLoader.GetValue<float2>("Offset", d["Offset"].Value);
|
||||||
|
|
||||||
|
// Apply offset to each sprite in the sequence
|
||||||
|
// Different sequences may apply different offsets to the same frame
|
||||||
|
sprites = Game.modData.SpriteLoader.LoadAllSprites(srcOverride ?? unit).Select(
|
||||||
|
s => new Sprite(s.sheet, s.bounds, s.offset + offset, s.channel)).ToArray();
|
||||||
|
|
||||||
if (!d.ContainsKey("Length"))
|
if (!d.ContainsKey("Length"))
|
||||||
length = 1;
|
length = 1;
|
||||||
else if (d["Length"].Value == "*")
|
else if (d["Length"].Value == "*")
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace OpenRA.Traits
|
|||||||
RenderSimpleInfo Info;
|
RenderSimpleInfo Info;
|
||||||
|
|
||||||
public RenderSimple(Actor self, Func<int> baseFacing)
|
public RenderSimple(Actor self, Func<int> baseFacing)
|
||||||
: base(self, baseFacing)
|
: base(self)
|
||||||
{
|
{
|
||||||
anims.Add("", new Animation(GetImage(self), baseFacing));
|
anims.Add("", new Animation(GetImage(self), baseFacing));
|
||||||
Info = self.Info.Traits.Get<RenderSimpleInfo>();
|
Info = self.Info.Traits.Get<RenderSimpleInfo>();
|
||||||
@@ -55,13 +55,9 @@ namespace OpenRA.Traits
|
|||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual string NormalizeSequence(Actor self, string baseSequence)
|
public string NormalizeSequence(Actor self, string baseSequence)
|
||||||
{
|
{
|
||||||
string damageState = self.GetDamageState() >= DamageState.Heavy ? "damaged-" : "";
|
return NormalizeSequence(anim, self.GetDamageState(), baseSequence);
|
||||||
if (anim.HasSequence(damageState + baseSequence))
|
|
||||||
return damageState + baseSequence;
|
|
||||||
else
|
|
||||||
return baseSequence;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PlayCustomAnim(Actor self, string name)
|
public void PlayCustomAnim(Actor self, string name)
|
||||||
|
|||||||
@@ -54,14 +54,11 @@ namespace OpenRA.Traits
|
|||||||
bool initializePalette = true;
|
bool initializePalette = true;
|
||||||
protected PaletteReference palette;
|
protected PaletteReference palette;
|
||||||
|
|
||||||
public RenderSprites(Actor self, Func<int> baseFacing)
|
public RenderSprites(Actor self)
|
||||||
{
|
{
|
||||||
Info = self.Info.Traits.Get<RenderSpritesInfo>();
|
Info = self.Info.Traits.Get<RenderSpritesInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderSprites(Actor self)
|
|
||||||
: this(self, MakeFacingFunc(self)) {}
|
|
||||||
|
|
||||||
public static string GetImage(ActorInfo actor)
|
public static string GetImage(ActorInfo actor)
|
||||||
{
|
{
|
||||||
var Info = actor.Traits.Get<RenderSpritesInfo>();
|
var Info = actor.Traits.Get<RenderSpritesInfo>();
|
||||||
@@ -103,5 +100,21 @@ namespace OpenRA.Traits
|
|||||||
a.Animation.Tick();
|
a.Animation.Tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string NormalizeSequence(Animation anim, DamageState state, string baseSequence)
|
||||||
|
{
|
||||||
|
var states = new Pair<DamageState, string>[]
|
||||||
|
{
|
||||||
|
Pair.New(DamageState.Critical, "critical-"),
|
||||||
|
Pair.New(DamageState.Heavy, "damaged-"),
|
||||||
|
Pair.New(DamageState.Medium, "scratched-"),
|
||||||
|
Pair.New(DamageState.Light, "scuffed-")
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var s in states)
|
||||||
|
if (state >= s.First && anim.HasSequence(s.Second+baseSequence))
|
||||||
|
return s.Second+baseSequence;
|
||||||
|
|
||||||
|
return baseSequence;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,6 @@
|
|||||||
<Compile Include="ProductionAirdrop.cs" />
|
<Compile Include="ProductionAirdrop.cs" />
|
||||||
<Compile Include="ProductionQueueFromSelection.cs" />
|
<Compile Include="ProductionQueueFromSelection.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="RenderBuildingRefinery.cs" />
|
|
||||||
<Compile Include="WithCargo.cs" />
|
<Compile Include="WithCargo.cs" />
|
||||||
<Compile Include="RenderGunboat.cs" />
|
<Compile Include="RenderGunboat.cs" />
|
||||||
<Compile Include="SpawnViceroid.cs" />
|
<Compile Include="SpawnViceroid.cs" />
|
||||||
|
|||||||
@@ -1,67 +0,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.Linq;
|
|
||||||
using OpenRA.Graphics;
|
|
||||||
using OpenRA.Traits;
|
|
||||||
using OpenRA.Mods.RA.Render;
|
|
||||||
|
|
||||||
namespace OpenRA.Mods.Cnc
|
|
||||||
{
|
|
||||||
class RenderBuildingRefineryInfo : RenderBuildingInfo
|
|
||||||
{
|
|
||||||
public readonly WVec Offset = new WVec(1365, 896, 0);
|
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new RenderBuildingRefinery(init, this); }
|
|
||||||
}
|
|
||||||
|
|
||||||
class RenderBuildingRefinery : RenderBuilding, INotifyBuildComplete, INotifySold, INotifyCapture
|
|
||||||
{
|
|
||||||
public Animation lights;
|
|
||||||
PlayerResources playerResources;
|
|
||||||
bool buildComplete;
|
|
||||||
|
|
||||||
public RenderBuildingRefinery(ActorInitializer init, RenderBuildingRefineryInfo info)
|
|
||||||
: base(init, info)
|
|
||||||
{
|
|
||||||
playerResources = init.self.Owner.PlayerActor.Trait<PlayerResources>();
|
|
||||||
|
|
||||||
lights = new Animation(GetImage(init.self));
|
|
||||||
lights.PlayFetchIndex("lights",
|
|
||||||
() => playerResources.OreCapacity != 0
|
|
||||||
? (59 * playerResources.Ore) / (10 * playerResources.OreCapacity)
|
|
||||||
: 0);
|
|
||||||
|
|
||||||
anims.Add("lights", new AnimationWithOffset(lights, () => info.Offset, () => !buildComplete, 1024));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void BuildingComplete( Actor self )
|
|
||||||
{
|
|
||||||
buildComplete = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void DamageStateChanged(Actor self, AttackInfo e)
|
|
||||||
{
|
|
||||||
if (lights.CurrentSequence != null)
|
|
||||||
lights.ReplaceAnim(NormalizeSequence(self, "lights"));
|
|
||||||
|
|
||||||
base.DamageStateChanged(self, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCapture (Actor self, Actor captor, Player oldOwner, Player newOwner)
|
|
||||||
{
|
|
||||||
playerResources = newOwner.PlayerActor.Trait<PlayerResources>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Selling(Actor self) { anims.Remove("lights"); }
|
|
||||||
public void Sold(Actor self) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,66 +10,55 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.RA.Render
|
namespace OpenRA.Mods.RA.Render
|
||||||
{
|
{
|
||||||
class RenderGunboatInfo : RenderSimpleInfo
|
class RenderGunboatInfo : RenderSpritesInfo, Requires<IBodyOrientationInfo>
|
||||||
{
|
{
|
||||||
public override object Create(ActorInitializer init) { return new RenderGunboat(init.self); }
|
[Desc("Turreted 'Turret' key to display")]
|
||||||
|
public readonly string Turret = "primary";
|
||||||
|
|
||||||
|
public override object Create(ActorInitializer init) { return new RenderGunboat(init.self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
class RenderGunboat : RenderSimple, INotifyDamageStateChanged
|
class RenderGunboat : RenderSprites, INotifyDamageStateChanged
|
||||||
{
|
{
|
||||||
IFacing facing;
|
Animation left, right;
|
||||||
string lastDir = "left";
|
|
||||||
string lastDamage = "";
|
|
||||||
|
|
||||||
static Func<int> TurretFacingFunc(Actor self)
|
public RenderGunboat(Actor self, RenderGunboatInfo info)
|
||||||
|
: base(self)
|
||||||
{
|
{
|
||||||
return () => self.HasTrait<Turreted>() ? self.TraitsImplementing<Turreted>().First().turretFacing : 0;
|
var name = GetImage(self);
|
||||||
}
|
var facing = self.Trait<IFacing>();
|
||||||
|
var turret = self.TraitsImplementing<Turreted>()
|
||||||
|
.First(t => t.Name == info.Turret);
|
||||||
|
|
||||||
public RenderGunboat(Actor self)
|
left = new Animation(name, () => turret.turretFacing);
|
||||||
: base(self, TurretFacingFunc(self))
|
left.Play("left");
|
||||||
{
|
anims.Add("left", new AnimationWithOffset(left, null, () => facing.Facing > 128, 0));
|
||||||
facing = self.Trait<IFacing>();
|
|
||||||
anim.Play("left");
|
|
||||||
|
|
||||||
var wake = new Animation(anim.Name);
|
right = new Animation(name, () => turret.turretFacing);
|
||||||
wake.Play("left-wake");
|
right.Play("right");
|
||||||
|
anims.Add("right", new AnimationWithOffset(right, null, () => facing.Facing <= 128, 0));
|
||||||
|
|
||||||
var leftOffset = new WVec(43, 86, 0);
|
var leftWake = new Animation(name);
|
||||||
var rightOffset = new WVec(-43, 86, 0);
|
leftWake.Play("wake-left");
|
||||||
anims.Add("wake", new AnimationWithOffset(wake,
|
anims.Add("wake-left", new AnimationWithOffset(leftWake, null, () => facing.Facing > 128, -87));
|
||||||
() => anims["wake"].Animation.CurrentSequence.Name == "left-wake" ? leftOffset : rightOffset,
|
|
||||||
() => false, -87));
|
|
||||||
|
|
||||||
self.Trait<IBodyOrientation>().QuantizedFacings = anim.CurrentSequence.Facings;
|
var rightWake = new Animation(name);
|
||||||
}
|
rightWake.Play("wake-right");
|
||||||
|
anims.Add("wake-right", new AnimationWithOffset(rightWake, null, () => facing.Facing <= 128, -87));
|
||||||
|
|
||||||
public override void Tick(Actor self)
|
self.Trait<IBodyOrientation>().QuantizedFacings = 2;
|
||||||
{
|
|
||||||
var dir = (facing.Facing > 128) ? "right" : "left";
|
|
||||||
if (dir != lastDir)
|
|
||||||
{
|
|
||||||
anim.ReplaceAnim(dir+lastDamage);
|
|
||||||
anims["wake"].Animation.ReplaceAnim(dir+"-wake");
|
|
||||||
lastDir = dir;
|
|
||||||
}
|
|
||||||
base.Tick(self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DamageStateChanged(Actor self, AttackInfo e)
|
public void DamageStateChanged(Actor self, AttackInfo e)
|
||||||
{
|
{
|
||||||
if (e.DamageState >= DamageState.Critical)
|
left.ReplaceAnim(NormalizeSequence(left, e.DamageState, "left"));
|
||||||
lastDamage = "-critical";
|
right.ReplaceAnim(NormalizeSequence(right, e.DamageState, "right"));
|
||||||
else if (e.DamageState >= DamageState.Heavy)
|
|
||||||
lastDamage = "-damaged";
|
|
||||||
else if (e.DamageState < DamageState.Heavy)
|
|
||||||
lastDamage = "";
|
|
||||||
anim.ReplaceAnim(lastDir+lastDamage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ namespace OpenRA.Mods.Cnc
|
|||||||
{
|
{
|
||||||
class WithFireInfo : ITraitInfo, Requires<RenderSpritesInfo>
|
class WithFireInfo : ITraitInfo, Requires<RenderSpritesInfo>
|
||||||
{
|
{
|
||||||
public readonly WVec Offset = new WVec(299,-640,0);
|
|
||||||
|
|
||||||
public object Create(ActorInitializer init) { return new WithFire(init.self, this); }
|
public object Create(ActorInitializer init) { return new WithFire(init.self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,8 +25,7 @@ namespace OpenRA.Mods.Cnc
|
|||||||
var rs = self.Trait<RenderSprites>();
|
var rs = self.Trait<RenderSprites>();
|
||||||
var roof = new Animation(rs.GetImage(self));
|
var roof = new Animation(rs.GetImage(self));
|
||||||
roof.PlayThen("fire-start", () => roof.PlayRepeating("fire-loop"));
|
roof.PlayThen("fire-start", () => roof.PlayRepeating("fire-loop"));
|
||||||
|
rs.anims.Add("fire", new AnimationWithOffset(roof, null, null, 1024));
|
||||||
rs.anims.Add("fire", new AnimationWithOffset(roof, () => info.Offset, null, 1024));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ namespace OpenRA.Mods.RA
|
|||||||
public readonly string Anim = "1";
|
public readonly string Anim = "1";
|
||||||
public readonly int Damage = 1;
|
public readonly int Damage = 1;
|
||||||
public readonly int Interval = 8;
|
public readonly int Interval = 8;
|
||||||
public readonly WVec Offset = new WVec(0,0,128);
|
|
||||||
|
|
||||||
public object Create(ActorInitializer init) { return new Burns(init.self, this); }
|
public object Create(ActorInitializer init) { return new Burns(init.self, this); }
|
||||||
}
|
}
|
||||||
@@ -34,8 +33,7 @@ namespace OpenRA.Mods.RA
|
|||||||
|
|
||||||
var anim = new Animation("fire", () => 0);
|
var anim = new Animation("fire", () => 0);
|
||||||
anim.PlayRepeating(Info.Anim);
|
anim.PlayRepeating(Info.Anim);
|
||||||
self.Trait<RenderSprites>().anims.Add("fire",
|
self.Trait<RenderSprites>().anims.Add("fire", anim);
|
||||||
new AnimationWithOffset(anim, () => info.Offset, null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Tick(Actor self)
|
public void Tick(Actor self)
|
||||||
|
|||||||
@@ -17,14 +17,12 @@ namespace OpenRA.Mods.RA.Effects
|
|||||||
{
|
{
|
||||||
class GpsSatellite : IEffect
|
class GpsSatellite : IEffect
|
||||||
{
|
{
|
||||||
float2 Origin;
|
|
||||||
WPos Pos;
|
WPos Pos;
|
||||||
Animation Anim = new Animation("sputnik");
|
Animation Anim = new Animation("sputnik");
|
||||||
|
|
||||||
public GpsSatellite(WPos pos, float2 spriteOrigin)
|
public GpsSatellite(WPos pos)
|
||||||
{
|
{
|
||||||
Pos = pos;
|
Pos = pos;
|
||||||
Origin = spriteOrigin;
|
|
||||||
Anim.PlayRepeating("idle");
|
Anim.PlayRepeating("idle");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +37,7 @@ namespace OpenRA.Mods.RA.Effects
|
|||||||
|
|
||||||
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
yield return new SpriteRenderable(Anim.Image, Pos, 0, wr.Palette("effect"), 1f, Origin);
|
yield return new SpriteRenderable(Anim.Image, Pos, 0, wr.Palette("effect"), 1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace OpenRA.Mods.RA.Effects
|
|||||||
var pos = cachedLocation.CenterPosition;
|
var pos = cachedLocation.CenterPosition;
|
||||||
var palette = wr.Palette(palettePrefix+building.Owner.InternalName);
|
var palette = wr.Palette(palettePrefix+building.Owner.InternalName);
|
||||||
yield return new SpriteRenderable(circles.Image, pos, 0, palette, 1f);
|
yield return new SpriteRenderable(circles.Image, pos, 0, palette, 1f);
|
||||||
yield return new SpriteRenderable(flag.Image, pos, 0, palette, 1f, new int2(1, 17));
|
yield return new SpriteRenderable(flag.Image, pos, 0, palette, 1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ namespace OpenRA.Mods.RA.Effects
|
|||||||
{
|
{
|
||||||
int frame = 0;
|
int frame = 0;
|
||||||
Animation doors = new Animation("atek");
|
Animation doors = new Animation("atek");
|
||||||
float2 doorOrigin = new float2(16,24);
|
|
||||||
WPos pos;
|
WPos pos;
|
||||||
|
|
||||||
public SatelliteLaunch(Actor a)
|
public SatelliteLaunch(Actor a)
|
||||||
@@ -35,12 +34,12 @@ namespace OpenRA.Mods.RA.Effects
|
|||||||
doors.Tick();
|
doors.Tick();
|
||||||
|
|
||||||
if (++frame == 19)
|
if (++frame == 19)
|
||||||
world.AddFrameEndTask(w => w.Add(new GpsSatellite(pos, doorOrigin)));
|
world.AddFrameEndTask(w => w.Add(new GpsSatellite(pos)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
yield return new SpriteRenderable(doors.Image, pos, 0, wr.Palette("effect"), 1f, doorOrigin);
|
yield return new SpriteRenderable(doors.Image, pos, 0, wr.Palette("effect"), 1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -453,6 +453,7 @@
|
|||||||
<Compile Include="Render\WithVoxelBarrel.cs" />
|
<Compile Include="Render\WithVoxelBarrel.cs" />
|
||||||
<Compile Include="Render\WithVoxelWalkerBody.cs" />
|
<Compile Include="Render\WithVoxelWalkerBody.cs" />
|
||||||
<Compile Include="Widgets\Logic\CreditsLogic.cs" />
|
<Compile Include="Widgets\Logic\CreditsLogic.cs" />
|
||||||
|
<Compile Include="Render\WithResources.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||||
|
|||||||
@@ -24,15 +24,8 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
{
|
{
|
||||||
public readonly bool HasMakeAnimation = true;
|
public readonly bool HasMakeAnimation = true;
|
||||||
|
|
||||||
[Desc("Artwork offset in world (not local) coordinates")]
|
|
||||||
public readonly WVec Origin = WVec.Zero;
|
|
||||||
public override object Create(ActorInitializer init) { return new RenderBuilding(init, this);}
|
public override object Create(ActorInitializer init) { return new RenderBuilding(init, this);}
|
||||||
|
|
||||||
public override IEnumerable<IRenderable> RenderPreview(ActorInfo building, PaletteReference pr)
|
|
||||||
{
|
|
||||||
return base.RenderPreview(building, pr).Select(a => a.WithPos(a.Pos + Origin));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Render(WorldRenderer wr, World w, ActorInfo ai, PPos centerLocation)
|
public void Render(WorldRenderer wr, World w, ActorInfo ai, PPos centerLocation)
|
||||||
{
|
{
|
||||||
if (!ai.Traits.Get<BuildingInfo>().RequiresBaseProvider)
|
if (!ai.Traits.Get<BuildingInfo>().RequiresBaseProvider)
|
||||||
@@ -45,16 +38,14 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
|
|
||||||
public class RenderBuilding : RenderSimple, INotifyDamageStateChanged, IRenderModifier
|
public class RenderBuilding : RenderSimple, INotifyDamageStateChanged, IRenderModifier
|
||||||
{
|
{
|
||||||
readonly RenderBuildingInfo Info;
|
public RenderBuilding(ActorInitializer init, RenderBuildingInfo info)
|
||||||
|
|
||||||
public RenderBuilding( ActorInitializer init, RenderBuildingInfo info )
|
|
||||||
: this(init, info, () => 0) { }
|
: this(init, info, () => 0) { }
|
||||||
|
|
||||||
public RenderBuilding( ActorInitializer init, RenderBuildingInfo info, Func<int> baseFacing )
|
public RenderBuilding(ActorInitializer init, RenderBuildingInfo info, Func<int> baseFacing)
|
||||||
: base(init.self, baseFacing)
|
: base(init.self, baseFacing)
|
||||||
{
|
{
|
||||||
Info = info;
|
|
||||||
var self = init.self;
|
var self = init.self;
|
||||||
|
|
||||||
// Work around a bogus crash
|
// Work around a bogus crash
|
||||||
anim.PlayRepeating( NormalizeSequence(self, "idle") );
|
anim.PlayRepeating( NormalizeSequence(self, "idle") );
|
||||||
self.Trait<IBodyOrientation>().QuantizedFacings = anim.CurrentSequence.Facings;
|
self.Trait<IBodyOrientation>().QuantizedFacings = anim.CurrentSequence.Facings;
|
||||||
@@ -71,18 +62,17 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
var disabled = self.IsDisabled();
|
var disabled = self.IsDisabled();
|
||||||
foreach (var a in r)
|
foreach (var a in r)
|
||||||
{
|
{
|
||||||
var ret = a.WithPos(a.Pos + Info.Origin);
|
yield return a;
|
||||||
yield return ret;
|
|
||||||
if (disabled)
|
if (disabled)
|
||||||
yield return ret.WithPalette(wr.Palette("disabled")).WithZOffset(1);
|
yield return a.WithPalette(wr.Palette("disabled")).WithZOffset(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Complete( Actor self )
|
void Complete(Actor self)
|
||||||
{
|
{
|
||||||
anim.PlayRepeating( NormalizeSequence(self, "idle") );
|
anim.PlayRepeating(NormalizeSequence(self, "idle"));
|
||||||
foreach( var x in self.TraitsImplementing<INotifyBuildComplete>() )
|
foreach (var x in self.TraitsImplementing<INotifyBuildComplete>())
|
||||||
x.BuildingComplete( self );
|
x.BuildingComplete(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PlayCustomAnimThen(Actor self, string name, Action a)
|
public void PlayCustomAnimThen(Actor self, string name, Action a)
|
||||||
@@ -94,7 +84,7 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
public void PlayCustomAnimRepeating(Actor self, string name)
|
public void PlayCustomAnimRepeating(Actor self, string name)
|
||||||
{
|
{
|
||||||
anim.PlayThen(NormalizeSequence(self, name),
|
anim.PlayThen(NormalizeSequence(self, name),
|
||||||
() => { PlayCustomAnimRepeating(self, name); });
|
() => PlayCustomAnimRepeating(self, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PlayCustomAnimBackwards(Actor self, string name, Action a)
|
public void PlayCustomAnimBackwards(Actor self, string name, Action a)
|
||||||
@@ -105,15 +95,13 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
|
|
||||||
public void CancelCustomAnim(Actor self)
|
public void CancelCustomAnim(Actor self)
|
||||||
{
|
{
|
||||||
anim.PlayRepeating( NormalizeSequence(self, "idle") );
|
anim.PlayRepeating(NormalizeSequence(self, "idle"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void DamageStateChanged(Actor self, AttackInfo e)
|
public virtual void DamageStateChanged(Actor self, AttackInfo e)
|
||||||
{
|
{
|
||||||
if (e.DamageState >= DamageState.Heavy && e.PreviousDamageState < DamageState.Heavy)
|
if (anim.CurrentSequence != null)
|
||||||
anim.ReplaceAnim("damaged-idle");
|
anim.ReplaceAnim(NormalizeSequence(self, "idle"));
|
||||||
else if (e.DamageState < DamageState.Heavy)
|
|
||||||
anim.ReplaceAnim("idle");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,20 +14,17 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
{
|
{
|
||||||
class RenderBuildingSiloInfo : RenderBuildingInfo
|
class RenderBuildingSiloInfo : RenderBuildingInfo
|
||||||
{
|
{
|
||||||
public readonly int FillSteps = 49;
|
|
||||||
public override object Create(ActorInitializer init) { return new RenderBuildingSilo(init, this); }
|
public override object Create(ActorInitializer init) { return new RenderBuildingSilo(init, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
class RenderBuildingSilo : RenderBuilding, INotifyBuildComplete, INotifyCapture
|
class RenderBuildingSilo : RenderBuilding, INotifyBuildComplete, INotifyCapture
|
||||||
{
|
{
|
||||||
PlayerResources playerResources;
|
PlayerResources playerResources;
|
||||||
readonly RenderBuildingSiloInfo Info;
|
|
||||||
|
|
||||||
public RenderBuildingSilo( ActorInitializer init, RenderBuildingSiloInfo info )
|
public RenderBuildingSilo( ActorInitializer init, RenderBuildingSiloInfo info )
|
||||||
: base(init, info)
|
: base(init, info)
|
||||||
{
|
{
|
||||||
playerResources = init.self.Owner.PlayerActor.Trait<PlayerResources>();
|
playerResources = init.self.Owner.PlayerActor.Trait<PlayerResources>();
|
||||||
Info = info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BuildingComplete(Actor self)
|
public void BuildingComplete(Actor self)
|
||||||
@@ -35,7 +32,7 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
var animation = (self.GetDamageState() >= DamageState.Heavy) ? "damaged-idle" : "idle";
|
var animation = (self.GetDamageState() >= DamageState.Heavy) ? "damaged-idle" : "idle";
|
||||||
anim.PlayFetchIndex(animation,
|
anim.PlayFetchIndex(animation,
|
||||||
() => playerResources.OreCapacity != 0
|
() => playerResources.OreCapacity != 0
|
||||||
? (Info.FillSteps * playerResources.Ore) / (10 * playerResources.OreCapacity)
|
? ((10 * anim.CurrentSequence.Length - 1) * playerResources.Ore) / (10 * playerResources.OreCapacity)
|
||||||
: 0);
|
: 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,16 +37,7 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
|
|
||||||
public override void DamageStateChanged(Actor self, AttackInfo e)
|
public override void DamageStateChanged(Actor self, AttackInfo e)
|
||||||
{
|
{
|
||||||
if (e.DamageState == DamageState.Medium && anim.HasSequence("scratched-idle"))
|
anim.PlayFetchIndex(NormalizeSequence(anim, e.DamageState, "idle"), () => adjacentWalls);
|
||||||
seqName = "scratched-idle";
|
|
||||||
else if (e.DamageState <= DamageState.Medium)
|
|
||||||
seqName = "idle";
|
|
||||||
else if (e.DamageState == DamageState.Critical && anim.HasSequence("critical-idle"))
|
|
||||||
seqName = "critical-idle";
|
|
||||||
else if (e.DamageState <= DamageState.Critical)
|
|
||||||
seqName = "damaged-idle";
|
|
||||||
|
|
||||||
anim.PlayFetchIndex(seqName, () => adjacentWalls);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasTicked = false;
|
bool hasTicked = false;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Render
|
|||||||
|
|
||||||
var anim = new Animation(RenderSprites.GetImage(building), () => 0);
|
var anim = new Animation(RenderSprites.GetImage(building), () => 0);
|
||||||
anim.PlayRepeating("idle-top");
|
anim.PlayRepeating("idle-top");
|
||||||
yield return new SpriteRenderable(anim.Image, WPos.Zero + Origin, 0, pr, 1f);
|
yield return new SpriteRenderable(anim.Image, WPos.Zero, 0, pr, 1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
70
OpenRA.Mods.RA/Render/WithResources.cs
Executable file
70
OpenRA.Mods.RA/Render/WithResources.cs
Executable file
@@ -0,0 +1,70 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2013 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.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.RA.Render
|
||||||
|
{
|
||||||
|
class WithResourcesInfo : ITraitInfo, Requires<RenderSimpleInfo>
|
||||||
|
{
|
||||||
|
[Desc("Sequence name to use")]
|
||||||
|
public readonly string Sequence = "resources";
|
||||||
|
|
||||||
|
public object Create(ActorInitializer init) { return new WithResources(init.self, this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
class WithResources : INotifyBuildComplete, INotifySold, INotifyCapture, INotifyDamageStateChanged
|
||||||
|
{
|
||||||
|
WithResourcesInfo info;
|
||||||
|
Animation anim;
|
||||||
|
RenderSimple rs;
|
||||||
|
PlayerResources playerResources;
|
||||||
|
bool buildComplete;
|
||||||
|
|
||||||
|
public WithResources(Actor self, WithResourcesInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
rs = self.Trait<RenderSimple>();
|
||||||
|
playerResources = self.Owner.PlayerActor.Trait<PlayerResources>();
|
||||||
|
|
||||||
|
anim = new Animation(rs.GetImage(self));
|
||||||
|
anim.PlayFetchIndex(info.Sequence,
|
||||||
|
() => playerResources.OreCapacity != 0
|
||||||
|
? ((10 * anim.CurrentSequence.Length - 1) * playerResources.Ore) / (10 * playerResources.OreCapacity)
|
||||||
|
: 0);
|
||||||
|
|
||||||
|
rs.anims.Add("resources_{0}".F(info.Sequence), new AnimationWithOffset(
|
||||||
|
anim, null, () => !buildComplete, 1024));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BuildingComplete( Actor self )
|
||||||
|
{
|
||||||
|
buildComplete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DamageStateChanged(Actor self, AttackInfo e)
|
||||||
|
{
|
||||||
|
if (anim.CurrentSequence != null)
|
||||||
|
anim.ReplaceAnim(rs.NormalizeSequence(self, info.Sequence));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCapture (Actor self, Actor captor, Player oldOwner, Player newOwner)
|
||||||
|
{
|
||||||
|
playerResources = newOwner.PlayerActor.Trait<PlayerResources>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Selling(Actor self) { rs.anims.Remove("resources_{0}".F(info.Sequence)); }
|
||||||
|
public void Sold(Actor self) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,8 @@ BOAT:
|
|||||||
LocalOffset: 213,-180,0, 213,128,0, 213,0,0
|
LocalOffset: 213,-180,0, 213,128,0, 213,0,0
|
||||||
AttackTurreted:
|
AttackTurreted:
|
||||||
RenderGunboat:
|
RenderGunboat:
|
||||||
|
Selectable:
|
||||||
|
Bounds: 42,24
|
||||||
AutoTarget:
|
AutoTarget:
|
||||||
AllowMovement: false
|
AllowMovement: false
|
||||||
WithSmoke:
|
WithSmoke:
|
||||||
|
|||||||
@@ -134,8 +134,7 @@ PROC:
|
|||||||
InitialActivity: FindResources
|
InitialActivity: FindResources
|
||||||
SpawnOffset: 1,2
|
SpawnOffset: 1,2
|
||||||
Facing: 64
|
Facing: 64
|
||||||
-RenderBuilding:
|
WithResources:
|
||||||
RenderBuildingRefinery:
|
|
||||||
|
|
||||||
SILO:
|
SILO:
|
||||||
Inherits: ^Building
|
Inherits: ^Building
|
||||||
@@ -161,7 +160,7 @@ SILO:
|
|||||||
Range: 4
|
Range: 4
|
||||||
RenderBuildingSilo:
|
RenderBuildingSilo:
|
||||||
StoresOre:
|
StoresOre:
|
||||||
PipCount: 24
|
PipCount: 10
|
||||||
PipColor: Green
|
PipColor: Green
|
||||||
Capacity: 2400
|
Capacity: 2400
|
||||||
Selectable:
|
Selectable:
|
||||||
|
|||||||
@@ -12,22 +12,26 @@ boat:
|
|||||||
left:
|
left:
|
||||||
Start: 0
|
Start: 0
|
||||||
Facings: 32
|
Facings: 32
|
||||||
left-damaged:
|
damaged-left:
|
||||||
Start: 32
|
Start: 32
|
||||||
left-critical:
|
Facings: 32
|
||||||
|
critical-left:
|
||||||
Start: 64
|
Start: 64
|
||||||
left-wake: wake
|
Facings: 32
|
||||||
|
wake-left: wake
|
||||||
Start: 6
|
Start: 6
|
||||||
Length: 6
|
Length: 6
|
||||||
|
Offset: 1,2
|
||||||
right:
|
right:
|
||||||
Start: 96
|
Start: 96
|
||||||
Facings: 32
|
Facings: 32
|
||||||
right-damaged:
|
damaged-right:
|
||||||
Start: 128
|
Start: 128
|
||||||
Facings: 32
|
Facings: 32
|
||||||
right-critical:
|
critical-right:
|
||||||
Start: 160
|
Start: 160
|
||||||
Facings: 32
|
Facings: 32
|
||||||
right-wake: wake
|
wake-right: wake
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: 6
|
Length: 6
|
||||||
|
Offset: -1,2
|
||||||
@@ -482,9 +482,11 @@ v19.husk:
|
|||||||
fire-start: flmspt
|
fire-start: flmspt
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 7,-15
|
||||||
fire-loop: flmspt
|
fire-loop: flmspt
|
||||||
Start: 50
|
Start: 50
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 7,-15
|
||||||
|
|
||||||
v20:
|
v20:
|
||||||
idle:
|
idle:
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ fire:
|
|||||||
1: fire1
|
1: fire1
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 0,-3
|
||||||
2: fire2
|
2: fire2
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 0,-3
|
||||||
|
|
||||||
120mm:
|
120mm:
|
||||||
idle:
|
idle:
|
||||||
@@ -145,6 +147,7 @@ rallypoint:
|
|||||||
flag:flagfly
|
flag:flagfly
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 10,-5
|
||||||
circles:fpls
|
circles:fpls
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
|||||||
@@ -54,12 +54,14 @@ proc:
|
|||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
Tick: 80
|
Tick: 80
|
||||||
lights: proctwr
|
resources: proctwr
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: 6
|
Length: 6
|
||||||
damaged-lights: proctwr
|
Offset: -32,-21
|
||||||
|
damaged-resources: proctwr
|
||||||
Start: 6
|
Start: 6
|
||||||
Length: 6
|
Length: 6
|
||||||
|
Offset: -32,-21
|
||||||
|
|
||||||
silo:
|
silo:
|
||||||
idle:
|
idle:
|
||||||
|
|||||||
@@ -168,7 +168,6 @@
|
|||||||
Range: 4
|
Range: 4
|
||||||
-RenderBuilding:
|
-RenderBuilding:
|
||||||
RenderBuildingSilo:
|
RenderBuildingSilo:
|
||||||
FillSteps: 39
|
|
||||||
StoresOre:
|
StoresOre:
|
||||||
PipColor: green
|
PipColor: green
|
||||||
PipCount: 5
|
PipCount: 5
|
||||||
|
|||||||
@@ -1143,6 +1143,7 @@ rallypoint:
|
|||||||
flag:flagfly
|
flag:flagfly
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 11,-5
|
||||||
circles:fpls
|
circles:fpls
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
@@ -1259,15 +1260,19 @@ fire:
|
|||||||
1: fire2
|
1: fire2
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 0,-3
|
||||||
2: fire2
|
2: fire2
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 0,-3
|
||||||
3: fire3
|
3: fire3
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 0,-3
|
||||||
4: fire
|
4: fire
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 0,-3
|
||||||
|
|
||||||
smoke_m:
|
smoke_m:
|
||||||
idle: minifire
|
idle: minifire
|
||||||
|
|||||||
@@ -1009,7 +1009,6 @@ SILO:
|
|||||||
RevealsShroud:
|
RevealsShroud:
|
||||||
Range: 4
|
Range: 4
|
||||||
RenderBuildingSilo:
|
RenderBuildingSilo:
|
||||||
FillSteps: 89
|
|
||||||
StoresOre:
|
StoresOre:
|
||||||
PipCount: 5
|
PipCount: 5
|
||||||
Capacity: 1500
|
Capacity: 1500
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ rallypoint:
|
|||||||
flag:flagfly
|
flag:flagfly
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 11,-5
|
||||||
circles:fpls
|
circles:fpls
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
@@ -174,6 +175,7 @@ sputnik:
|
|||||||
idle:
|
idle:
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: -4,0
|
||||||
|
|
||||||
dd-crnr:
|
dd-crnr:
|
||||||
idle:
|
idle:
|
||||||
@@ -319,15 +321,19 @@ fire:
|
|||||||
1: fire1
|
1: fire1
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 0,-3
|
||||||
2: fire2
|
2: fire2
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 0,-3
|
||||||
3: fire3
|
3: fire3
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 0,-3
|
||||||
4: fire4
|
4: fire4
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: 0,-3
|
||||||
|
|
||||||
rank:
|
rank:
|
||||||
rank:
|
rank:
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ atek:
|
|||||||
active: sputdoor
|
active: sputdoor
|
||||||
Start: 0
|
Start: 0
|
||||||
Length: *
|
Length: *
|
||||||
|
Offset: -4,0
|
||||||
|
|
||||||
stek:
|
stek:
|
||||||
idle:
|
idle:
|
||||||
|
|||||||
Reference in New Issue
Block a user