diff --git a/src/proceduralItem/modifiers/restrictions/_list.zig b/src/proceduralItem/modifiers/restrictions/_list.zig index c77fcf13aa..59717b3340 100644 --- a/src/proceduralItem/modifiers/restrictions/_list.zig +++ b/src/proceduralItem/modifiers/restrictions/_list.zig @@ -3,3 +3,4 @@ pub const @"and" = @import("and.zig"); pub const encased = @import("encased.zig"); pub const not = @import("not.zig"); pub const @"or" = @import("or.zig"); +pub const on_orthogonal = @import("on_orthogonal.zig"); diff --git a/src/proceduralItem/modifiers/restrictions/on_orthogonal.zig b/src/proceduralItem/modifiers/restrictions/on_orthogonal.zig new file mode 100644 index 0000000000..2e1c35ec3c --- /dev/null +++ b/src/proceduralItem/modifiers/restrictions/on_orthogonal.zig @@ -0,0 +1,52 @@ +const std = @import("std"); + +const main = @import("main"); +const NeverFailingAllocator = main.heap.NeverFailingAllocator; +const ModifierRestriction = main.items.ModifierRestriction; +const ProceduralItem = main.items.ProceduralItem; +const ZonElement = main.ZonElement; + +const On_orthogonal = struct { + tag: main.Tag, + amount: usize, + range: ?usize, +}; + +pub fn satisfied(self: *const On_orthogonal, proceduralItem: *const ProceduralItem, x: i32, y: i32) bool { + var count: usize = 0; + const gridSize: usize = proceduralItem.materialGrid.len - 1; + const rangeChecked = @min(self.range orelse gridSize, gridSize); + const lowBound = 0; + const highBound = rangeChecked*2 + 1; + for (lowBound..highBound) |dx| { + const checkedX = x + (@as(i32, @intCast(dx)) - rangeChecked); + const checkedY = y + (@as(i32, @intCast(0)) - rangeChecked); + if ((proceduralItem.getItemAt(checkedX, checkedY) orelse continue).hasTag(self.tag)) count += 1; + } + for (lowBound..highBound) |dy| { + const checkedX = x + (@as(i32, @intCast(0)) - rangeChecked); + const checkedY = y + (@as(i32, @intCast(dy)) - rangeChecked); + if (dy != 0) { // prevents double counting + if ((proceduralItem.getItemAt(checkedX, checkedY) orelse continue).hasTag(self.tag)) count += 1; + } + } + return count >= self.amount; +} + +pub fn loadFromZon(allocator: NeverFailingAllocator, zon: ZonElement) *const On_orthogonal { + const result = allocator.create(On_orthogonal); + result.* = .{ + .tag = main.Tag.find(zon.get([]const u8, "tag", "not specified")), + .amount = zon.get(usize, "amount", 8), + .range = zon.get(?usize, "range", null), + }; + return result; +} + +pub fn printTooltip(self: *const On_orthogonal, outString: *main.List(u8)) void { + if (self.range == null) { + outString.print("{} .{s} {s}", .{self.amount, self.tag.getName(), "on orthoganal axis"}); + } else { + outString.print("{} .{s} {s} {?}", .{self.amount, self.tag.getName(), "in orthoganal range", self.range}); + } +}