/// <summary> /// Displays the Objects tab /// </summary> /// <param name="objects">List of GameObjects to include in the Item List Tab</param> /// <param name="tile">Tile to include in the Item List Tab</param> /// <param name="position">Position of objects</param> public static void ShowItemListTab(IEnumerable <GameObject> objects, LayerTile tile, Vector3 position) { //If window exists, player is perhaps alt-clicking at another tile. Only slide tabs if Item List Tab doesn't already exist. if (Instance.itemListTabExists) { UITileList.ClearItemPanel(); } else { SlideOptionsAndMoreTabs(Vector3.right); } UITileList.UpdateTileList(objects, tile, position); if (!UITileList.IsEmpty()) { Instance.ItemListTab.GetComponentInChildren <Text>().text = tile ? tile.name : "Objects"; Instance.ItemListTab.gameObject.SetActive(true); Instance.Button_Item_List(); Instance.itemListTabExists = true; } }
public override void WriteSyncData(OutgoingMessage writer) { if (wo.GetAction() == ActionEnum.Move) { this.lastNextTile = move.nextTile; } else if (wo.GetAction() == ActionEnum.Switch) { this.lastNextTile = sb.otherTile; } else { this.lastNextTile = ee.nextTile; } //send action state as it is not synchro yet in the client(for speed purposes) //we should be passing speed instead but messages cannot send double numeric variables. writer.Write((int)wo.GetAction()); writer.Write(lastNextTile.LocalPosition.X); writer.Write(lastNextTile.LocalPosition.Y); lastAnimation = wo.animation; }
public void InternalUpdateTile(Vector3Int position, TileType tileType, string tileName, Matrix4x4?transformMatrix = null, Color?color = null) { LayerTile layerTile = TileManager.GetTile(tileType, tileName); metaTileMap.SetTile(position, layerTile, transformMatrix, color); //if we are changing a tile at z=0, make sure to remove any overlays it has as well //TODO: OVERLAYS - right now it only removes at z = -1, but we will eventually need //to allow multiple overlays on a given location which would require multiple z levels. if (layerTile.TileType != TileType.UnderFloor) { if (position.z == 0) { position.z = -1; if (metaTileMap.HasTile(position, layerTile.LayerType)) { metaTileMap.RemoveTileWithlayer(position, layerTile.LayerType); } } } }
private LayerTile DrawHighlightTile(RectangleShape targetExtent, LayerTile tile) { tile.DrawingLayers.Clear(); if (highlightFeatureLayer.InternalFeatures.Count > 0) { tile.DrawingLayers.Add(highlightFeatureLayer); } GeoCanvas geoCanvas = new GdiPlusGeoCanvas() { CompositingQuality = CompositingQuality.HighSpeed, DrawingQuality = DrawingQuality.HighSpeed, SmoothingMode = SmoothingMode.HighSpeed }; Bitmap bitmap = new Bitmap((int)tile.Width, (int)tile.Height); geoCanvas.BeginDrawing(bitmap, targetExtent, MapArguments.MapUnit); tile.Draw(geoCanvas); geoCanvas.EndDrawing(); tile.CommitDrawing(geoCanvas, MapSuiteSampleHelper.GetImageSourceFromNativeImage(bitmap)); return tile; }
/// <summary> /// Displays the Objects tab /// </summary> /// <param name="objects">List of GameObjects to include in the Item List Tab</param> /// <param name="tile">Tile to include in the Item List Tab</param> /// <param name="position">Position of objects</param> public static void ShowItemListTab(IEnumerable <GameObject> objects, LayerTile tile, Vector3 position) { var tab = Instance.ClientTabs[ClientTabType.ItemList]; if (!UITileList.Instance) { UITileList.Instance = tab.GetComponentsInChildren <UITileList>(true) [0]; } if (!Instance.itemListTabExists) { Instance.UnhideTab(ClientTabType.ItemList); } UITileList.ClearItemPanel(); UITileList.UpdateTileList(objects, tile, position); if (!UITileList.IsEmpty()) { Instance.SelectTab(ClientTabType.ItemList); } }
/// <summary> /// Displays the Objects tab /// </summary> /// <param name="objects">List of GameObjects to include in the Item List Tab</param> /// <param name="tile">Tile to include in the Item List Tab</param> /// <param name="position">Position of objects</param> public static void ShowItemListTab(List <GameObject> objects, LayerTile tile, Vector3 position) { //If window exists, player is perhaps alt-clicking at another tile. Only slide tabs if Item List Tab doesn't already exist. if (Instance.itemListTabExists) { UITileList.ClearItemPanel(); } else { SlideOptionsAndMoreTabs(Vector3.right); } UITileList.AddTileToItemPanel(tile, position); foreach (GameObject itemObject in objects) { UITileList.AddObjectToItemPanel(itemObject); } Instance.ItemListTab.GetComponentInChildren <Text>().text = tile.name; Instance.ItemListTab.gameObject.SetActive(true); Instance.Button_Item_List(); Instance.itemListTabExists = true; }
private LayerTile DrawHighlightTile(RectangleShape targetExtent, LayerTile tile) { tile.DrawingLayers.Clear(); if (highlightFeatureLayer.InternalFeatures.Count > 0) { tile.DrawingLayers.Add(highlightFeatureLayer); } GeoCanvas geoCanvas = new PlatformGeoCanvas() { CompositingQuality = CompositingQuality.HighSpeed, DrawingQuality = DrawingQuality.HighSpeed, SmoothingMode = SmoothingMode.HighSpeed }; Bitmap bitmap = new Bitmap((int)tile.Width, (int)tile.Height); geoCanvas.BeginDrawing(bitmap, targetExtent, MapArguments.MapUnit); tile.Draw(geoCanvas); geoCanvas.EndDrawing(); tile.CommitDrawing(geoCanvas, MapSuiteSampleHelper.GetImageSourceFromNativeImage(bitmap)); return(tile); }
public void EnterCottage(WorldObject cot) { if (CanAct(cot)) { Cottage cottage = cot.Owner.FindComponent <Cottage>(); LayerTile l1 = Map.map.GetTileByWorldPosition(cottage.wo.GetCenteredPosition()); LayerTile l2 = Map.map.GetTileByWorldPosition(wo.GetCenteredPosition()); cottage.SetCount(cottage.GetCount() + 1); nextTile = l1; currentTile = l2; this.cottage = cottage; Trace.WriteLine(cottage.GetCount()); wo.SetAction(ActionEnum.Enter); if (wo.animation != null) { wo.animation.Cancel(); } wo.animation = new WaveEngine.Components.GameActions.MoveTo2DGameAction(Owner, l1.LocalPosition, TimeSpan.FromSeconds(wo.genericSpeed)); wo.animation.Run(); } }
/** * <summary> * show auxiliar info about the map, including the tile in the center of the camera * </summary> */ private void ShowMapInfo() { //get info about map Trace.WriteLine(string.Format("Map size:height={0}, width={1}", map.tiledMap.Height, map.tiledMap.Width)); //A tileset is the set of tiles used for painting de tmx Tileset set = map.tiledMap.GetTilesetByGid(17); if (set != null) { Trace.WriteLine(string.Format("tileset id: {0}", set.FirstGid)); } //tile in the camera center LayerTile tile = map.GetTileByWorldPosition(camTransform.Position); if (tile != null) { Trace.WriteLine(tile.ToString()); Trace.WriteLine(string.Format("Tile coordinate:x={0}, y={1}", tile.X, tile.Y)); Trace.WriteLine(string.Format("tile type: {0}", tile.Tileset.FirstGid)); } }
public void SetPreviewTile(Vector3Int position, LayerTile tile, Matrix4x4 transformMatrix) { for (var i = 0; i < LayersValues.Length; i++) { Layer layer = LayersValues[i]; if (layer.LayerType < tile.LayerType) { if (layer.LayerType == LayerType.Objects) { continue; } Layers[layer.LayerType].SetPreviewTile(position, LayerTile.EmptyTile, Matrix4x4.identity); } } if (!Layers.ContainsKey(tile.LayerType)) { Logger.LogErrorFormat($"LAYER TYPE: {0} not found!", Category.TileMaps, tile.LayerType); return; } Layers[tile.LayerType].SetPreviewTile(position, tile, transformMatrix); }
private float DistBetween(LayerTile current, LayerTile neighbor) { float dist = 1; //If neighbor revealed or visible and occupied or not traversable, no path if (neighbor != start && neighbor != end) { dist = CalculateDistance(neighbor); } //If current revealed or visible and occupied or not traversable, no path if (dist != float.PositiveInfinity && current != start && current != end) { dist = CalculateDistance(current); } //If current not revealed nor visible and neighbor not revealed nor visible, dist is unknown if (dist != float.PositiveInfinity && fog.IsNotVisible(neighbor) && fog.IsNotVisible(current)) { dist = 3; } return(dist); }
/** * <summary> * This loads the first things * </summary> */ public List <LayerTile> DStar(LayerTile startTile, LayerTile endTile) { Reset(); start = startTile; end = endTile; last = start; // The cost of going from end to end is zero. rhs[end] = 0; // For the first node, that value is completely heuristic. fScore[end] = CalculateKey(end); // Initially, only the start node is known. openSet.Add(end, fScore[end]); ComputeShortestPath(); List <LayerTile> tiles = ReconstructPath(); pathSet = true; return(tiles); }
public void RemoveSpecifiedTile(Vector3Int position, LayerTile tile) { if (!TileStore.ContainsKey((Vector2Int)position)) { return; } if (TileStore.ContainsKey((Vector2Int)position)) { if (TileStore[(Vector2Int)position].Contains(tile)) { int index = TileStore[(Vector2Int)position].IndexOf(tile); matrix.TileChangeManager.RemoveTile(new Vector3Int(position.x, position.y, (-index) + 1), LayerType.Underfloor, false); TileStore[(Vector2Int)position][index] = null; } } else { Logger.LogWarning(position + "Was not present in the underfloor layer Trying to remove" + tile); } }
/** * <summary> * Method for executing an action if requires adjacency, * or computes a path and stores the action for when it finishes moving closer * </summary> */ private void HandleMovementAction(WorldObject wo, LayerTile currentTile, ActionBehavior act) { if (selectedWO != null && !selectedWO.IsDestroyed() && !selectedWO.IsActionBlocking()) { if (wo.IsAdjacent(selectedWO)) { SendCommand(act, wo, false); } else if (selectedWO.IsMobile()) { List <LayerTile> dPath = new List <LayerTile>(); DStarLite dstar = selectedWO.Owner.FindComponent <DStarLite>(); LayerTile start = map.GetTileByWorldPosition(selectedWO.GetCenteredPosition()); if (currentTile != start) { dPath = dstar.DStar(start, currentTile); } else { //we are in the same tile, we move to an adjacent an enqueue action dPath.Add(start); List <LayerTile> neighbors = IsAdjacentTileFree(start, dstar); if (neighbors.Count > 0) { dPath.Add(neighbors[0]); } } if (dPath.Count > 1) { SendPath(dPath); SendCommand(act, wo, true); } } } }
public void CmdPoint(GameObject pointTarget, Vector3 mousePos) { if (playerScript.IsGhost || playerScript.playerHealth.ConsciousState != ConsciousState.CONSCIOUS) { return; } //If we are trying to find matrix get matrix instead if (pointTarget.TryGetComponent <MatrixSync>(out var matrixSync)) { pointTarget = matrixSync.NetworkedMatrix.gameObject; } string pointedName = pointTarget.ExpensiveName(); var interactableTiles = pointTarget.GetComponent <InteractableTiles>(); if (interactableTiles) { LayerTile tile = interactableTiles.LayerTileAt(mousePos); if (tile != null) // null if space { pointedName = tile.DisplayName; } } var livinghealthbehavior = pointTarget.GetComponent <LivingHealthMasterBase>(); var preposition = ""; if (livinghealthbehavior == null) { preposition = "the "; } Effect.PlayParticleDirectional(gameObject, mousePos); Chat.AddActionMsgToChat(playerScript.gameObject, $"You point at {preposition}{pointedName}.", $"{playerScript.gameObject.ExpensiveName()} points at {preposition}{pointedName}."); }
/** * <summary> * This calculates a new initial path between start and end. * </summary> */ private void ComputeShortestPath() { while (openSet.Count > 0 && (CompareKeys(openSet.First().Value, CalculateKey(start)) || rhs[start] != gScore[start])) { fScore[start] = CalculateKey(start); Vector2 oldKey = openSet.First().Value; LayerTile u = openSet.First().Key;//the node in openSet having the lowest fScore[] value openSet.Remove(u); if (CompareKeys(oldKey, CalculateKey(u))) { fScore[u] = CalculateKey(u); openSet.Add(u, fScore[u]); } else if (gScore[u] > rhs[u]) { gScore[u] = rhs[u]; foreach (Point neighborPoint in fog.Adjacents(u, adjPoints)) { LayerTile s = map.GetTileByMapCoordinates(neighborPoint.X, neighborPoint.Y); UpdateVertex(s); } } else { gScore[u] = float.PositiveInfinity; UpdateVertex(u); foreach (Point neighborPoint in fog.Adjacents(u, adjPoints)) { LayerTile s = map.GetTileByMapCoordinates(neighborPoint.X, neighborPoint.Y); UpdateVertex(s); } } } }
protected override void DefaultValues() { base.DefaultValues(); // For each node, the cost of getting from the start node to that node. // map with default value of Infinity gScore = new Dictionary <LayerTile, float>(); rhs = new Dictionary <LayerTile, float>(); // For each node, the total cost of getting from the start node to the goal // by passing by that node. That value is partly known, partly heuristic. // map with default value of Infinity fScore = new Dictionary <LayerTile, Vector2>(); // For each node, which node it can most efficiently be reached from. // If a node can be reached from many nodes, cameFrom will eventually contain the // most efficient previous step. cameFrom = new Dictionary <LayerTile, LayerTile>(); // The set of currently discovered nodes that are not evaluated yet. // The set is ordered by the fScore openSet = new SortedList <LayerTile, Vector2>(new DStarTileComparer(fScore)); start = null; end = null; last = null; km = 0; pathSet = false; updatedTiles = new HashSet <LayerTile>(); visitedTiles = new Dictionary <LayerTile, int>(); recalculate = false; }
/// <summary> /// Updates Item List Tab to match what the current item stack holds /// </summary> public static void UpdateItemPanelList() { Vector3 position = GetListedItemsLocation(); if (position == new Vector3(0f, 0f, -100f)) { ClearItemPanel(); return; } List <GameObject> newList = GetItemsAtPosition(position); List <GameObject> oldList = new List <GameObject>(); foreach (GameObject gameObject in Instance.listedObjects) { GameObject item = gameObject.GetComponent <UITileListItem>().Item; //We don't want to add the TileLayer in listedObjects if (item != null) { oldList.Add(item); } } LayerTile newTile = GetTileAtPosition(position); //If item stack has changed, redo the itemList tab if (!newList.AreEquivalent(oldList) || newTile.name != Instance.listedTile.name) { ClearItemPanel(); AddTileToItemPanel(newTile, position); foreach (GameObject gameObject in newList) { AddObjectToItemPanel(gameObject); } } }
private void RedrawTile(LayerTile layerTile) { int tileSW = (int)MapArguments.ActualWidth; int tileSH = (int)MapArguments.ActualHeight; GeoCanvas geoCanvas = null; object nativeImage = null; if (RenderMode == RenderMode.DrawingVisual) { geoCanvas = new DrawingVisualGeoCanvas(); nativeImage = new RenderTargetBitmap(tileSW, tileSH, geoCanvas.Dpi, geoCanvas.Dpi, PixelFormats.Pbgra32); } else { nativeImage = new System.Drawing.Bitmap(tileSW, tileSH); geoCanvas = new PlatformGeoCanvas(); } geoCanvas.BeginDrawing(nativeImage, layerTile.TargetExtent, MapArguments.MapUnit); layerTile.Draw(geoCanvas); geoCanvas.EndDrawing(); layerTile.CommitDrawing(geoCanvas, GetImageSourceFromNativeImage(nativeImage)); }
public void CreateTileDebris(ref LayerTile tile, int x, int y) { float[] speedMultiplier = { -2, 2, -1, 1 }; int quarterSize = Tileset.TileSize / 2; float z = layers[sprLayerIndex].Depth - 80f; Material material = tile.Material.Res; Texture texture = material.MainTexture.Res; for (int i = 0; i < 4; i++) { debrisList.Add(new DestructibleDebris { Pos = new Vector3(x * 32 + (i % 2) * quarterSize, y * 32 + (i / 2) * quarterSize, z), Size = new Vector2(quarterSize, quarterSize), Speed = new Vector2(speedMultiplier[i] * MathF.Rnd.NextFloat(0.8f, 1.2f), -4f * MathF.Rnd.NextFloat(0.8f, 1.2f)), Acceleration = new Vector2(0f, 0.3f), Scale = 1f, ScaleSpeed = MathF.Rnd.NextFloat(-0.01f, -0.002f), AngleSpeed = speedMultiplier[i] * MathF.Rnd.NextFloat(0f, 0.014f), Alpha = 1f, AlphaSpeed = -0.01f, Time = 120f, Material = material, MaterialOffset = new Rect( (tile.MaterialOffset.X + (i % 2) * quarterSize) * texture.UVRatio.X / texture.ContentWidth, (tile.MaterialOffset.Y + (i / 2) * quarterSize) * texture.UVRatio.Y / texture.ContentHeight, quarterSize * texture.UVRatio.X / texture.ContentWidth, quarterSize * texture.UVRatio.Y / texture.ContentHeight ) }); } }
/**<summary> * Returns the tile at the specified coordinates in the playable map * </summary> * <returns> * The tile is null if the position is outside the playable field. Always check if null before doing things with this * </returns> */ public LayerTile GetTileByMapCoordinates(int x, int y) { LayerTile tile = mapLayer.GetLayerTileByMapCoordinates(x, y); return(InBounds(tile) ? tile : null); }
/**<summary> * Returns the tile at the specified position in the playable map * </summary> * <returns> * The tile is null if the position is outside the playable field. Always check if null before doing things with this * </returns> */ public LayerTile GetTileByWorldPosition(Vector2 position) { LayerTile tile = GetLayerTileByWorldPosition(position); return(InBounds(tile) ? tile : null); }
/** * <summary> * Returns true if the tile is inside the playable field * </summary> */ public bool InBounds(LayerTile tile) { return(tile != null?InBounds(tile.X, tile.Y) : false); }
public void ServerPerformMeleeAttack(GameObject victim, Vector2 attackDirection, BodyPartType damageZone, LayerType layerType) { if (Cooldowns.IsOnServer(playerScript, CommonCooldowns.Instance.Melee)) { return; } var weapon = playerScript.playerNetworkActions.GetActiveHandItem(); var tiles = victim.GetComponent <InteractableTiles>(); if (tiles) { //validate based on position of target vector if (!Validations.CanApply(playerScript, victim, NetworkSide.Server, targetVector: attackDirection)) { return; } } else { //validate based on position of target object if (!Validations.CanApply(playerScript, victim, NetworkSide.Server)) { return; } } if (!playerMove.allowInput || playerScript.IsGhost || !victim || !playerScript.playerHealth.serverPlayerConscious ) { return; } var isWeapon = weapon != null; ItemAttributesV2 weaponAttr = isWeapon ? weapon.GetComponent <ItemAttributesV2>() : null; var damage = isWeapon ? weaponAttr.ServerHitDamage : fistDamage; var damageType = isWeapon ? weaponAttr.ServerDamageType : DamageType.Brute; var attackSoundName = isWeapon ? weaponAttr.ServerHitSound : "Punch#"; LayerTile attackedTile = null; bool didHit = false; ItemAttributesV2 weaponStats = null; if (isWeapon) { weaponStats = weapon.GetComponent <ItemAttributesV2>(); } // If Tilemap LayerType is not None then it is a tilemap being attacked if (layerType != LayerType.None) { var tileChangeManager = victim.GetComponent <TileChangeManager>(); if (tileChangeManager == null) { return; //Make sure its on a matrix that is destructable } //Tilemap stuff: var tileMapDamage = victim.GetComponentInChildren <MetaTileMap>().Layers[layerType].gameObject .GetComponent <TilemapDamage>(); if (tileMapDamage != null) { if (isWeapon && weaponStats != null && weaponStats.hitSoundSettings == SoundItemSettings.OnlyObject) { attackSoundName = ""; } var worldPos = (Vector2)transform.position + attackDirection; attackedTile = tileChangeManager.InteractableTiles.LayerTileAt(worldPos, true); tileMapDamage.DoMeleeDamage(worldPos, gameObject, (int)damage); didHit = true; } } else { //a regular object being attacked LivingHealthBehaviour victimHealth = victim.GetComponent <LivingHealthBehaviour>(); var integrity = victim.GetComponent <Integrity>(); if (integrity != null) { //damaging an object if (isWeapon && weaponStats != null && weaponStats.hitSoundSettings == SoundItemSettings.Both) { SoundManager.PlayNetworkedAtPos(integrity.soundOnHit, gameObject.WorldPosServer(), Random.Range(0.9f, 1.1f)); } else if (isWeapon && weaponStats != null && weaponStats.hitSoundSettings == SoundItemSettings.OnlyObject && integrity.soundOnHit != "") { SoundManager.PlayNetworkedAtPos(integrity.soundOnHit, gameObject.WorldPosServer(), Random.Range(0.9f, 1.1f)); attackSoundName = ""; } integrity.ApplyDamage((int)damage, AttackType.Melee, damageType); didHit = true; } else { //damaging a living thing var rng = new System.Random(); // This is based off the alien/humanoid/attack_hand punch code of TGStation's codebase. // Punches have 90% chance to hit, otherwise it is a miss. if (isWeapon || 90 >= rng.Next(1, 100)) { // The attack hit. victimHealth.ApplyDamageToBodypart(gameObject, (int)damage, AttackType.Melee, damageType, damageZone); didHit = true; } else { // The punch missed. string victimName = victim.Player()?.Name; SoundManager.PlayNetworkedAtPos("PunchMiss", transform.position); Chat.AddCombatMsgToChat(gameObject, $"You attempted to punch {victimName} but missed!", $"{gameObject.Player()?.Name} has attempted to punch {victimName}!"); } } } //common logic to do if we hit something if (didHit) { if (!string.IsNullOrEmpty(attackSoundName)) { SoundManager.PlayNetworkedAtPos(attackSoundName, transform.position); } if (damage > 0) { Chat.AddAttackMsgToChat(gameObject, victim, damageZone, weapon, attackedTile: attackedTile); } if (victim != gameObject) { RpcMeleeAttackLerp(attackDirection, weapon); //playerMove.allowInput = false; } } Cooldowns.TryStartServer(playerScript, CommonCooldowns.Instance.Melee); }
private void PlaceLayerTile(MetaTileMap metaTileMap, Vector3Int position, LayerTile tile) { //metaTileMap.RemoveTileWithlayer(position, tile.LayerType); SetTile(metaTileMap, position, tile); }
protected override void Update(TimeSpan gameTime) { if (wo.networkedScene.isHost) { if (wo.GetAction() == ActionEnum.Enter) { LayerTile tile = Map.map.GetTileByWorldPosition(wo.GetCenteredPosition()); if (tile == nextTile) { if (cottage != null && !cottage.IsDestroyed()) { cottage.AddPerson(wo); cottage = null; if (Map.map.GetWorldObject(currentTile.X, currentTile.Y) == null || Map.map.GetWorldObject(currentTile.X, currentTile.Y).IsTraversable(wo)) { //This is common execution path. however, if we came from a water tile because the bridge was destroyed //this should not, and do not, run, effectively not setting the water tile to false, which is not right Map.map.SetTileOccupied(currentTile.X, currentTile.Y, false); Map.map.SetMobile(currentTile.X, currentTile.Y, null); } //nullify coordinates so when destroyed wont set anything free wo.SetX(-1); wo.SetY(-1); nextTile = null; currentTile = null; cottage = null; wo.SetAction(ActionEnum.Inside); } else { ExitCottage(nextTile, currentTile); } } } else if (wo.GetAction() == ActionEnum.Exit) { Map map = Map.map; LayerTile tile = Map.map.GetTileByWorldPosition(wo.GetCenteredPosition()); if (tile == nextTile) { if (map.GetWorldObject(nextTile.X, nextTile.Y) != null && !map.GetWorldObject(nextTile.X, nextTile.Y).IsTraversable(wo)) { if (cottage != null && !cottage.IsDestroyed()) { //If we found water, return back EnterCottage(cottage.wo); } else { //If we found water and the cottage is destroyed, back luck wo.Destroy(); } } else { Map.map.SetMobile(nextTile.X, nextTile.Y, wo); if (tile.LocalPosition == wo.transform.Position) { wo.Stop(); nextTile = null; currentTile = null; cottage = null; } } } } } }
/// <summary> /// Sends a message to all players about an attack that took place /// </summary> /// <param name="attacker">GameObject of the player that attacked</param> /// <param name="victim">GameObject of the player hat was the victim</param> /// <param name="damage">damage done</param> /// <param name="hitZone">zone that was damaged</param> /// <param name="item">optional gameobject with an itemattributes, representing the item the attack was made with</param> /// <param name="customAttackVerb">If you want to override the attack verb then pass the verb here</param> /// <param name="attackedTile">If attacking a particular tile, the layer tile being attacked</param> public static void AddAttackMsgToChat(GameObject attacker, GameObject victim, BodyPartType hitZone = BodyPartType.None, GameObject item = null, string customAttackVerb = "", LayerTile attackedTile = null) { string attackVerb; string attack; if (item) { var itemAttributes = item.GetComponent <ItemAttributesV2>(); attackVerb = itemAttributes.ServerAttackVerbs.PickRandom() ?? "attacked"; attack = $" with {itemAttributes.ArticleName}"; } else { // Punch attack as there is no item. attackVerb = "punched"; attack = ""; } if (!string.IsNullOrEmpty(customAttackVerb)) { attackVerb = customAttackVerb; } var player = victim.Player(); if (player == null) { hitZone = BodyPartType.None; } string victimName; string victimNameOthers = ""; if (attacker == victim) { victimName = "yourself"; if (player != null) { if (player.Script.characterSettings.Gender == Gender.Female) { victimNameOthers = "herself"; } if (player.Script.characterSettings.Gender == Gender.Male) { victimNameOthers = "himself"; } if (player.Script.characterSettings.Gender == Gender.Neuter) { victimNameOthers = "itself"; } } else { victimNameOthers = "itself"; } } else if (attackedTile != null) { victimName = attackedTile.DisplayName; victimNameOthers = victimName; } else { victimName = victim.ExpensiveName(); victimNameOthers = victimName; } var attackerName = attacker.Player()?.Name; if (string.IsNullOrEmpty(attackerName)) { var mobAi = attacker.GetComponent <MobAI>(); if (mobAi != null) { attackerName = mobAi.mobName; } else { attackerName = "Unknown"; } } var messageOthers = $"{attackerName} has {attackVerb} {victimNameOthers}{InTheZone(hitZone)}{attack}!"; var message = $"You {attackVerb} {victimName}{InTheZone(hitZone)}{attack}!"; Instance.addChatLogServer.Invoke(new ChatEvent { channels = ChatChannel.Combat, message = message, messageOthers = messageOthers, position = attacker.WorldPosServer(), speaker = attacker.name, originator = attacker }); }
public void CmdRequestMeleeAttack(GameObject victim, Vector2 attackDirection, BodyPartType damageZone, LayerType layerType) { var weapon = playerScript.playerNetworkActions.GetActiveHandItem(); var tiles = victim.GetComponent <InteractableTiles>(); if (tiles) { //validate based on position of target vector if (!Validations.CanApply(playerScript, victim, NetworkSide.Server, targetVector: attackDirection)) { return; } } else { //validate based on position of target object if (!Validations.CanApply(playerScript, victim, NetworkSide.Server)) { return; } } if (!playerMove.allowInput || playerScript.IsGhost || !victim || !playerScript.playerHealth.serverPlayerConscious ) { return; } if (!allowAttack) { return; } var isWeapon = weapon != null; ItemAttributesV2 weaponAttr = isWeapon ? weapon.GetComponent <ItemAttributesV2>() : null; var damage = isWeapon ? weaponAttr.ServerHitDamage : fistDamage; var damageType = isWeapon ? weaponAttr.ServerDamageType : DamageType.Brute; var attackSoundName = isWeapon ? weaponAttr.ServerHitSound : "Punch#"; LayerTile attackedTile = null; bool didHit = false; // If Tilemap LayerType is not None then it is a tilemap being attacked if (layerType != LayerType.None) { var tileChangeManager = victim.GetComponent <TileChangeManager>(); if (tileChangeManager == null) { return; //Make sure its on a matrix that is destructable } //Tilemap stuff: var tileMapDamage = victim.GetComponentInChildren <MetaTileMap>().Layers[layerType].gameObject .GetComponent <TilemapDamage>(); if (tileMapDamage != null) { var worldPos = (Vector2)transform.position + attackDirection; attackedTile = tileChangeManager.InteractableTiles.LayerTileAt(worldPos); tileMapDamage.DoMeleeDamage(worldPos, gameObject, (int)damage); didHit = true; } } else { //a regular object being attacked //butchering //TODO: Move butchering logic to IF2, it should be a progress action done on corpses (make a Corpse component probably) LivingHealthBehaviour victimHealth = victim.GetComponent <LivingHealthBehaviour>(); if (victimHealth != null && victimHealth.IsDead && isWeapon && weaponAttr.HasTrait(KnifeTrait)) { if (victim.GetComponent <SimpleAnimal>()) { SimpleAnimal attackTarget = victim.GetComponent <SimpleAnimal>(); RpcMeleeAttackLerp(attackDirection, weapon); playerMove.allowInput = false; attackTarget.Harvest(); SoundManager.PlayNetworkedAtPos("BladeSlice", transform.position); } else { PlayerHealth attackTarget = victim.GetComponent <PlayerHealth>(); RpcMeleeAttackLerp(attackDirection, weapon); playerMove.allowInput = false; attackTarget.Harvest(); SoundManager.PlayNetworkedAtPos("BladeSlice", transform.position); } } var integrity = victim.GetComponent <Integrity>(); if (integrity != null) { //damaging an object integrity.ApplyDamage((int)damage, AttackType.Melee, damageType); didHit = true; } else { //damaging a living thing var rng = new System.Random(); // This is based off the alien/humanoid/attack_hand punch code of TGStation's codebase. // Punches have 90% chance to hit, otherwise it is a miss. if (isWeapon || 90 >= rng.Next(1, 100)) { // The attack hit. victimHealth.ApplyDamageToBodypart(gameObject, (int)damage, AttackType.Melee, damageType, damageZone); didHit = true; } else { // The punch missed. string victimName = victim.Player()?.Name; SoundManager.PlayNetworkedAtPos("PunchMiss", transform.position); Chat.AddCombatMsgToChat(gameObject, $"You attempted to punch {victimName} but missed!", $"{gameObject.Player()?.Name} has attempted to punch {victimName}!"); } } } //common logic to do if we hit something if (didHit) { SoundManager.PlayNetworkedAtPos(attackSoundName, transform.position); if (damage > 0) { Chat.AddAttackMsgToChat(gameObject, victim, damageZone, weapon, attackedTile: attackedTile); } if (victim != gameObject) { RpcMeleeAttackLerp(attackDirection, weapon); playerMove.allowInput = false; } } //no matter what, start a cooldown for attacking again so they can't spam attack requests StartCoroutine(AttackCoolDown()); }
private bool DetermineTileAction(GameObject originator, Vector3 position, string hand) { metaTileMap = originator.GetComponentInParent <MetaTileMap>(); objectLayer = originator.GetComponentInParent <ObjectLayer>(); PlayerNetworkActions pna = originator.GetComponent <PlayerNetworkActions>(); Vector3Int pos = objectLayer.transform.InverseTransformPoint(position).RoundToInt(); pos.z = 0; Vector3Int cellPos = baseTileMap.WorldToCell(position); LayerTile tile = metaTileMap.GetTile(pos); GameObject handObj; //if we are client, our pna.Inventory is always empty so we should get the hand item a different way if (!isServer) { if (originator != PlayerManager.LocalPlayer) { Logger.LogError("Client is attempting to determine the tile actions of a player other than" + " themselves. This should not happen and should be fixed. Client should only determine their own" + " actions."); return(false); } else { handObj = UIManager.InventorySlots[hand].Item; } } else { handObj = pna.Inventory[hand].Item; } // Nothing in hand, do nothing if (handObj == null) { return(false); } if (tile != null) { switch (tile.TileType) { case TileType.Table: { Vector3 targetPosition = position; targetPosition.z = -0.2f; pna.CmdPlaceItem(hand, targetPosition, originator, true); return(true); } case TileType.Floor: { //Crowbar if (handObj.GetComponent <CrowbarTrigger>()) { pna.CmdCrowBarRemoveFloorTile(originator, LayerType.Floors, new Vector2(cellPos.x, cellPos.y), position); return(true); } break; } case TileType.Base: { if (handObj.GetComponent <UniFloorTile>()) { pna.CmdPlaceFloorTile(originator, new Vector2(cellPos.x, cellPos.y), handObj); return(true); } break; } case TileType.Window: { //Check Melee: MeleeTrigger melee = windowTileMap.gameObject.GetComponent <MeleeTrigger>(); if (melee != null && melee.MeleeInteract(originator, hand)) { return(true); } break; } case TileType.Grill: { //Check Melee: MeleeTrigger melee = grillTileMap.gameObject.GetComponent <MeleeTrigger>(); if (melee != null && melee.MeleeInteract(originator, hand)) { return(true); } break; } case TileType.Wall: { Welder welder = handObj.GetComponent <Welder>(); if (welder) { if (welder.isOn) { //Request to deconstruct from the server: RequestTileDeconstructMessage.Send(originator, gameObject, TileType.Wall, cellPos, position); return(true); } } break; } } } return(false); }
private void RefreshHighlightLayerTileAndPopup(RectangleShape targetExtent, LayerTile tile) { bool isRefreshTile = false; if (translateTransform.X != 0 || translateTransform.Y != 0 || MapArguments.CurrentScale != currentScale) { translateTransform.X = 0; translateTransform.Y = 0; tile = DrawHighlightTile(targetExtent, tile); isRefreshTile = true; } if (highlightFeature != null) { string key = highlightFeature.ColumnValues.Select(k => k.Key).ToArray()[0]; if (highlightFeatureLayer.InternalFeatures.Count == 0 || !highlightFeatureLayer.InternalFeatures[0].ColumnValues.ContainsKey(key) || (highlightFeatureLayer.InternalFeatures.Count > 0 && (highlightFeature.ColumnValues[key] != highlightFeatureLayer.InternalFeatures[0].ColumnValues[key]))) { highlightFeatureLayer.InternalFeatures.Clear(); highlightFeatureLayer.InternalFeatures.Add(highlightFeature); tile = DrawHighlightTile(targetExtent, tile); isRefreshTile = true; } } else if (highlightFeatureLayer.InternalFeatures.Count > 0) { highlightFeatureLayer.InternalFeatures.Clear(); tile = DrawHighlightTile(targetExtent, tile); isRefreshTile = true; } RefreshOverlayCanvas(targetExtent, tile, isRefreshTile); currentScale = MapArguments.CurrentScale; }
public void SetTile(Vector3Int position, LayerTile tile, Matrix4x4 transformMatrix) { Layers[tile.LayerType].SetTile(position, tile, transformMatrix); }
private LayerTile GetTile(RectangleShape targetExtent, double tileScreenWidth, double tileScreenHeight, long tileColumnIndex, long tileRowIndex, int zoomLevelIndex) { LayerTile layerTile = new LayerTile(); layerTile.Width = tileScreenWidth; layerTile.Height = tileScreenHeight; layerTile.IsAsync = false; layerTile.RowIndex = tileRowIndex; layerTile.ColumnIndex = tileColumnIndex; layerTile.TargetExtent = targetExtent; layerTile.ZoomLevelIndex = zoomLevelIndex; layerTile.DrawingExceptionMode = DrawingExceptionMode; layerTile.Background = new SolidColorBrush(Colors.Transparent); return layerTile; }
public void SetTile(Vector3Int position, LayerTile tile) { Layers[tile.LayerType].SetTile(position, tile, Matrix4x4.identity); }
private void RefreshOverlayCanvas(RectangleShape targetExtent, LayerTile tile, bool isRefreshTile) { if (isRefreshTile) { OverlayCanvas.Children.Clear(); Canvas.SetTop(tile, 0); Canvas.SetLeft(tile, 0); OverlayCanvas.Children.Add(tile); } }