Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions nml/actions/action0properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import itertools

from nml import generic, nmlop, global_constants
from nml.global_constants import constant_numbers as global_constant_numbers
from nml.expression import (
AcceptCargo,
Array,
Expand Down Expand Up @@ -818,6 +819,48 @@ def station_tile_flags(value):
]


def array_for_station_properties(prop_num: int, list_type: str, invert_function: callable):
def generated_function(value):
if not isinstance(value, Array):
raise generic.ScriptError(f"{list_type} list must be an array, not {type(value).__name__}", value.pos)
new_value = Array([], value.pos)
for element in value.values:
if isinstance(element, ConstantNumeric):
new_value.values.append(element)
new_value.values.append(invert_function(element))
elif isinstance(element, Array):
if len(element.values) != 2:
raise generic.ScriptError(
f"{list_type} list can only contain int or two element array", element.pos
)
new_value.values.append(element.values[0])
new_value.values.append(element.values[1])
else:
raise generic.ScriptError(f"{list_type} list can only contain int or two element array", element.pos)
if len(new_value.values) % 2 != 0:
raise generic.ScriptError(f"{list_type} list does not have even length", new_value.pos)
return [VariableByteListProp(prop_num, [[flags.reduce_constant().value for flags in new_value.values]], True)]

return generated_function


def invert_bridge_pillars_flags(value):
out = ConstantNumeric(0, value.pos)
for i_flag, o_flag in [
(global_constant_numbers["BRIDGE_PILLAR_CORNER_W"], global_constant_numbers["BRIDGE_PILLAR_CORNER_S"]),
(global_constant_numbers["BRIDGE_PILLAR_CORNER_S"], global_constant_numbers["BRIDGE_PILLAR_CORNER_W"]),
(global_constant_numbers["BRIDGE_PILLAR_CORNER_N"], global_constant_numbers["BRIDGE_PILLAR_CORNER_E"]),
(global_constant_numbers["BRIDGE_PILLAR_CORNER_E"], global_constant_numbers["BRIDGE_PILLAR_CORNER_N"]),
(global_constant_numbers["BRIDGE_PILLAR_EDGE_NE"], global_constant_numbers["BRIDGE_PILLAR_EDGE_NE"]),
(global_constant_numbers["BRIDGE_PILLAR_EDGE_SE"], global_constant_numbers["BRIDGE_PILLAR_EDGE_SW"]),
(global_constant_numbers["BRIDGE_PILLAR_EDGE_SW"], global_constant_numbers["BRIDGE_PILLAR_EDGE_SE"]),
(global_constant_numbers["BRIDGE_PILLAR_EDGE_NW"], global_constant_numbers["BRIDGE_PILLAR_EDGE_NW"]),
]:
if value.value & (1 << i_flag):
out.value += 1 << o_flag
return out
Comment on lines +847 to +861
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic should not be here, it's a bad idea to assume that the flags can be flipped.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not?
It is based on how station's sprite should be inverted.
Zrzut ekranu z 2025-09-01 19-29-19

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because NML shouldn't be assuming anything. There's no rule that says sprites should be "inverted".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here picture clearly says that other values are invertible.
Station_var45



# fmt: off
properties[0x04] = {
"class": {"size": 4, "num": 0x08, "first": None, "string_literal": 4},
Expand All @@ -843,6 +886,12 @@ def station_tile_flags(value):
"name": {"size": 2, "num": (256, -1, 0x1C), "string": (256, 0xC5, 0xDC), "required": True},
"classname": {"size": 2, "num": (256, -1, 0x1D), "string": (256, 0xC4, 0xDC)},
"tile_flags": {"custom_function": station_tile_flags}, # = prop 1E
"minimum_bridge_height": {
"custom_function": array_for_station_properties(0x20, "Bridge heights", lambda v : v)
},
"bridge_pillars_flags": {
"custom_function": array_for_station_properties(0x21, "Flag", invert_bridge_pillars_flags)
},
}
# fmt: on

Expand Down Expand Up @@ -1657,4 +1706,10 @@ def byte_sequence_list(value, prop_num, description, expected_count):
# 11 (callback flags) is not set by user
"general_flags": {"size": 4, "num": 0x12},
"cost_multipliers": {"custom_function": lambda x: byte_sequence_list(x, 0x15, "Cost multipliers", 2)},
"minimum_bridge_height": {
"custom_function": array_for_station_properties(0x13, "Bridge heights", lambda v : v)
},
"bridge_pillars_flags": {
"custom_function": array_for_station_properties(0x14, "Flag", invert_bridge_pillars_flags)
},
}
10 changes: 10 additions & 0 deletions nml/global_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,16 @@ def constant_number(name, info, pos):
# station tiles
"STAT_ALL_TILES" : 0xFF,

# bridge pillar flags
"BRIDGE_PILLAR_CORNER_W" : 0,
"BRIDGE_PILLAR_CORNER_S" : 1,
"BRIDGE_PILLAR_CORNER_E" : 2,
"BRIDGE_PILLAR_CORNER_N" : 3,
"BRIDGE_PILLAR_EDGE_NE" : 4,
"BRIDGE_PILLAR_EDGE_SE" : 5,
"BRIDGE_PILLAR_EDGE_SW" : 6,
"BRIDGE_PILLAR_EDGE_NW" : 7,

# house flags
"HOUSE_FLAG_NOT_SLOPED" : 1,
"HOUSE_FLAG_ANIMATE" : 5,
Expand Down
Loading