Move FindTilesInCircle from WorldUtils to Map
This commit is contained in:
@@ -573,5 +573,38 @@ namespace OpenRA
|
|||||||
var y = dir.Y == 0 ? int.MaxValue : ((dir.Y < 0 ? tl.Y : br.Y) - pos.Y) / dir.Y;
|
var y = dir.Y == 0 ? int.MaxValue : ((dir.Y < 0 ? tl.Y : br.Y) - pos.Y) / dir.Y;
|
||||||
return new WRange(Math.Min(x, y) * dir.Length);
|
return new WRange(Math.Min(x, y) * dir.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public const int MaxTilesInCircleRange = 50;
|
||||||
|
static List<CVec>[] TilesByDistance = InitTilesByDistance(MaxTilesInCircleRange);
|
||||||
|
|
||||||
|
static List<CVec>[] InitTilesByDistance(int max)
|
||||||
|
{
|
||||||
|
var ts = new List<CVec>[max + 1];
|
||||||
|
for (var i = 0; i < max + 1; i++)
|
||||||
|
ts [i] = new List<CVec>();
|
||||||
|
|
||||||
|
for (var j = -max; j <= max; j++)
|
||||||
|
for (var i = -max; i <= max; i++)
|
||||||
|
if (max * max >= i * i + j * j)
|
||||||
|
ts [(int)Math.Ceiling(Math.Sqrt(i * i + j * j))].Add(new CVec(i, j));
|
||||||
|
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<CPos> FindTilesInCircle(CPos center, int range)
|
||||||
|
{
|
||||||
|
if (range >= TilesByDistance.Length)
|
||||||
|
throw new InvalidOperationException("FindTilesInCircle supports queries for only <= {0}".F(MaxTilesInCircleRange));
|
||||||
|
|
||||||
|
for(var i = 0; i <= range; i++)
|
||||||
|
{
|
||||||
|
foreach(var offset in TilesByDistance[i])
|
||||||
|
{
|
||||||
|
var t = offset + center;
|
||||||
|
if (Bounds.Contains(t.X, t.Y))
|
||||||
|
yield return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,39 +55,6 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<CPos> FindTilesInCircle(this World world, CPos a, int r)
|
|
||||||
{
|
|
||||||
if (r >= TilesByDistance.Length)
|
|
||||||
throw new InvalidOperationException("FindTilesInCircle supports queries for only <= {0}".F(MaxRange));
|
|
||||||
|
|
||||||
for(var i = 0; i <= r; i++)
|
|
||||||
{
|
|
||||||
foreach(var offset in TilesByDistance[i])
|
|
||||||
{
|
|
||||||
var t = offset + a;
|
|
||||||
if (world.Map.Bounds.Contains(t.X, t.Y))
|
|
||||||
yield return t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static List<CVec>[] InitTilesByDistance(int max)
|
|
||||||
{
|
|
||||||
var ts = new List<CVec>[max+1];
|
|
||||||
for (var i = 0; i < max+1; i++)
|
|
||||||
ts[i] = new List<CVec>();
|
|
||||||
|
|
||||||
for (var j = -max; j <= max; j++)
|
|
||||||
for (var i = -max; i <= max; i++)
|
|
||||||
if (max * max >= i * i + j * j)
|
|
||||||
ts[(int)Math.Ceiling(Math.Sqrt(i*i + j*j))].Add(new CVec(i,j));
|
|
||||||
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public const int MaxRange = 50;
|
|
||||||
static List<CVec>[] TilesByDistance = InitTilesByDistance(MaxRange);
|
|
||||||
|
|
||||||
public static CPos ChooseRandomEdgeCell(this World w)
|
public static CPos ChooseRandomEdgeCell(this World w)
|
||||||
{
|
{
|
||||||
var isX = w.SharedRandom.Next(2) == 0;
|
var isX = w.SharedRandom.Next(2) == 0;
|
||||||
|
|||||||
@@ -345,7 +345,7 @@ namespace OpenRA.Mods.RA.AI
|
|||||||
{
|
{
|
||||||
for (var k = MaxBaseDistance; k >= 0; k--)
|
for (var k = MaxBaseDistance; k >= 0; k--)
|
||||||
{
|
{
|
||||||
var tlist = world.FindTilesInCircle(center, k)
|
var tlist = Map.FindTilesInCircle(center, k)
|
||||||
.OrderBy(a => (a.CenterPosition - pos).LengthSquared);
|
.OrderBy(a => (a.CenterPosition - pos).LengthSquared);
|
||||||
|
|
||||||
foreach (var t in tlist)
|
foreach (var t in tlist)
|
||||||
@@ -365,7 +365,7 @@ namespace OpenRA.Mods.RA.AI
|
|||||||
return enemyBase != null ? findPos(enemyBase.CenterPosition, defenseCenter) : null;
|
return enemyBase != null ? findPos(enemyBase.CenterPosition, defenseCenter) : null;
|
||||||
|
|
||||||
case BuildingType.Refinery:
|
case BuildingType.Refinery:
|
||||||
var tilesPos = world.FindTilesInCircle(baseCenter, MaxBaseDistance)
|
var tilesPos = Map.FindTilesInCircle(baseCenter, MaxBaseDistance)
|
||||||
.Where(a => resourceTypeIndices.Contains(Map.GetTerrainIndex(new CPos(a.X, a.Y))));
|
.Where(a => resourceTypeIndices.Contains(Map.GetTerrainIndex(new CPos(a.X, a.Y))));
|
||||||
if (tilesPos.Any())
|
if (tilesPos.Any())
|
||||||
{
|
{
|
||||||
@@ -377,7 +377,7 @@ namespace OpenRA.Mods.RA.AI
|
|||||||
case BuildingType.Building:
|
case BuildingType.Building:
|
||||||
for (var k = 0; k < maxBaseDistance; k++)
|
for (var k = 0; k < maxBaseDistance; k++)
|
||||||
{
|
{
|
||||||
foreach (var t in world.FindTilesInCircle(baseCenter, k))
|
foreach (var t in Map.FindTilesInCircle(baseCenter, k))
|
||||||
{
|
{
|
||||||
if (world.CanPlaceBuilding(actorType, bi, t, null))
|
if (world.CanPlaceBuilding(actorType, bi, t, null))
|
||||||
{
|
{
|
||||||
@@ -696,7 +696,7 @@ namespace OpenRA.Mods.RA.AI
|
|||||||
// Won't work for shipyards...
|
// Won't work for shipyards...
|
||||||
CPos ChooseRallyLocationNear(CPos startPos)
|
CPos ChooseRallyLocationNear(CPos startPos)
|
||||||
{
|
{
|
||||||
var possibleRallyPoints = world.FindTilesInCircle(startPos, Info.RallyPointScanRadius)
|
var possibleRallyPoints = Map.FindTilesInCircle(startPos, Info.RallyPointScanRadius)
|
||||||
.Where(IsRallyPointValid);
|
.Where(IsRallyPointValid);
|
||||||
|
|
||||||
if (!possibleRallyPoints.Any())
|
if (!possibleRallyPoints.Any())
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
bool screenFlash;
|
bool screenFlash;
|
||||||
string sound;
|
string sound;
|
||||||
|
|
||||||
const int maxCellSearchRange = WorldUtils.MaxRange;
|
const int maxCellSearchRange = Map.MaxTilesInCircleRange;
|
||||||
|
|
||||||
public Teleport(Actor chronosphere, CPos destination, int? maximumDistance, bool killCargo, bool screenFlash, string sound)
|
public Teleport(Actor chronosphere, CPos destination, int? maximumDistance, bool killCargo, bool screenFlash, string sound)
|
||||||
{
|
{
|
||||||
@@ -90,7 +90,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
|
|
||||||
CPos? ChooseBestDestinationCell(Actor self, CPos destination)
|
CPos? ChooseBestDestinationCell(Actor self, CPos destination)
|
||||||
{
|
{
|
||||||
var restrictTo = maximumDistance == null ? null : self.World.FindTilesInCircle(self.Location, maximumDistance.Value);
|
var restrictTo = maximumDistance == null ? null : self.World.Map.FindTilesInCircle(self.Location, maximumDistance.Value);
|
||||||
|
|
||||||
if (maximumDistance != null)
|
if (maximumDistance != null)
|
||||||
destination = restrictTo.MinBy(x => (x - destination).LengthSquared);
|
destination = restrictTo.MinBy(x => (x - destination).LengthSquared);
|
||||||
@@ -102,7 +102,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
var searched = new List<CPos>();
|
var searched = new List<CPos>();
|
||||||
for (int r = 1; r <= maxCellSearchRange || (maximumDistance != null && r <= maximumDistance); r++)
|
for (int r = 1; r <= maxCellSearchRange || (maximumDistance != null && r <= maximumDistance); r++)
|
||||||
{
|
{
|
||||||
foreach (var tile in self.World.FindTilesInCircle(destination, r).Except(searched))
|
foreach (var tile in self.World.Map.FindTilesInCircle(destination, r).Except(searched))
|
||||||
{
|
{
|
||||||
if (self.Owner.Shroud.IsExplored(tile)
|
if (self.Owner.Shroud.IsExplored(tile)
|
||||||
&& (restrictTo == null || (restrictTo != null && restrictTo.Contains(tile)))
|
&& (restrictTo == null || (restrictTo != null && restrictTo.Contains(tile)))
|
||||||
|
|||||||
@@ -53,12 +53,12 @@ namespace OpenRA.Mods.RA
|
|||||||
if (warhead.Size[0] > 0)
|
if (warhead.Size[0] > 0)
|
||||||
{
|
{
|
||||||
var resLayer = world.WorldActor.Trait<ResourceLayer>();
|
var resLayer = world.WorldActor.Trait<ResourceLayer>();
|
||||||
var allCells = world.FindTilesInCircle(targetTile, warhead.Size[0]).ToList();
|
var allCells = world.Map.FindTilesInCircle(targetTile, warhead.Size[0]).ToList();
|
||||||
|
|
||||||
// `smudgeCells` might want to just be an outer shell of the cells:
|
// `smudgeCells` might want to just be an outer shell of the cells:
|
||||||
IEnumerable<CPos> smudgeCells = allCells;
|
IEnumerable<CPos> smudgeCells = allCells;
|
||||||
if (warhead.Size.Length == 2)
|
if (warhead.Size.Length == 2)
|
||||||
smudgeCells = smudgeCells.Except(world.FindTilesInCircle(targetTile, warhead.Size[1]));
|
smudgeCells = smudgeCells.Except(world.Map.FindTilesInCircle(targetTile, warhead.Size[1]));
|
||||||
|
|
||||||
// Draw the smudges:
|
// Draw the smudges:
|
||||||
foreach (var sc in smudgeCells)
|
foreach (var sc in smudgeCells)
|
||||||
@@ -110,17 +110,21 @@ namespace OpenRA.Mods.RA
|
|||||||
var damage = (int)GetDamageToInflict(pos, victim, warhead, weapon, firepowerModifier, true);
|
var damage = (int)GetDamageToInflict(pos, victim, warhead, weapon, firepowerModifier, true);
|
||||||
victim.InflictDamage(firedBy, damage, warhead);
|
victim.InflictDamage(firedBy, damage, warhead);
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case DamageModel.PerCell:
|
case DamageModel.PerCell:
|
||||||
{
|
{
|
||||||
foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
|
foreach (var t in world.Map.FindTilesInCircle(targetTile, warhead.Size[0]))
|
||||||
|
{
|
||||||
foreach (var unit in world.ActorMap.GetUnitsAt(t))
|
foreach (var unit in world.ActorMap.GetUnitsAt(t))
|
||||||
{
|
{
|
||||||
var damage = (int)GetDamageToInflict(pos, unit, warhead, weapon, firepowerModifier, false);
|
var damage = (int)GetDamageToInflict(pos, unit, warhead, weapon, firepowerModifier, false);
|
||||||
unit.InflictDamage(firedBy, damage, warhead);
|
unit.InflictDamage(firedBy, damage, warhead);
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case DamageModel.HealthPercentage:
|
case DamageModel.HealthPercentage:
|
||||||
{
|
{
|
||||||
@@ -135,9 +139,11 @@ namespace OpenRA.Mods.RA
|
|||||||
var healthInfo = victim.Info.Traits.Get<HealthInfo>();
|
var healthInfo = victim.Info.Traits.Get<HealthInfo>();
|
||||||
damage = (float)(damage / 100 * healthInfo.HP);
|
damage = (float)(damage / 100 * healthInfo.HP);
|
||||||
}
|
}
|
||||||
|
|
||||||
victim.InflictDamage(firedBy, (int)damage, warhead);
|
victim.InflictDamage(firedBy, (int)damage, warhead);
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -324,13 +324,15 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
var searched = new List<CPos>();
|
var searched = new List<CPos>();
|
||||||
// Limit search to a radius of 10 tiles
|
// Limit search to a radius of 10 tiles
|
||||||
for (int r = minRange; r < maxRange; r++)
|
for (int r = minRange; r < maxRange; r++)
|
||||||
foreach (var tile in self.World.FindTilesInCircle(target, r).Except(searched))
|
{
|
||||||
|
foreach (var tile in self.World.Map.FindTilesInCircle(target, r).Except(searched))
|
||||||
{
|
{
|
||||||
if (CanEnterCell(tile))
|
if (CanEnterCell(tile))
|
||||||
return tile;
|
return tile;
|
||||||
|
|
||||||
searched.Add(tile);
|
searched.Add(tile);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Couldn't find a cell
|
// Couldn't find a cell
|
||||||
return target;
|
return target;
|
||||||
@@ -343,13 +345,15 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
|
|
||||||
var searched = new List<CPos>();
|
var searched = new List<CPos>();
|
||||||
for (int r = minRange; r < maxRange; r++)
|
for (int r = minRange; r < maxRange; r++)
|
||||||
foreach (var tile in self.World.FindTilesInCircle(target, r).Except(searched))
|
{
|
||||||
|
foreach (var tile in self.World.Map.FindTilesInCircle(target, r).Except(searched))
|
||||||
{
|
{
|
||||||
if (check(tile))
|
if (check(tile))
|
||||||
return tile;
|
return tile;
|
||||||
|
|
||||||
searched.Add(tile);
|
searched.Add(tile);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Couldn't find a cell
|
// Couldn't find a cell
|
||||||
return target;
|
return target;
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
|
|
||||||
// Select only the tiles that are within range from the requested SubCell
|
// Select only the tiles that are within range from the requested SubCell
|
||||||
// This assumes that the SubCell does not change during the path traversal
|
// This assumes that the SubCell does not change during the path traversal
|
||||||
var tilesInRange = world.FindTilesInCircle(targetCell, range.Range / 1024 + 1)
|
var tilesInRange = world.Map.FindTilesInCircle(targetCell, range.Range / 1024 + 1)
|
||||||
.Where(t => (t.CenterPosition - target).LengthSquared <= rangeSquared
|
.Where(t => (t.CenterPosition - target).LengthSquared <= rangeSquared
|
||||||
&& mi.CanEnterCell(self.World, self, t, null, true, true));
|
&& mi.CanEnterCell(self.World, self, t, null, true, true));
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace OpenRA.Mods.RA
|
|||||||
var total = (double)world.Map.Bounds.Width * world.Map.Bounds.Height;
|
var total = (double)world.Map.Bounds.Width * world.Map.Bounds.Height;
|
||||||
MapControl = world.Actors
|
MapControl = world.Actors
|
||||||
.Where(a => !a.IsDead() && a.IsInWorld && a.Owner == player && a.HasTrait<RevealsShroud>())
|
.Where(a => !a.IsDead() && a.IsInWorld && a.Owner == player && a.HasTrait<RevealsShroud>())
|
||||||
.SelectMany(a => world.FindTilesInCircle(a.Location, a.Trait<RevealsShroud>().Range.Clamp(WRange.Zero, WRange.FromCells(50)).Range / 1024))
|
.SelectMany(a => world.Map.FindTilesInCircle(a.Location, a.Trait<RevealsShroud>().Range.Clamp(WRange.Zero, WRange.FromCells(50)).Range / 1024))
|
||||||
.Distinct()
|
.Distinct()
|
||||||
.Count() / total;
|
.Count() / total;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ namespace OpenRA.Mods.RA
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Spawn support units in an annulus around the base actor
|
// Spawn support units in an annulus around the base actor
|
||||||
var supportSpawnCells = w.FindTilesInCircle(sp, unitGroup.OuterSupportRadius)
|
var supportSpawnCells = w.Map.FindTilesInCircle(sp, unitGroup.OuterSupportRadius)
|
||||||
.Except(w.FindTilesInCircle(sp, unitGroup.InnerSupportRadius));
|
.Except(w.Map.FindTilesInCircle(sp, unitGroup.InnerSupportRadius));
|
||||||
|
|
||||||
foreach (var s in unitGroup.SupportActors)
|
foreach (var s in unitGroup.SupportActors)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace OpenRA.Mods.RA
|
|||||||
public IEnumerable<Actor> UnitsInRange(CPos xy)
|
public IEnumerable<Actor> UnitsInRange(CPos xy)
|
||||||
{
|
{
|
||||||
var range = ((ChronoshiftPowerInfo)Info).Range;
|
var range = ((ChronoshiftPowerInfo)Info).Range;
|
||||||
var tiles = self.World.FindTilesInCircle(xy, range);
|
var tiles = self.World.Map.FindTilesInCircle(xy, range);
|
||||||
var units = new List<Actor>();
|
var units = new List<Actor>();
|
||||||
foreach (var t in tiles)
|
foreach (var t in tiles)
|
||||||
units.AddRange(self.World.ActorMap.GetUnitsAt(t));
|
units.AddRange(self.World.ActorMap.GetUnitsAt(t));
|
||||||
@@ -69,8 +69,8 @@ namespace OpenRA.Mods.RA
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
var range = ((ChronoshiftPowerInfo)Info).Range;
|
var range = ((ChronoshiftPowerInfo)Info).Range;
|
||||||
var sourceTiles = self.World.FindTilesInCircle(xy, range);
|
var sourceTiles = self.World.Map.FindTilesInCircle(xy, range);
|
||||||
var destTiles = self.World.FindTilesInCircle(sourceLocation, range);
|
var destTiles = self.World.Map.FindTilesInCircle(sourceLocation, range);
|
||||||
|
|
||||||
using (var se = sourceTiles.GetEnumerator())
|
using (var se = sourceTiles.GetEnumerator())
|
||||||
using (var de = destTiles.GetEnumerator())
|
using (var de = destTiles.GetEnumerator())
|
||||||
@@ -134,7 +134,7 @@ namespace OpenRA.Mods.RA
|
|||||||
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world)
|
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world)
|
||||||
{
|
{
|
||||||
var xy = wr.Position(wr.Viewport.ViewToWorldPx(Viewport.LastMousePos)).ToCPos();
|
var xy = wr.Position(wr.Viewport.ViewToWorldPx(Viewport.LastMousePos)).ToCPos();
|
||||||
var tiles = world.FindTilesInCircle(xy, range);
|
var tiles = world.Map.FindTilesInCircle(xy, range);
|
||||||
var pal = wr.Palette("terrain");
|
var pal = wr.Palette("terrain");
|
||||||
foreach (var t in tiles)
|
foreach (var t in tiles)
|
||||||
yield return new SpriteRenderable(tile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true);
|
yield return new SpriteRenderable(tile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true);
|
||||||
@@ -216,11 +216,11 @@ namespace OpenRA.Mods.RA
|
|||||||
var pal = wr.Palette("terrain");
|
var pal = wr.Palette("terrain");
|
||||||
|
|
||||||
// Source tiles
|
// Source tiles
|
||||||
foreach (var t in world.FindTilesInCircle(sourceLocation, range))
|
foreach (var t in world.Map.FindTilesInCircle(sourceLocation, range))
|
||||||
yield return new SpriteRenderable(sourceTile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true);
|
yield return new SpriteRenderable(sourceTile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true);
|
||||||
|
|
||||||
// Destination tiles
|
// Destination tiles
|
||||||
foreach (var t in world.FindTilesInCircle(xy, range))
|
foreach (var t in world.Map.FindTilesInCircle(xy, range))
|
||||||
yield return new SpriteRenderable(sourceTile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true);
|
yield return new SpriteRenderable(sourceTile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true);
|
||||||
|
|
||||||
// Unit previews
|
// Unit previews
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace OpenRA.Mods.RA
|
|||||||
public IEnumerable<Actor> UnitsInRange(CPos xy)
|
public IEnumerable<Actor> UnitsInRange(CPos xy)
|
||||||
{
|
{
|
||||||
int range = ((IronCurtainPowerInfo)Info).Range;
|
int range = ((IronCurtainPowerInfo)Info).Range;
|
||||||
var tiles = self.World.FindTilesInCircle(xy, range);
|
var tiles = self.World.Map.FindTilesInCircle(xy, range);
|
||||||
var units = new List<Actor>();
|
var units = new List<Actor>();
|
||||||
foreach (var t in tiles)
|
foreach (var t in tiles)
|
||||||
units.AddRange(self.World.ActorMap.GetUnitsAt(t));
|
units.AddRange(self.World.ActorMap.GetUnitsAt(t));
|
||||||
@@ -110,7 +110,7 @@ namespace OpenRA.Mods.RA
|
|||||||
{
|
{
|
||||||
var xy = wr.Position(wr.Viewport.ViewToWorldPx(Viewport.LastMousePos)).ToCPos();
|
var xy = wr.Position(wr.Viewport.ViewToWorldPx(Viewport.LastMousePos)).ToCPos();
|
||||||
var pal = wr.Palette("terrain");
|
var pal = wr.Palette("terrain");
|
||||||
foreach (var t in world.FindTilesInCircle(xy, range))
|
foreach (var t in world.Map.FindTilesInCircle(xy, range))
|
||||||
yield return new SpriteRenderable(tile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true);
|
yield return new SpriteRenderable(tile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user