public virtual bool HijackPlacementRequest(GridCoordinates coordinates) { return(false); }
/** * Adds a block * @param {[type]} string name [Name of block object (has type)] * @param {[type]} Vector3 last [The previous coords of this block] * @param {[type]} Vector3 coords [Coords of this block now] * @param {[type]} GridCoordinates obj [Grid coordinates obj tied to this block (for movement)] */ public void AddBlock(string name, Vector3 last, Vector3 coords, GridCoordinates obj) { Block.BlockType bt = Block.BlockType.WALL; if (name.Contains("grass") || name.Contains("start")) { bt = Block.BlockType.GRASS; } else if (name.Contains("magma")) { bt = Block.BlockType.LAVA; } else if (name.Contains("interactable") || name.Contains("poof")) { bt = Block.BlockType.MOVEABLE; } else if (name.Contains("winblock")) { bt = Block.BlockType.WIN; } else if (name.Contains("NPC")) { bt = Block.BlockType.NPC; } else if (name.Contains("GATE")) { bt = Block.BlockType.GATE; } else if (name.Contains("spinning") || name.Contains("arrow") || name.Contains("tut") || name.Contains("Bulk")) //for final && tut level { bt = Block.BlockType.NONE; } // else { // for debugginggz // Debug.Log("wall block name: " + name); // } Vector2Int xz; // Add new block object if (bt != Block.BlockType.NONE) { coords.x = (float)Math.Round(coords.x); coords.y = (float)Math.Round(coords.y); coords.z = (float)Math.Round(coords.z); Block block; block = new Block(bt, coords, obj); xz = new Vector2Int((int)coords.x, (int)coords.z); SortedList <int, Block> get; if (map.TryGetValue(xz, out get)) { get.Remove((int)coords.y); get.Add((int)coords.y, block); } else { get = new SortedList <int, Block>(); map.Add(xz, get); get.Add((int)coords.y, block); } // if(name.Contains("start")) { // Debug.Log(name + " " + block.getCoords() + " " + block.b_type); // Block get_b; // if(get.TryGetValue((int)coords.y, out get_b)) { // Debug.Log("get block in block block: " + get_b.getCoords()); // Debug.Log("get block in block block: " + get_b.b_type); // } // } } }
public abstract void PopupMessage(GridCoordinates coordinates, IEntity viewer, string message);
/// <summary> /// Throw an entity in the direction of <paramref name="targetLoc"/> from <paramref name="sourceLoc"/>. /// </summary> /// <param name="thrownEnt">The entity to throw.</param> /// <param name="throwForce"> /// The force to throw the entity with. /// Total impulse applied is equal to this force applied for one second. /// </param> /// <param name="targetLoc"> /// The target location to throw at. /// This is only used to calculate a direction, /// actual distance is purely determined by <paramref name="throwForce"/>. /// </param> /// <param name="sourceLoc"> /// The position to start the throw from. /// </param> /// <param name="spread"> /// If true, slightly spread the actual throw angle. /// </param> /// <param name="throwSourceEnt"> /// The entity that did the throwing. An opposite impulse will be applied to this entity if passed in. /// </param> public static void Throw(IEntity thrownEnt, float throwForce, GridCoordinates targetLoc, GridCoordinates sourceLoc, bool spread = false, IEntity throwSourceEnt = null) { if (!thrownEnt.TryGetComponent(out ICollidableComponent colComp)) { return; } var mapManager = IoCManager.Resolve <IMapManager>(); colComp.CanCollide = true; // I can now collide with player, so that i can do damage. if (!thrownEnt.TryGetComponent(out ThrownItemComponent projComp)) { projComp = thrownEnt.AddComponent <ThrownItemComponent>(); if (colComp.PhysicsShapes.Count == 0) { colComp.PhysicsShapes.Add(new PhysShapeAabb()); } colComp.PhysicsShapes[0].CollisionMask |= (int)CollisionGroup.ThrownItem; colComp.Status = BodyStatus.InAir; } var angle = new Angle(targetLoc.ToMapPos(mapManager) - sourceLoc.ToMapPos(mapManager)); if (spread) { var spreadRandom = IoCManager.Resolve <IRobustRandom>(); angle += Angle.FromDegrees(spreadRandom.NextGaussian(0, 3)); } if (throwSourceEnt != null) { projComp.User = throwSourceEnt; projComp.IgnoreEntity(throwSourceEnt); if (ActionBlockerSystem.CanChangeDirection(throwSourceEnt)) { throwSourceEnt.Transform.LocalRotation = angle.GetCardinalDir().ToAngle(); } } // scaling is handled elsewhere, this is just multiplying by 10 independent of timing as a fix until elsewhere values are updated var spd = throwForce * 10; projComp.StartThrow(angle.ToVec(), spd); if (throwSourceEnt != null && throwSourceEnt.TryGetComponent <IPhysicsComponent>(out var physics) && physics.TryGetController(out MoverController mover)) { var physicsMgr = IoCManager.Resolve <IPhysicsManager>(); if (physicsMgr.IsWeightless(throwSourceEnt.Transform.GridPosition)) { // We don't check for surrounding entities, // so you'll still get knocked around if you're hugging the station wall in zero g. // I got kinda lazy is the reason why. Also it makes a bit of sense. // If somebody wants they can come along and make it so magboots completely hold you still. // Would be a cool incentive to use them. const float ThrowFactor = 5.0f; // Break Newton's Third Law for better gameplay mover.Push(-angle.ToVec(), spd * ThrowFactor / physics.Mass); } } }
public abstract IEntity SpawnEntityAt(string entityType, GridCoordinates coordinates);
public async Task AllComponentsOneToOneDeleteTest() { var skipComponents = new[] { "DebugExceptionOnAdd", // Debug components that explicitly throw exceptions "DebugExceptionExposeData", "DebugExceptionInitialize", "DebugExceptionStartup", "Map", // We aren't testing a map entity in this test "MapGrid" }; var testEntity = @" - type: entity id: AllComponentsOneToOneDeleteTestEntity"; var server = StartServerDummyTicker(); await server.WaitIdleAsync(); var mapManager = server.ResolveDependency <IMapManager>(); var entityManager = server.ResolveDependency <IEntityManager>(); var mapLoader = server.ResolveDependency <IMapLoader>(); var pauseManager = server.ResolveDependency <IPauseManager>(); var componentFactory = server.ResolveDependency <IComponentFactory>(); var prototypeManager = server.ResolveDependency <IPrototypeManager>(); IMapGrid grid = default; server.Post(() => { // Load test entity using var reader = new StringReader(testEntity); prototypeManager.LoadFromStream(reader); // Load test map var mapId = mapManager.CreateMap(); pauseManager.AddUninitializedMap(mapId); grid = mapLoader.LoadBlueprint(mapId, "Maps/stationstation.yml"); pauseManager.DoMapInitialize(mapId); }); server.Assert(() => { var testLocation = new GridCoordinates(new Vector2(0, 0), grid); foreach (var type in componentFactory.AllRegisteredTypes) { var component = (Component)componentFactory.GetComponent(type); // If this component is ignored if (skipComponents.Contains(component.Name)) { continue; } var entity = entityManager.SpawnEntity("AllComponentsOneToOneDeleteTestEntity", testLocation); Assert.That(entity.Initialized); // The component may already exist if it is a mandatory component // such as MetaData or Transform if (entity.HasComponent(type)) { continue; } component.Owner = entity; Logger.LogS(LogLevel.Debug, "EntityTest", $"Adding component: {component.Name}"); Assert.DoesNotThrow(() => { entityManager.ComponentManager.AddComponent(entity, component); }, "Component '{0}' threw an exception.", component.Name); server.RunTicks(10); entityManager.DeleteEntity(entity.Uid); } }); await server.WaitIdleAsync(); }
protected override void FrameUpdate(FrameEventArgs args) { if (!VisibleInTree) { return; } var stringBuilder = new StringBuilder(); var mouseScreenPos = inputManager.MouseScreenPosition; var screenSize = _displayManager.ScreenSize; MapCoordinates mouseWorldMap; GridCoordinates mouseGridPos; TileRef tile; mouseWorldMap = eyeManager.ScreenToMap(mouseScreenPos); if (_mapManager.TryFindGridAt(mouseWorldMap, out var mouseGrid)) { mouseGridPos = mouseGrid.MapToGrid(mouseWorldMap); tile = mouseGrid.GetTileRef(mouseGridPos); } else { mouseGridPos = new GridCoordinates(mouseWorldMap.Position, GridId.Invalid); tile = default; } stringBuilder.AppendFormat(@"Positioning Debug: Screen Size: {0} Mouse Pos: Screen: {1} {2} {3} {4} GUI: {5}", screenSize, mouseScreenPos, mouseWorldMap, mouseGridPos, tile, UserInterfaceManager.CurrentlyHovered); stringBuilder.AppendLine("\nAttached Entity:"); if (playerManager.LocalPlayer?.ControlledEntity == null) { stringBuilder.AppendLine("No attached entity."); } else { var entityTransform = playerManager.LocalPlayer.ControlledEntity.Transform; var playerWorldOffset = entityTransform.MapPosition; var playerScreen = eyeManager.WorldToScreen(playerWorldOffset.Position); var playerGridPos = playerManager.LocalPlayer.ControlledEntity.Transform.GridPosition; stringBuilder.AppendFormat(@" Screen: {0} {1} {2} EntityUid: {3}", playerScreen, playerWorldOffset, playerGridPos, entityTransform.Owner.Uid); } contents.Text = stringBuilder.ToString(); MinimumSizeChanged(); }
private void PlaceNewTile(GridCoordinates coordinates, ushort tileType, MapId mapId, Vector2 position) { // tile can snap up to 0.75m away from grid var gridSearchBox = new Box2(-0.5f, -0.5f, 0.5f, 0.5f) .Scale(1.5f) .Translated(position); var gridsInArea = _mapManager.FindGridsIntersecting(mapId, gridSearchBox); IMapGrid closest = null; float distance = float.PositiveInfinity; Box2 intersect = new Box2(); foreach (var grid in gridsInArea) { // figure out closest intersect var gridIntersect = gridSearchBox.Intersect(grid.WorldBounds); var gridDist = (gridIntersect.Center - position).LengthSquared; if (gridDist >= distance) { continue; } distance = gridDist; closest = grid; intersect = gridIntersect; } if (closest != null) // stick to existing grid { // round to nearest cardinal dir var normal = new Angle(position - intersect.Center).GetCardinalDir().ToVec(); // round coords to center of tile var tileIndices = closest.WorldToTile(intersect.Center); var tileCenterLocal = closest.GridTileToLocal(tileIndices); var tileCenterWorld = tileCenterLocal.ToWorld(_mapManager).Position; // move mouse one tile out along normal var newTilePos = tileCenterWorld + normal * closest.TileSize; // you can always remove a tile if (Tile.Empty.TypeId != tileType) { var tileBounds = Box2.UnitCentered.Scale(closest.TileSize).Translated(newTilePos); var collideCount = _mapManager.FindGridsIntersecting(mapId, tileBounds).Count(); // prevent placing a tile if it overlaps more than one grid if (collideCount > 1) { return; } } var pos = closest.WorldToTile(position); closest.SetTile(pos, new Tile(tileType)); } else // create a new grid { var newGrid = _mapManager.CreateGrid(mapId); newGrid.WorldPosition = position + (newGrid.TileSize / 2f); // assume bottom left tile origin var tilePos = newGrid.WorldToTile(position); newGrid.SetTile(tilePos, new Tile(tileType)); } }
public static void SpawnExplosion(GridCoordinates coords, int devastationRange, int heavyImpactRange, int lightImpactRange, int flashRange) { var tileDefinitionManager = IoCManager.Resolve <ITileDefinitionManager>(); var serverEntityManager = IoCManager.Resolve <IServerEntityManager>(); var entitySystemManager = IoCManager.Resolve <IEntitySystemManager>(); var mapManager = IoCManager.Resolve <IMapManager>(); var robustRandom = IoCManager.Resolve <IRobustRandom>(); var maxRange = MathHelper.Max(devastationRange, heavyImpactRange, lightImpactRange, 0f); //Entity damage calculation var entitiesAll = serverEntityManager.GetEntitiesInRange(coords, maxRange).ToList(); foreach (var entity in entitiesAll) { if (entity.Deleted) { continue; } if (!entity.Transform.IsMapTransform) { continue; } var distanceFromEntity = (int)entity.Transform.GridPosition.Distance(mapManager, coords); var exAct = entitySystemManager.GetEntitySystem <ActSystem>(); var severity = ExplosionSeverity.Destruction; if (distanceFromEntity < devastationRange) { severity = ExplosionSeverity.Destruction; } else if (distanceFromEntity < heavyImpactRange) { severity = ExplosionSeverity.Heavy; } else if (distanceFromEntity < lightImpactRange) { severity = ExplosionSeverity.Light; } else { continue; } //exAct.HandleExplosion(Owner, entity, severity); exAct.HandleExplosion(null, entity, severity); } //Tile damage calculation mockup //TODO: make it into some sort of actual damage component or whatever the boys think is appropriate var mapGrid = mapManager.GetGrid(coords.GridID); var circle = new Circle(coords.Position, maxRange); var tiles = mapGrid.GetTilesIntersecting(circle); foreach (var tile in tiles) { var tileLoc = mapGrid.GridTileToLocal(tile.GridIndices); var tileDef = (ContentTileDefinition)tileDefinitionManager[tile.Tile.TypeId]; var distanceFromTile = (int)tileLoc.Distance(mapManager, coords); if (!string.IsNullOrWhiteSpace(tileDef.SubFloor)) { if (distanceFromTile < devastationRange) { mapGrid.SetTile(tileLoc, new Tile(tileDefinitionManager["space"].TileId)); } if (distanceFromTile < heavyImpactRange) { if (robustRandom.Prob(80)) { mapGrid.SetTile(tileLoc, new Tile(tileDefinitionManager[tileDef.SubFloor].TileId)); } else { mapGrid.SetTile(tileLoc, new Tile(tileDefinitionManager["space"].TileId)); } } if (distanceFromTile < lightImpactRange) { if (robustRandom.Prob(50)) { mapGrid.SetTile(tileLoc, new Tile(tileDefinitionManager[tileDef.SubFloor].TileId)); } } } } //Effects and sounds var time = IoCManager.Resolve <IGameTiming>().CurTime; var message = new EffectSystemMessage { EffectSprite = "Effects/explosion.rsi", RsiState = "explosionfast", Born = time, DeathTime = time + TimeSpan.FromSeconds(5), Size = new Vector2(flashRange / 2, flashRange / 2), Coordinates = coords, //Rotated from east facing Rotation = 0f, ColorDelta = new Vector4(0, 0, 0, -1500f), Color = Vector4.Multiply(new Vector4(255, 255, 255, 750), 0.5f), Shaded = false }; entitySystemManager.GetEntitySystem <EffectSystem>().CreateParticle(message); entitySystemManager.GetEntitySystem <AudioSystem>().Play("/Audio/effects/explosion.ogg", coords); // Knock back cameras of all players in the area. var playerManager = IoCManager.Resolve <IPlayerManager>(); foreach (var player in playerManager.GetAllPlayers()) { if (player.AttachedEntity == null || player.AttachedEntity.Transform.MapID != mapGrid.ParentMapId || !player.AttachedEntity.TryGetComponent(out CameraRecoilComponent recoil)) { continue; } var playerPos = player.AttachedEntity.Transform.WorldPosition; var delta = coords.ToMapPos(mapManager) - playerPos; var distance = delta.LengthSquared; var effect = 1 / (1 + 0.2f * distance); if (effect > 0.01f) { var kick = -delta.Normalized * effect; recoil.Kick(kick); } } }
public override IEntity TakeProjectile(GridCoordinates spawnAtGrid, MapCoordinates spawnAtMap) { var powerCellEntity = _powerCellContainer.ContainedEntity; if (powerCellEntity == null) { return(null); } var capacitor = powerCellEntity.GetComponent <BatteryComponent>(); if (capacitor.CurrentCharge < _lowerChargeLimit) { return(null); } // Can fire confirmed // Multiply the entity's damage / whatever by the percentage of charge the shot has. IEntity entity; var chargeChange = Math.Min(capacitor.CurrentCharge, _baseFireCost); capacitor.UseCharge(chargeChange); var energyRatio = chargeChange / _baseFireCost; if (_ammoContainer.ContainedEntity != null) { entity = _ammoContainer.ContainedEntity; _ammoContainer.Remove(entity); } else { entity = Owner.Transform.GridID != GridId.Invalid ? Owner.EntityManager.SpawnEntity(_ammoPrototype, Owner.Transform.GridPosition) : Owner.EntityManager.SpawnEntity(_ammoPrototype, Owner.Transform.MapPosition); } if (entity.TryGetComponent(out ProjectileComponent projectileComponent)) { if (energyRatio < 1.0) { var newDamages = new Dictionary <DamageType, int>(projectileComponent.Damages.Count); foreach (var(damageType, damage) in projectileComponent.Damages) { newDamages.Add(damageType, (int)(damage * energyRatio)); } projectileComponent.Damages = newDamages; } } else if (entity.TryGetComponent(out HitscanComponent hitscanComponent)) { hitscanComponent.Damage *= energyRatio; hitscanComponent.ColorModifier = energyRatio; } else { throw new InvalidOperationException("Ammo doesn't have hitscan or projectile?"); } Dirty(); UpdateAppearance(); return(entity); }
/// <summary> /// Play an audio file at a static position. /// </summary> /// <param name="filename">The resource path to the OGG Vorbis file to play.</param> /// <param name="coordinates">The coordinates at which to play the audio.</param> /// <param name="audioParams"></param> public void Play(string filename, GridCoordinates coordinates, AudioParams?audioParams = null) { Play(resourceCache.GetResource <AudioResource>(new ResourcePath(filename)), coordinates, audioParams); }
/// <inheritdoc /> public IEnumerable <IEntity> GetEntitiesInRange(GridCoordinates position, float range) { var aabb = new Box2(position.Position - new Vector2(range / 2, range / 2), position.Position + new Vector2(range / 2, range / 2)); return(GetEntitiesIntersecting(_mapManager.GetGrid(position.GridID).ParentMapId, aabb)); }
/// <inheritdoc /> public IEnumerable <IEntity> GetEntitiesIntersecting(GridCoordinates position) { var mapPos = position.ToMap(_mapManager); return(GetEntitiesIntersecting(mapPos.MapId, mapPos.Position)); }
/// <summary> /// /// </summary> /// <param name="curPath"></param> /// <param name="curLeftBound"></param> /// <param name="curRightBound"></param> private void InitialiseGridWindows(LinePath curPath, IList<LinePath> curLeftBounds, IList<LinePath> curRightBounds) { StartWatch(); // start stopwatch // find min and max limits of path and lane bounds double minX = double.MaxValue; double minY = double.MaxValue; double maxX = double.MinValue; double maxY = double.MinValue; FindMinMax(curPath, ref minX, ref maxX, ref minY, ref maxY); foreach (LinePath curLeftBound in curLeftBounds) { FindMinMax(curLeftBound, ref minX, ref maxX, ref minY, ref maxY); } foreach (LinePath curRightBound in curRightBounds) { FindMinMax(curRightBound, ref minX, ref maxX, ref minY, ref maxY); } // create tight window gridWindowLowerX = (int)Math.Round(minX / gridStep) + gridMiddleX; gridWindowLowerY = (int)Math.Round(minY / gridStep) + gridMiddleY; gridWindowUpperX = (int)Math.Round(maxX / gridStep) + gridMiddleX; gridWindowUpperY = (int)Math.Round(maxY / gridStep) + gridMiddleY; // expand window int offset = (int)Math.Round(maxCost); gridWindowLowerX = Math.Max(gridWindowLowerX - offset, 0); gridWindowLowerY = Math.Max(gridWindowLowerY - offset, 0); gridWindowUpperX = Math.Min(gridWindowUpperX + offset, gridSizeX - 1); gridWindowUpperY = Math.Min(gridWindowUpperY + offset, gridSizeY - 1); // set up grid windows bool windowEnabled = true; GridCoordinates windowLowerLeft = new GridCoordinates(gridWindowLowerX, gridWindowLowerY); GridCoordinates windowUpperRight = new GridCoordinates(gridWindowUpperX, gridWindowUpperY); gridPath.SetWindow(windowLowerLeft, windowUpperRight, windowEnabled); gridPathScale.SetWindow(windowLowerLeft, windowUpperRight, windowEnabled); gridObstacle.SetWindow(windowLowerLeft, windowUpperRight, windowEnabled); gridObstacleID.SetWindow(windowLowerLeft, windowUpperRight, windowEnabled); gridLaneBound.SetWindow(windowLowerLeft, windowUpperRight, windowEnabled); gridCost.SetWindow(windowLowerLeft, windowUpperRight, windowEnabled); gridSearchPath.SetWindow(windowLowerLeft, windowUpperRight, windowEnabled); gridPath.ZeroGrid(true); gridPathScale.ZeroGrid(true); gridObstacle.ZeroGrid(true); gridObstacleID.ZeroGrid(true); gridLaneBound.ZeroGrid(true); gridCost.ZeroGrid(true); gridSearchPath.ZeroGrid(true); // display time taken to process grid windows gridWindowTime = StopWatch("ObstacleManager - GridWindows - "); }
public bool InRange(GridCoordinates from, GridCoordinates to) { return(from.InRange(_mapManager, to, 15)); }
/// <summary> /// Updates grid path and grid path scale with path information /// </summary> /// <param name="basePath">Base path points</param> private void UpdateGridPath(LinePath basePath, bool reverse, bool sparse) { StartWatch(); // start stopwatch // generate no-go regions near vehicle // no-go area in opposite direction of vehicle motion List<GridCoordinates> setLocs; if (reverse) { gridPath.SetLineValues(new GridCoordinates(gridMiddleX + 1, 0), new GridCoordinates(gridMiddleX + 1, gridSizeY - 1), maxCost, out setLocs); gridPath.FloodFill(new GridCoordinates(gridMiddleX + 2, gridMiddleY), maxCost, 0); } else { gridPath.SetLineValues(new GridCoordinates(gridMiddleX - 1, 0), new GridCoordinates(gridMiddleX - 1, gridSizeY - 1), maxCost, out setLocs); gridPath.FloodFill(new GridCoordinates(gridMiddleX - 2, gridMiddleY), maxCost, 0); } // radius for no-go circle regions float circleRadius = 7; // radius of circles beside rear axle, in meters int circleGridRadius = (int)Math.Round(circleRadius / gridStep); // generate no-go circle region to the left List<GridCoordinates> leftCircleLocs; GridCoordinates leftCircleCenterLoc = new GridCoordinates(gridMiddleX, gridMiddleY + circleGridRadius + 1); gridPath.BresenhamCircle(leftCircleCenterLoc, circleGridRadius, out leftCircleLocs); //gridPath.SetValues(leftCircleLocs, maxCost); //gridPath.FloodFill(leftCircleCenterLoc, maxCost, 0); gridPath.FillConvexInterior(leftCircleLocs, maxCost); // generate no-go circle region to the right List<GridCoordinates> rightCircleLocs; GridCoordinates rightCircleCenterLoc = new GridCoordinates(gridMiddleX, gridMiddleY - circleGridRadius - 1); gridPath.BresenhamCircle(rightCircleCenterLoc, circleGridRadius, out rightCircleLocs); //gridPath.SetValues(rightCircleLocs, maxCost); //gridPath.FloodFill(rightCircleCenterLoc, maxCost, 0); gridPath.FillConvexInterior(rightCircleLocs, maxCost); float gridStartValue = 1; List<GridCoordinates> gridExtendLocs; // find grid base path points FindPoints(basePath, out gridBasePath); gridPath.SetValues(gridBasePath, gridStartValue); gridPathScale.SetValues(gridBasePath, gridStartValue); // extend start of base path to grid border, if necessary ExtendPoints(basePath[1], basePath[0], out gridExtendLocs); //gridPath.SetValues(gridExtendLocs, gridStartValue); gridPathScale.SetValues(gridExtendLocs, gridStartValue); // extend end of base path to grid border, if necessary int lastIndex = basePath.Count - 1; ExtendPoints(basePath[lastIndex - 1], basePath[lastIndex], out gridExtendLocs); gridPath.SetValues(gridExtendLocs, gridStartValue); gridPathScale.SetValues(gridExtendLocs, gridStartValue); // generate grid path using wavefront propagation gridPath.WaveFront(gridStartValue, 0, sparse ? 0.05f : 0.5f, maxCost); // display time taken to process grid path gridPathTime = StopWatch("ObstacleManager - GridPath - "); StartWatch(); // start stopwatch // grid path scale values float leftScaleValue = gridStartValue; // scale value for region left of path float rightScaleValue = 0.75f; // scale value for region right of path // set up left region for grid path scale using floodfill int offsetX = gridBasePath[1].X - gridBasePath[0].X; int offsetY = gridBasePath[1].Y - gridBasePath[0].Y; GridCoordinates leftStartLoc = new GridCoordinates(gridBasePath[0].X - offsetY, gridBasePath[0].Y + offsetX); gridPathScale.FloodFill(leftStartLoc, leftScaleValue, 0); // set up right region for grid path scale by replacing remaining empty grid locations gridPathScale.Replace(0, rightScaleValue); // display time taken to process grid path scale gridPathScaleTime = StopWatch("ObstacleManager - GridPathScale - "); // write grid data to file (for debugging) if (writeToFileFlag == true) { // write grid path data to file StartWatch(); gridPath.WriteGridToFile("GridPath.txt"); StopWatch("ObstacleManager - GridPath File Write - "); // write grid path scale data to file StartWatch(); gridPathScale.WriteGridToFile("GridPathScale.txt"); StopWatch("ObstacleManager - GridPathScale File Write - "); } }
public bool TryPoint(ICommonSession?session, GridCoordinates coords, EntityUid uid) { var player = (session as IPlayerSession)?.ContentData()?.Mind?.CurrentEntity; if (player == null) { return(false); } if (_pointers.TryGetValue(session !, out var lastTime) && _gameTiming.CurTime < lastTime + PointDelay) { return(false); } if (EntityManager.TryGetEntity(uid, out var entity) && entity.HasComponent <PointingArrowComponent>()) { // this is a pointing arrow. no pointing here... return(false); } if (!InRange(coords, player.Transform.GridPosition)) { player.PopupMessage(Loc.GetString("You can't reach there!")); return(false); } if (ActionBlockerSystem.CanChangeDirection(player)) { var diff = coords.ToMapPos(_mapManager) - player.Transform.MapPosition.Position; if (diff.LengthSquared > 0.01f) { player.Transform.LocalRotation = new Angle(diff); } } var arrow = EntityManager.SpawnEntity("pointingarrow", coords); var layer = (int)VisibilityFlags.Normal; if (player.TryGetComponent(out VisibilityComponent? playerVisibility)) { var arrowVisibility = arrow.EnsureComponent <VisibilityComponent>(); layer = arrowVisibility.Layer = playerVisibility.Layer; } // Get players that are in range and whose visibility layer matches the arrow's. var viewers = _playerManager.GetPlayersBy((playerSession) => { if ((playerSession.VisibilityMask & layer) == 0) { return(false); } var ent = playerSession.ContentData()?.Mind?.CurrentEntity; return(ent != null && ent.Transform.MapPosition.InRange(player.Transform.MapPosition, PointingRange)); }); string selfMessage; string viewerMessage; string?viewerPointedAtMessage = null; if (EntityManager.TryGetEntity(uid, out var pointed)) { selfMessage = player == pointed ? Loc.GetString("You point at yourself.") : Loc.GetString("You point at {0:theName}.", pointed); viewerMessage = player == pointed ? $"{player.Name} {Loc.GetString("points at {0:themself}.", player)}" : $"{player.Name} {Loc.GetString("points at {0:theName}.", pointed)}"; viewerPointedAtMessage = $"{player.Name} {Loc.GetString("points at you.")}"; } else { var tileRef = _mapManager.GetGrid(coords.GridID).GetTileRef(coords); var tileDef = _tileDefinitionManager[tileRef.Tile.TypeId]; selfMessage = Loc.GetString("You point at {0}.", tileDef.DisplayName); viewerMessage = $"{player.Name} {Loc.GetString("points at {0}.", tileDef.DisplayName)}"; } _pointers[session !] = _gameTiming.CurTime;
public abstract IEntity SpawnEntityNoMapInit(string protoName, GridCoordinates coordinates);
public static void Write(this NetOutgoingMessage message, GridCoordinates coordinates) { message.Write(coordinates.GridID.Value); message.Write(coordinates.Position); }
public IList <IEntity> GetEntitiesUnderPosition(GridCoordinates coordinates) { return(GetEntitiesUnderPosition(coordinates.ToMap(_mapManager))); }
void TryStartStructureConstruction(GridCoordinates loc, string prototypeName, Angle angle, int ack) { var protoMan = IoCManager.Resolve <IPrototypeManager>(); var prototype = protoMan.Index <ConstructionPrototype>(prototypeName); var transform = Owner.GetComponent <ITransformComponent>(); if (!loc.InRange(transform.GridPosition, InteractionSystem.INTERACTION_RANGE)) { return; } if (prototype.Stages.Count < 2) { throw new InvalidOperationException($"Prototype '{prototypeName}' does not have enough stages."); } var stage0 = prototype.Stages[0]; if (!(stage0.Forward is ConstructionStepMaterial matStep)) { throw new NotImplementedException(); } // Try to find the stack with the material in the user's hand. var hands = Owner.GetComponent <HandsComponent>(); var activeHand = hands.GetActiveHand?.Owner; if (activeHand == null) { return; } if (!activeHand.TryGetComponent(out StackComponent stack) || !ConstructionComponent.MaterialStackValidFor(matStep, stack)) { return; } if (!stack.Use(matStep.Amount)) { return; } // OK WE'RE GOOD CONSTRUCTION STARTED. var entMgr = IoCManager.Resolve <IServerEntityManager>(); IoCManager.Resolve <IEntitySystemManager>().GetEntitySystem <AudioSystem>().Play("/Audio/items/deconstruct.ogg", loc); if (prototype.Stages.Count == 2) { // Exactly 2 stages, so don't make an intermediate frame. var ent = entMgr.ForceSpawnEntityAt(prototype.Result, loc); ent.GetComponent <ITransformComponent>().LocalRotation = angle; } else { var frame = entMgr.ForceSpawnEntityAt("structureconstructionframe", loc); var construction = frame.GetComponent <ConstructionComponent>(); construction.Init(prototype); frame.GetComponent <ITransformComponent>().LocalRotation = angle; } var msg = new AckStructureConstructionMessage(ack); SendNetworkMessage(msg); }
public async Task AllComponentsOneEntityDeleteTest() { var skipComponents = new[] { "DebugExceptionOnAdd", // Debug components that explicitly throw exceptions "DebugExceptionExposeData", "DebugExceptionInitialize", "DebugExceptionStartup", "Map", // We aren't testing a map entity in this test "MapGrid" }; var testEntity = @" - type: entity id: AllComponentsOneEntityDeleteTestEntity"; var server = StartServerDummyTicker(); await server.WaitIdleAsync(); var mapManager = server.ResolveDependency <IMapManager>(); var entityManager = server.ResolveDependency <IEntityManager>(); var mapLoader = server.ResolveDependency <IMapLoader>(); var pauseManager = server.ResolveDependency <IPauseManager>(); var componentFactory = server.ResolveDependency <IComponentFactory>(); var prototypeManager = server.ResolveDependency <IPrototypeManager>(); IMapGrid grid = default; server.Post(() => { // Load test entity using var reader = new StringReader(testEntity); prototypeManager.LoadFromStream(reader); // Load test map var mapId = mapManager.CreateMap(); pauseManager.AddUninitializedMap(mapId); grid = mapLoader.LoadBlueprint(mapId, "Maps/stationstation.yml"); pauseManager.DoMapInitialize(mapId); }); var distinctComponents = new List <(List <Type> components, List <Type> references)> { (new List <Type>(), new List <Type>()) }; // Split components into groups, ensuring that their references don't conflict foreach (var type in componentFactory.AllRegisteredTypes) { var registration = componentFactory.GetRegistration(type); for (var i = 0; i < distinctComponents.Count; i++) { var distinct = distinctComponents[i]; if (distinct.references.Intersect(registration.References).Any()) { // Ensure the next list if this one has conflicting references if (i + 1 >= distinctComponents.Count) { distinctComponents.Add((new List <Type>(), new List <Type>())); } continue; } // Add the component and its references if no conflicting references were found distinct.components.Add(type); distinct.references.AddRange(registration.References); } } // Sanity check Assert.That(distinctComponents, Is.Not.Empty); server.Assert(() => { foreach (var distinct in distinctComponents) { var testLocation = new GridCoordinates(new Vector2(0, 0), grid); var entity = entityManager.SpawnEntity("AllComponentsOneEntityDeleteTestEntity", testLocation); Assert.That(entity.Initialized); foreach (var type in distinct.components) { var component = (Component)componentFactory.GetComponent(type); // If the entity already has this component, if it was ensured or added by another if (entity.HasComponent(component.GetType())) { continue; } // If this component is ignored if (skipComponents.Contains(component.Name)) { continue; } component.Owner = entity; Logger.LogS(LogLevel.Debug, "EntityTest", $"Adding component: {component.Name}"); Assert.DoesNotThrow(() => { entityManager.ComponentManager.AddComponent(entity, component); }, "Component '{0}' threw an exception.", component.Name); } server.RunTicks(48); // Run one full second on the server entityManager.DeleteEntity(entity.Uid); } }); await server.WaitIdleAsync(); }
void TryStartStructureConstruction(GridCoordinates loc, string prototypeName, Angle angle, int ack) { var prototype = _prototypeManager.Index <ConstructionPrototype>(prototypeName); if (!InteractionChecks.InRangeUnobstructed(Owner, loc.ToMapPos(_mapManager), ignoredEnt: Owner, insideBlockerValid: prototype.CanBuildInImpassable)) { return; } if (prototype.Stages.Count < 2) { throw new InvalidOperationException($"Prototype '{prototypeName}' does not have enough stages."); } var stage0 = prototype.Stages[0]; if (!(stage0.Forward is ConstructionStepMaterial matStep)) { throw new NotImplementedException(); } // Try to find the stack with the material in the user's hand. var hands = Owner.GetComponent <HandsComponent>(); var activeHand = hands.GetActiveHand?.Owner; if (activeHand == null) { return; } if (!activeHand.TryGetComponent(out StackComponent stack) || !ConstructionComponent.MaterialStackValidFor(matStep, stack)) { return; } if (!stack.Use(matStep.Amount)) { return; } // OK WE'RE GOOD CONSTRUCTION STARTED. _entitySystemManager.GetEntitySystem <AudioSystem>().Play("/Audio/items/deconstruct.ogg", loc); if (prototype.Stages.Count == 2) { // Exactly 2 stages, so don't make an intermediate frame. var ent = _serverEntityManager.SpawnEntity(prototype.Result, loc); ent.Transform.LocalRotation = angle; } else { var frame = _serverEntityManager.SpawnEntity("structureconstructionframe", loc); var construction = frame.GetComponent <ConstructionComponent>(); construction.Init(prototype); frame.Transform.LocalRotation = angle; } var msg = new AckStructureConstructionMessage(ack); SendNetworkMessage(msg); }
public override void ReadFromBuffer(NetIncomingMessage buffer) { Message = buffer.ReadString(); Coordinates = buffer.ReadGridLocalCoordinates(); }
public override IEntity SpawnEntityAt(string entityType, GridCoordinates coordinates) { throw new NotImplementedException(); }
public override bool IsValidPosition(GridCoordinates position) { if (pManager.CurrentPermission !.IsTile) { return(false); }
public void Update(float frameTime) { Age += TimeSpan.FromSeconds(frameTime); if (Age >= Deathtime) { return; } Velocity += Acceleration * frameTime; RadialVelocity += RadialAcceleration * frameTime; TangentialVelocity += TangentialAcceleration * frameTime; var deltaPosition = new Vector2(0f, 0f); //If we have an emitter we can do special effects around that emitter position if (_mapManager.GridExists(EmitterCoordinates.GridID)) { //Calculate delta p due to radial velocity var positionRelativeToEmitter = Coordinates.ToWorld(_mapManager).Position - EmitterCoordinates.ToWorld(_mapManager).Position; var deltaRadial = RadialVelocity * frameTime; deltaPosition = positionRelativeToEmitter * (deltaRadial / positionRelativeToEmitter.Length); //Calculate delta p due to tangential velocity var radius = positionRelativeToEmitter.Length; if (radius > 0) { var theta = (float)Math.Atan2(positionRelativeToEmitter.Y, positionRelativeToEmitter.X); theta += TangentialVelocity * frameTime; deltaPosition += new Vector2(radius * (float)Math.Cos(theta), radius * (float)Math.Sin(theta)) - positionRelativeToEmitter; } } //Calculate new position from our velocity as well as possible rotation/movement around emitter deltaPosition += Velocity * frameTime; Coordinates = new GridCoordinates(Coordinates.Position + deltaPosition, Coordinates.GridID); //Finish calculating new rotation, size, color Rotation += RotationRate * frameTime; Size += SizeDelta * frameTime; Color += ColorDelta * frameTime; if (RsiState == null) { return; } // Calculate RSI animations. var delayCount = RsiState.DelayCount; if (delayCount > 0 && (AnimationLoops || AnimationIndex < delayCount - 1)) { AnimationTime += frameTime; while (RsiState.GetDelay(AnimationIndex) < AnimationTime) { var delay = RsiState.GetDelay(AnimationIndex); AnimationIndex += 1; AnimationTime -= delay; if (AnimationIndex == delayCount) { if (AnimationLoops) { AnimationIndex = 0; } else { break; } } EffectSprite = RsiState.GetFrame(RSI.State.Direction.South, AnimationIndex); } } }
public virtual bool HijackDeletion(GridCoordinates coordinates) { return(false); }
public IEntity GetEntityUnderPosition(GridCoordinates coordinates) { var entitiesUnderPosition = GetEntitiesUnderPosition(coordinates); return(entitiesUnderPosition.Count > 0 ? entitiesUnderPosition[0] : null); }
/// <summary> /// Check if grid location is within grid /// </summary> /// <param name="gridLoc">Grid location to check</param> /// <returns></returns> public Boolean InGrid(GridCoordinates gridLoc) { if (gridLoc.X >= 0 && gridLoc.X < gridSizeX && gridLoc.Y >= 0 && gridLoc.Y < gridSizeY) return true; else return false; }
/// <summary> /// Verifies the location of placement is a valid position to place at /// </summary> /// <param name="mouseScreen"></param> /// <returns></returns> public abstract bool IsValidPosition(GridCoordinates position);
/// <summary> /// Update grid lane bound /// </summary> /// <param name="leftBoundPoints">Lane left bound points</param> /// <param name="rightBoundPoints">Lane right bound points</param> private void UpdateGridLaneBound(IList<LinePath> leftBounds, IList<LinePath> rightBounds) { StartWatch(); // start stopwatch Coordinates extPoint = new Coordinates(); List<GridCoordinates> gridExtendLocs; foreach (LinePath leftBoundPoints in leftBounds) { // check if there is at least 2 left bound points if (leftBoundPoints.Count > 1) { // find grid lane bound left points FindPoints(leftBoundPoints, out gridLaneBoundLeft); gridLaneBound.SetValues(gridLaneBoundLeft, maxCost); // check if there are grid lane bound left points if (gridLaneBoundLeft.Count != 0) { // extend start of grid left lane bound to grid border extPoint = leftBoundPoints[0] - leftBoundPoints[1]; extPoint = leftBoundPoints[0] + extPoint.RotateM90(); ExtendPoints(leftBoundPoints[0], extPoint, out gridExtendLocs); gridLaneBound.SetValues(gridExtendLocs, maxCost); // extend end of grid left lane bound to grid border int lastIndex = leftBoundPoints.Count - 1; extPoint = leftBoundPoints[lastIndex] - leftBoundPoints[lastIndex - 1]; extPoint = leftBoundPoints[lastIndex] + extPoint.Rotate90().Normalize(); ExtendPoints(leftBoundPoints[lastIndex], extPoint, out gridExtendLocs); gridLaneBound.SetValues(gridExtendLocs, maxCost); // floodfill lane bound area List<Coordinates> partialLaneBoundPoints = new List<Coordinates>(); partialLaneBoundPoints.Add(leftBoundPoints[lastIndex]); partialLaneBoundPoints.Add(leftBoundPoints[lastIndex - 1]); partialLaneBoundPoints.Add(extPoint); Polygon partialLaneBoundArea = new Polygon(partialLaneBoundPoints); Coordinates partialLaneBoundAreaCenter = partialLaneBoundArea.Center; GridCoordinates partialGridLaneBoundAreaCenter = new GridCoordinates( (int)Math.Round(partialLaneBoundAreaCenter.X / gridStep) + gridMiddleX, (int)Math.Round(partialLaneBoundAreaCenter.Y / gridStep) + gridMiddleY); gridLaneBound.FloodFill(partialGridLaneBoundAreaCenter, maxCost, 0); } } } foreach (LinePath rightBoundPoints in rightBounds) { // check if there is at least 2 right bound points if (rightBoundPoints.Count > 1) { // find grid lane bound right points FindPoints(rightBoundPoints, out gridLaneBoundRight); gridLaneBound.SetValues(gridLaneBoundRight, maxCost); // check if there are grid lane bound right points if (gridLaneBoundRight.Count != 0) { // extend start of grid right lane bound to grid border extPoint = rightBoundPoints[0] - rightBoundPoints[1]; extPoint = rightBoundPoints[0] + extPoint.Rotate90(); ExtendPoints(rightBoundPoints[0], extPoint, out gridExtendLocs); gridLaneBound.SetValues(gridExtendLocs, maxCost); // extend end of grid right lane bound to grid border int lastIndex = rightBoundPoints.Count - 1; extPoint = rightBoundPoints[lastIndex] - rightBoundPoints[lastIndex - 1]; extPoint = rightBoundPoints[lastIndex] + extPoint.RotateM90().Normalize(); ExtendPoints(rightBoundPoints[lastIndex], extPoint, out gridExtendLocs); gridLaneBound.SetValues(gridExtendLocs, maxCost); // floodfill lane bound area List<Coordinates> partialLaneBoundPoints = new List<Coordinates>(); partialLaneBoundPoints.Add(rightBoundPoints[lastIndex]); partialLaneBoundPoints.Add(rightBoundPoints[lastIndex - 1]); partialLaneBoundPoints.Add(extPoint); Polygon partialLaneBoundArea = new Polygon(partialLaneBoundPoints); Coordinates partialLaneBoundAreaCenter = partialLaneBoundArea.Center; GridCoordinates partialGridLaneBoundAreaCenter = new GridCoordinates( (int)Math.Round(partialLaneBoundAreaCenter.X / gridStep) + gridMiddleX, (int)Math.Round(partialLaneBoundAreaCenter.Y / gridStep) + gridMiddleY); gridLaneBound.FloodFill(partialGridLaneBoundAreaCenter, maxCost, 0); } } } // generate grid lane bound using wavefront propagation float sepDist = 1; // in m float step = maxCost * gridStep / sepDist; //gridLaneBound.WaveFront(maxCost, 0, -step); // display time to process grid lane bound gridLaneBoundTime = StopWatch("ObstacleManager - GridLaneBound - "); // write grid data to file (for debugging) if (writeToFileFlag == true) { StartWatch(); gridLaneBound.WriteGridToFile("GridLaneBound.txt"); StopWatch("ObstacleManager - GridLaneBound File Write - "); } }
public abstract IEntity CreateEntityUninitialized(string prototypeName, GridCoordinates coordinates);
/// <summary> /// Update grid search path /// </summary> /// <param name="obstaclePath">Path that avoids obstacles</param> private void UpdateGridSearchPath(LinePath obstaclePath) { StartWatch(); // start stopwatch float gridStartValue = 1; float gridExtValue = -1; List<GridCoordinates> gridExtendLocs; // retrieve A star search path List<GridCoordinates> searchPath; gridCost.GetPath(out searchPath); // extend start of path to grid border, if necessary ExtendPoints(obstaclePath[1], obstaclePath[0], out gridExtendLocs); gridSearchPath.SetValues(gridExtendLocs, gridExtValue); // extend end of path to grid border, if necessary int lastIndex = obstaclePath.Count - 1; ExtendPoints(obstaclePath[lastIndex - 1], obstaclePath[lastIndex], out gridExtendLocs); gridSearchPath.SetValues(gridExtendLocs, gridExtValue); // set grid search path points gridSearchPath.SetValues(searchPath, gridStartValue); // generate a line path with a 7.5 m extension off the end of the path //List<Coordinates> pathPoints = new List<Coordinates>(); //pathPoints.Add(obstaclePath[obstaclePath.Count-1]); //pathPoints.Add(obstaclePath[obstaclePath.Count-1] + obstaclePath.EndSegment.Vector.Normalize(1.5*TahoeParams.VL)); //FindPoints(pathPoints, out gridExtendLocs); //gridSearchPath.SetValues(gridExtendLocs, gridStartValue); // set up left region for grid search path using floodfill int offsetX = searchPath[1].X - searchPath[0].X; int offsetY = searchPath[1].Y - searchPath[0].Y; GridCoordinates leftStartLoc = new GridCoordinates(searchPath[0].X - offsetY, searchPath[0].Y + offsetX); gridSearchPath.FloodFill(leftStartLoc, gridStartValue + 1, 0); // set up right region for grid search path // do nothing, remains 0 // display time to process grid search path gridSearchPathTime = StopWatch("ObstacleManager - GridSearchPath - "); // write grid data to file (for debugging) if (writeToFileFlag == true) { StartWatch(); gridSearchPath.WriteGridToFile("GridSearchPath.txt"); StopWatch("ObstacleManager - GridSearchPath File Write - "); } }
public AfterAttackMessage(IEntity user, IEntity itemInHand, IEntity attacked, GridCoordinates clickLocation) { User = user; Attacked = attacked; ClickLocation = clickLocation; ItemInHand = itemInHand; }