/// <summary> /// Get the coordinates of the skill's effect, if needed change the offset to match the direction of the player. /// For skills that paint the ground, match the correct height. /// </summary> private static List <CoordF> GetEffectCoords(SkillCast skillCast, int mapId, int attackIndex) { SkillAttack skillAttack = skillCast.SkillAttack; List <MagicPathMove> cubeMagicPathMoves = new(); List <MagicPathMove> magicPathMoves = new(); if (skillAttack.CubeMagicPathId != 0) { cubeMagicPathMoves.AddRange(MagicPathMetadataStorage.GetMagicPath(skillAttack.CubeMagicPathId)?.MagicPathMoves ?? new()); } if (skillAttack.MagicPathId != 0) { magicPathMoves.AddRange(MagicPathMetadataStorage.GetMagicPath(skillAttack.MagicPathId)?.MagicPathMoves ?? new()); } int skillMovesCount = cubeMagicPathMoves.Count + magicPathMoves.Count; List <CoordF> effectCoords = new(); if (skillMovesCount <= 0) { effectCoords.Add(skillCast.Position); return(effectCoords); } // TODO: Handle case where magicPathMoves and cubeMagicPathMoves counts are > 0 // Basically do the next if, with the later for loop if (magicPathMoves.Count > 0) { MagicPathMove magicPathMove = magicPathMoves[attackIndex]; IFieldActor <NpcMetadata> parentSkillTarget = skillCast.ParentSkill.Target; if (parentSkillTarget is not null) { effectCoords.Add(parentSkillTarget.Coord); return(effectCoords); } // Rotate the offset coord and distance based on the look direction CoordF rotatedOffset = CoordF.From(magicPathMove.FireOffsetPosition.Length(), skillCast.LookDirection); CoordF distance = CoordF.From(magicPathMove.Distance, skillCast.LookDirection); // Create new effect coord based on offset rotation and distance effectCoords.Add(rotatedOffset + distance + skillCast.Position); return(effectCoords); } // Adjust the effect on the destination/cube foreach (MagicPathMove cubeMagicPathMove in cubeMagicPathMoves) { CoordF offSetCoord = cubeMagicPathMove.FireOffsetPosition; // If false, rotate the offset based on the look direction. Example: Wizard's Tornado if (!cubeMagicPathMove.IgnoreAdjust) { // Rotate the offset coord based on the look direction CoordF rotatedOffset = CoordF.From(offSetCoord.Length(), skillCast.LookDirection); // Create new effect coord based on offset rotation and source coord effectCoords.Add(rotatedOffset + skillCast.Position); continue; } offSetCoord += Block.ClosestBlock(skillCast.Position); CoordS tempBlockCoord = offSetCoord.ToShort(); // Set the height to the max allowed, which is one block above the cast coord. tempBlockCoord.Z += Block.BLOCK_SIZE * 2; // Find the first block below the effect coord int distanceToNextBlockBelow = MapMetadataStorage.GetDistanceToNextBlockBelow(mapId, offSetCoord.ToShort(), out MapBlock blockBelow); // If the block is null or the distance from the cast effect Z height is greater than two blocks, continue if (blockBelow is null || distanceToNextBlockBelow > Block.BLOCK_SIZE * 2) { continue; } // If there is a block above, continue if (MapMetadataStorage.BlockAboveExists(mapId, blockBelow.Coord)) { continue; } // If block is liquid, continue if (MapMetadataStorage.IsLiquidBlock(blockBelow)) { continue; } // Since this is the block below, add 150 units to the Z coord so the effect is above the block offSetCoord = blockBelow.Coord.ToFloat(); offSetCoord.Z += Block.BLOCK_SIZE; effectCoords.Add(offSetCoord); } return(effectCoords); }