Documentation for this module may be created at Module:TestModule/doc
local p = {}
p.consts = {
bg_color = '#191714',
canvas_padding = 20,
icon_edge_thickness = 6,
label_font_size = 14,
node_size = {-1, -1},
node_padding = {8, 16, 8, 16},
node_icon_size = 64,
node_icon_padding = 16,
node_icon_container_size = -1,
node_spacing = {-1, -1},
wikitext_template_icon = '[[File:%s|frameless|%spx|link=]]',
wikitext_template_link = '[[%s|<span class="fab-station-ui__link" style="position: absolute; top: 0; left: 0; width: 100%%; height: 100%%;"/>]]',
tab_order = {
'garage',
'refine',
'survival_tools',
'lights',
'car_body',
'wheels',
'expansion_racks',
'car_storage',
'fuel',
'battery',
'utilities',
'engines',
},
}
p.consts.node_icon_container_size = p.consts.node_icon_size + p.consts.node_icon_padding * 2 + p.consts.icon_edge_thickness * 2
p.consts.node_size = {
p.consts.node_icon_container_size + p.consts.node_padding[2] + p.consts.node_padding[4],
p.consts.node_icon_container_size + p.consts.node_padding[1] + p.consts.node_padding[3] + 40
}
p.consts.node_spacing = {
p.consts.node_size[1] * 0.5,
p.consts.node_size[2] * 0.3,
}
-- slot notation is {row, col}
-- nodes are recorded left to right, top to bottom
-- edges are recorded by source node, left to right, top to bottom
p.tabs = {
battery = {
canvas_slots = {3, 6},
edges = {
{4, 1},
{4, 5},
{5, 2},
{5, 6},
{5, 10},
{6, 7},
{6, 11},
{7, 3},
{7, 8},
{8, 9},
{8, 12},
},
nodes = {
-- 1
{
id = 'plasma_charger',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Plasma Charger',
label = 'Plasma Charger',
slot = {1, 2},
},
-- 2
{
id = 'hydro_generator',
icon = 'RAIN-GENERATOR.png',
link_to = 'Hydro Generator',
label = 'Hydro Generator',
slot = {1, 3},
},
-- 3
{
id = 'leak_resistant_battery',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Leak-Resistant Battery',
label = 'Leak-Resistant Battery',
slot = {1, 5},
},
-- 4
{
id = 'battery_jumper',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Battery Jumper',
label = 'Battery Jumper',
slot = {2, 1},
},
-- 5
{
id = 'lightning_rod',
icon = 'ELEC-GENERATOR.png',
link_to = 'Lightning Rod',
label = 'Lightning Rod',
slot = {2, 2},
},
-- 6
{
id = 'side_battery',
icon = 'SIDE-BATTERY.png',
link_to = 'Side Battery',
label = 'Side Battery',
slot = {2, 3},
},
-- 7
{
id = 'lead_acid_battery',
icon = 'BACKSEAT-BATTERY.png',
link_to = 'Lead-Acid Battery',
label = 'Lead-Acid Battery',
slot = {2, 4},
},
-- 8
{
id = 'high_capacity_battery',
icon = 'EXPANDED-BACKSEAT-BATTERY.png',
link_to = 'High-Capacity Battery',
label = 'High-Capacity Battery',
slot = {2, 5},
},
-- 9
{
id = 'xl_roof_battery',
icon = 'ROOF-BATTERY.png',
link_to = 'XL Roof Battery',
label = 'XL Roof Battery',
slot = {2, 6},
},
-- 10
{
id = 'mini_turbine',
icon = 'Mini_Turbine_Icon.png',
link_to = 'Mini Turbine',
label = 'Mini Turbine',
slot = {3, 3},
},
-- 11
{
id = 'solar_panel',
icon = 'SOLAR-GENERATOR.png',
link_to = 'Solar Panel',
label = 'Solar Panel',
slot = {3, 4},
},
-- 12
{
id = 'anchor_energy_converter',
icon = 'BATTERY-GOBBLER.png',
link_to = 'Anchor Energy Converter',
label = 'Anchor Energy Converter',
slot = {3, 6},
},
},
},
car_body = {
canvas_slots = {7, 4},
edges = {
{2, 3},
{5, 1},
{5, 2},
{7, 8},
{8, 4},
{8, 5},
{8, 6},
{11, 12},
{12, 9},
{12, 13},
{12, 17},
{13, 10},
{13, 14},
{15, 16},
{16, 18},
{16, 19},
{16, 20},
{19, 21},
{19, 22},
},
nodes = {
-- 1
{
id = 'anti_corrosive_bumper',
icon = 'ACID-BUMPER.png',
link_to = 'Anti-Corrosive Bumper',
label = 'Anti-Corrosive Bumper',
slot = {1, 1},
},
-- 2
{
id = 'olympium_bumper',
icon = 'ACID-BUMPER.png',
link_to = 'Olympium Bumper',
label = 'Olympium Bumper',
slot = {1, 2},
},
-- 3
{
id = 'powered_bumper',
icon = 'POWERED-BUMPER.png',
link_to = 'Powered Bumper',
label = 'Powered Bumper',
slot = {1, 3},
},
-- 4
{
id = 'lead_plated_bumper',
icon = 'RADS-BUMPER.png',
link_to = 'Lead-Plated Bumper',
label = 'Lead-Plated Bumper',
slot = {2, 1},
},
-- 5
{
id = 'armored_bumper',
icon = 'HEAL-BUMPER.png',
link_to = 'Armored Bumper',
label = 'Armored Bumper',
slot = {2, 2},
},
-- 6
{
id = 'insulated_bumper',
icon = 'ELE-BUMPER.png',
link_to = 'Insulated Bumper',
label = 'Insulated Bumper',
slot = {2, 3},
},
-- 7
{
id = 'crude_bumper',
icon = 'Crude_Bumper.png',
link_to = 'Crude Bumper',
label = 'Crude Bumper',
slot = {3, 1},
},
-- 8
{
id = 'steel_bumper',
icon = 'Steel_Bumper.png',
link_to = 'Steel Bumper',
label = 'Steel Bumper',
slot = {3, 2},
},
-- 9
{
id = 'lead_plated_panel',
icon = 'RADS-PANEL.png',
link_to = 'Lead-Plated Panel',
label = 'Lead-Plated Panel',
slot = {3, 3},
},
-- 10
{
id = 'anti_corrosive_panel',
icon = 'POISON-PANEL.png',
link_to = 'Anti-Corrosive Panel',
label = 'Anti-Corrosive Panel',
slot = {3, 4},
},
-- 11
{
id = 'crude_panel',
icon = 'Crude_Panel.png',
link_to = 'Crude Panel',
label = 'Crude Panel',
slot = {4, 1},
},
-- 12
{
id = 'steel_panel',
icon = 'Steel_Panel.png',
link_to = 'Steel Panel',
label = 'Steel Panel',
slot = {4, 2},
},
-- 13
{
id = 'armored_panel',
icon = 'HEAL-PANEL.png',
link_to = 'Armored Panel',
label = 'Armored Panel',
slot = {4, 3},
},
-- 14
{
id = 'olympium_panel',
icon = 'PHYS-PANEL.png',
link_to = 'Olympium Panel',
label = 'Olympium Panel',
slot = {4, 4},
},
-- 15
{
id = 'crude_door',
icon = 'Crude_Door.png',
link_to = 'Crude Door',
label = 'Crude Door',
slot = {5, 1},
},
-- 16
{
id = 'steel_door',
icon = 'Steel_Door.png',
link_to = 'Steel Door',
label = 'Steel Door',
slot = {5, 2},
},
-- 17
{
id = 'insulated_panel',
icon = 'ELEC-PANEL.png',
link_to = 'Insulated Panel',
label = 'Insulated Panel',
slot = {5, 3},
},
-- 18
{
id = 'insulated_door',
icon = 'CAGED-STEEL-DOOR.png',
link_to = 'Insulated Door',
label = 'Insulated Door',
slot = {6, 1},
},
-- 19
{
id = 'armored_door',
icon = 'PLATED-DOOR.png',
link_to = 'Armored Door',
label = 'Armored Door',
slot = {6, 2},
},
-- 20
{
id = 'lead_plated_door',
icon = 'LEAD-SHIELD-DOOR.png',
link_to = 'Lead-Plated Door',
label = 'Lead-Plated Door',
slot = {6, 3},
},
-- 21
{
id = 'olympium_door',
icon = 'REINFORCED-DOOR.png',
link_to = 'Olympium Door',
label = 'Olympium Door',
slot = {7, 2},
},
-- 22
{
id = 'anti_corrosive_door',
icon = 'STEEL-FIBRE-DOOR.png',
link_to = 'Anti-Corrosive Door',
label = 'Anti-Corrosive Door',
slot = {7, 3},
},
},
},
car_storage = {
canvas_slots = {2, 3},
edges = {
{2, 1},
{2, 3},
{3, 4},
},
nodes = {
-- 1
{
id = 'xl_roof_storage',
icon = 'ROOF-STORAGE.png',
link_to = 'XL Roof Storage',
label = 'XL Roof Storage',
slot = {1, 2},
},
-- 2
{
id = 'side_storage',
icon = 'SIDE-STORAGE.png',
link_to = 'Side Storage',
label = 'Side Storage',
slot = {2, 1},
},
-- 3
{
id = 'a_trunk_in_the_trunk',
icon = 'STEEL-SHEET_Inverted.png',
link_to = 'A Trunk In The Trunk',
label = 'A Trunk in the Trunk',
slot = {2, 2},
},
-- 4
{
id = 'augmented_trunk_storage',
icon = 'TRUNK-T3.png',
link_to = 'Augmented Trunk Storage',
label = 'Augmented Trunk Storage',
slot = {2, 3},
},
},
},
engines = {
canvas_slots = {2, 3},
edges = {
{2, 3},
{3, 1},
{3, 4},
},
nodes = {
-- 1
{
id = 'amp_engine',
icon = 'AMP-Icon.png',
link_to = 'AMP Engine',
label = 'AMP Engine',
slot = {1, 3},
},
-- 2
{
id = 'carbureted_engine',
icon = 'Carbureted_Icon.png',
link_to = 'Carbureted Engine',
label = 'Carbureted Engine',
slot = {2, 1},
},
-- 3
{
id = 'turbolight_engine',
icon = 'Turbolight_Icon.png',
link_to = 'Turbolight Engine',
label = 'Turbolight Engine',
slot = {2, 2},
},
-- 4
{
id = 'lim_chipped_engine',
icon = 'LIM-Chipped-Icon.png',
link_to = 'LIM-Chipped Engine',
label = 'LIM-Chipped Engine',
slot = {2, 3},
},
},
},
expansion_racks = {
canvas_slots = {3, 5},
edges = {
{1, 2},
{3, 4},
{4, 1},
{4, 5},
{5, 6},
{5, 7},
{7, 8},
},
nodes = {
-- 1
{
id = 'seat_rack_1',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Seat Rack',
label = 'Seat Rack',
slot = {1, 3},
},
-- 2
{
id = 'seat_rack_2',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Seat Rack',
label = 'Seat Rack',
slot = {1, 4},
},
-- 3
{
id = 'side_rack_1',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Side Rack',
label = 'Side Rack',
slot = {2, 1},
},
-- 4
{
id = 'side_rack_2',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Side Rack',
label = 'Side Rack',
slot = {2, 2},
},
-- 5
{
id = 'side_rack_3',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Side Rack',
label = 'Side Rack',
slot = {2, 3},
},
-- 6
{
id = 'side_rack_4',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Side Rack',
label = 'Side Rack',
slot = {2, 4},
},
-- 7
{
id = 'roof_rack_1',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Roof Rack',
label = 'Roof Rack',
slot = {3, 4},
},
-- 8
{
id = 'roof_rack_2',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Roof Rack',
label = 'Roof Rack',
slot = {3, 5},
},
},
},
fuel = {
canvas_slots = {3, 5},
edges = {
{2, 3},
{3, 4},
{3, 7},
{4, 1},
{4, 5},
{5, 6},
},
nodes = {
-- 1
{
id = 'leak_resistant_fuel_tank',
icon = 'LEAK-RESIST-FUEL.png',
link_to = 'Leak-Resistant Fuel Tank',
label = 'Leak-Resistant Fuel Tank',
slot = {1, 4},
},
-- 2
{
id = 'large_fuel_can',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Large Fuel Can',
label = 'Large Fuel Can',
slot = {2, 1},
},
-- 3
{
id = 'side_fuel_tank',
icon = 'SIDE-FUEL.png',
link_to = 'Side Fuel Tank',
label = 'Side Fuel Tank',
slot = {2, 2},
},
-- 4
{
id = 'backseat_tank',
icon = 'BACKSEAT-FUEL.png',
link_to = 'Backseat Tank',
label = 'Backseat Tank',
slot = {2, 3},
},
-- 5
{
id = 'backseat_tank',
icon = 'EXPANDED-BACKSEAT-FUEL.png',
link_to = 'Expanded Backseat Tank',
label = 'Expanded Backseat Tank',
slot = {2, 4},
},
-- 6
{
id = 'gas_reservoir',
icon = 'ROOF-FUEL.png',
link_to = 'Gas Reservoir',
label = 'Gas Reservoir',
slot = {2, 5},
},
-- 7
{
id = 'fuel_synthesizer',
icon = 'FUEL-GENERATOR.png',
link_to = 'Fuel Synthesizer',
label = 'Fuel Synthesizer',
slot = {3, 3},
},
},
},
-- Scanning Antenna, Matter Deconstructor, Expanded Locker, Pneumatic Locker, Parts Lockers,
-- Outfitting Station, Vargas Auto-Pac-Vac, Rapid Refill Pump, Experimental Charging Station,
-- Improved Antenna, Advanced Antenna, Incident Board, Junction Re-Stabilizer, Junction Bypass,
-- Matter Regenerator, Investigator Module, Analysis Module, Advanced Workbench,
-- Expanded Matter Regenerator, Repair Station, Detailing Station, F.A.X. Machine,
-- Athletic Stimulation Station, Deco-Vend, Fish Tank, Smart Matter Deconstructor
garage = {
canvas_slots = {8, 6},
edges = {},
nodes = {},
},
lights = {
canvas_slots = {6, 4},
edges = {
{3, 1},
{3, 4},
{5, 2},
{5, 6},
{6, 3},
{8, 9},
{9, 7},
{9, 10},
{9, 13},
{11, 12},
{12, 14},
},
nodes = {
-- 1
{
id = 'biolantern',
icon = 'Biolantern.png',
no_icon_padding = true,
link_to = 'Biolantern',
label = 'Biolantern',
slot = {1, 3},
},
-- 2
{
id = 'crude_flashlight',
icon = 'Crude_Flashlight.png',
no_icon_padding = true,
link_to = 'Crude Flashlight',
label = 'Crude Flashlight',
slot = {2, 2},
},
-- 3
{
id = 'bioflare',
icon = 'Bioflare.png',
no_icon_padding = true,
link_to = 'Bioflare',
label = 'Bioflare',
slot = {2, 3},
},
-- 4
{
id = 'bioflare',
icon = 'Bioflare-Gun.png',
no_icon_padding = true,
link_to = 'Bioflare Gun',
label = 'Bioflare Gun',
slot = {2, 4},
},
-- 5
{
id = 'relightable_flare',
icon = 'Relightable_Flare.png',
no_icon_padding = true,
link_to = 'Relightable Flare',
label = 'Relightable Flare',
slot = {3, 1},
},
-- 6
{
id = 'flare_gun',
icon = 'Flare_Gun.png',
no_icon_padding = true,
link_to = 'Flare Gun',
label = 'Flare Gun',
slot = {3, 2},
},
-- 7
{
id = 'insulated_headlight',
icon = 'Insulated_Headlight_Icon.png',
link_to = 'Insulated Headlight',
label = 'Insulated Headlight',
slot = {3, 3},
},
-- 8
{
id = 'crude_headlight',
icon = 'Crude_Headlight_Icon.png',
link_to = 'Crude Headlight',
label = 'Crude Headlight',
slot = {4, 1},
},
-- 9
{
id = 'headlight',
icon = 'Headlight_Icon.png',
link_to = 'Headlight',
label = 'Headlight',
slot = {4, 2},
},
-- 10
{
id = 'reinforced_headlight',
icon = 'PHYS-LIGHT.png',
link_to = 'Reinforced Headlight',
label = 'Reinforced Headlight',
slot = {4, 3},
},
-- 11
{
id = 'side_floodlights',
icon = 'SIDE-LIGHT.png',
link_to = 'Side Floodlights',
label = 'Side Floodlights',
slot = {5, 1},
},
-- 12
{
id = 'roof_floodlights',
icon = 'ROOF-ARRAY.png',
link_to = 'Roof Floodlights',
label = 'Roof Floodlights',
slot = {5, 2},
},
-- 13
{
id = 'bio_headlight',
icon = 'BIO-LIGHT.png',
link_to = 'Bio Headlight',
label = 'Bio Headlight',
slot = {5, 3},
},
-- 14
{
id = 'auto_tracking_spotlight',
icon = 'ROOF-LIGHT.png',
link_to = 'Auto Tracking Spotlight',
label = 'Auto Tracking Spotlight',
slot = {6, 3},
},
},
},
refine = {
canvas_slots = {1, 6},
edges = {
{1, 2},
{2, 3},
{3, 4},
{4, 5},
{5, 6},
},
nodes = {
-- 1
{
id = 'gear',
icon = 'GEAR.png',
link_to = 'Gear',
label = 'Gear',
slot = {1, 1},
},
-- 2
{
id = 'bulb',
icon = 'BULB.png',
link_to = 'Bulb',
label = 'Bulb',
slot = {1, 2},
},
-- 3
{
id = 'steel_sheet',
icon = 'STEEL-SHEET_Inverted.png',
link_to = 'Steel Sheet',
label = 'Steel Sheet',
slot = {1, 3},
},
-- 4
{
id = 'circuit_board',
icon = 'BREADBOARD.png',
link_to = 'Circuit Board',
label = 'Circuit Board',
slot = {1, 4},
},
-- 5
{
id = 'carbonfiberglass',
icon = 'CARBON-FIBREGLASS.png',
link_to = 'Carbonfiberglass',
label = 'Carbonfiberglass',
slot = {1, 5},
},
-- 6
{
id = 'lim_chip',
icon = 'LIM-CHIP.png',
link_to = 'LIM Chip',
label = 'LIM Chip',
slot = {1, 6},
},
},
},
survival_tools = {
canvas_slots = {6, 3},
edges = {
{2, 1},
{4, 2},
{4, 5},
{5, 3},
{7, 8},
{7, 11},
{8, 6},
{8, 9},
{10, 13},
{10, 14},
{11, 12},
{14, 15},
},
nodes = {
-- 1
{
id = 'olympium_torch',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Olympium Torch',
label = 'Olympium Torch',
slot = {1, 3},
},
-- 2
{
id = 'blowtorch',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Blowtorch',
label = 'Blowtorch',
slot = {2, 2},
},
-- 3
{
id = 'electricians_kit',
icon = 'Electricians_Kit.png',
link_to = 'Electrician\'s Kit',
label = 'Electrician\'s Kit',
slot = {2, 3},
},
-- 4
{
id = 'repair_putty',
icon = 'REPAIR-PUTTY.png',
link_to = 'Repair Putty',
label = 'Repair Putty',
slot = {3, 1},
},
-- 5
{
id = 'light_replacement_kit',
icon = 'Light_Replacement_Kit.png',
link_to = 'Light Replacement Kit',
label = 'Light Replacement Kit',
slot = {3, 2},
},
-- 6
{
id = 'thermal_vacuum',
icon = 'Thermal_Vacuum.png',
link_to = 'Thermal Vacuum',
label = 'Thermal Vacuum',
slot = {3, 3},
},
-- 7
{
id = 'scrapper',
icon = 'Scrapper.png',
link_to = 'Scrapper',
label = 'Scrapper',
slot = {4, 1},
},
-- 8
{
id = 'hand_vac',
icon = 'Hand-Vac.png',
link_to = 'Hand-Vac',
label = 'Hand-Vac',
slot = {4, 2},
},
-- 9
{
id = 'plasma_scrapper',
icon = 'Plasma_Scrapper.png',
link_to = 'Plasma Scrapper',
label = 'Plasma Scrapper',
slot = {4, 3},
},
-- 10
{
id = 'prybar',
icon = 'Prybar.png',
link_to = 'Prybar',
label = 'Prybar',
slot = {5, 1},
},
-- 11
{
id = 'liberator',
icon = 'Liberator.png',
link_to = 'Liberator',
label = 'Liberator',
slot = {5, 2},
},
-- 12
{
id = 'liberator_mk2',
icon = 'PLACEHOLDER_PROTOTYPE.png',
link_to = 'Liberator Mk. 2',
label = 'Liberator Mk. 2',
slot = {5, 3},
},
-- 13
{
id = 'anchor_radar',
icon = 'Anchor_Radar.png',
link_to = 'Anchor Radar',
label = 'Anchor Radar',
slot = {6, 1},
},
-- 14
{
id = 'impact_hammer',
icon = 'Impact_Hammer.png',
link_to = 'Impact Hammer',
label = 'Impact Hammer',
slot = {6, 2},
},
-- 15
{
id = 'magnetic_hammer',
icon = 'Magnetic_Hammer.png',
link_to = 'Magnetic Hammer',
label = 'Magnetic Hammer',
slot = {6, 3},
},
},
},
utilities = {
canvas_slots = {3, 5},
edges = {
{4, 1},
{4, 5},
{4, 9},
{5, 6},
{5, 10},
{6, 2},
{6, 7},
{6, 11},
{7, 3},
{7, 8},
{7, 12},
},
nodes = {
-- 1
{
id = 'the_auto_parker',
icon = 'PARKING-MANOUVER.png',
link_to = 'The Auto Parker',
label = 'The Auto Parker',
slot = {1, 2},
},
-- 2
{
id = 'the_lazarus_device',
icon = 'LIFESAVER.png',
link_to = 'The Lazarus Device',
label = 'The Lazarus Device',
slot = {1, 4},
},
-- 3
{
id = 'chrono_dilator',
icon = 'TIME-MANOUVER.png',
link_to = 'Chrono Dilator',
label = 'Chrono Dilator',
slot = {1, 5},
},
-- 4
{
id = 'limpulse_emitter',
icon = 'PHYS-WAVE-SHIELD.png',
link_to = 'Limpulse Emitter',
label = 'Limpulse Emitter',
slot = {2, 1},
},
-- 5
{
id = 'jump_jacks',
icon = 'JUMP-MANOUVER.png',
link_to = 'Jump Jacks',
label = 'Jump Jacks',
slot = {2, 2},
},
-- 6
{
id = 'ion_shield',
icon = 'ROOF-RAD-SHIELD.png',
link_to = 'Ion Shield',
label = 'Ion Shield',
slot = {2, 3},
},
-- 7
{
id = 'mobile_workbench',
icon = 'BENCH-T1.png',
link_to = 'Mobile Workbench',
label = 'Mobile Workbench',
slot = {2, 4},
},
-- 8
{
id = 'magnetic_bumper',
icon = 'MAGNET-BUMPER.png',
link_to = 'Magnetic Bumper',
label = 'Magnetic Bumper',
slot = {2, 5},
},
-- 9
{
id = 'resource_radar',
icon = 'RESOURCE-SCANNER.png',
link_to = 'Resource Radar',
label = 'Resource Radar',
slot = {3, 2},
},
-- 10
{
id = 'juke_jets',
icon = 'SIDE-THRUSTERS-MANOUVER.png',
link_to = 'Juke Jets',
label = 'Juke Jets',
slot = {3, 3},
},
-- 11
{
id = 'nitro_boost',
icon = 'BOOST-MANOUVER.png',
link_to = 'Nitro Boost',
label = 'Nitro Boost',
slot = {3, 4},
},
-- 12
{
id = 'anti_grav_emitter',
icon = 'GRAVITY-MANOUVER.png',
link_to = 'Anti-Grav Emitter',
label = 'Anti-Grav Emitter',
slot = {3, 5},
},
},
},
wheels = {
canvas_slots = {3, 5},
edges = {
{2, 3},
{3, 4},
{4, 1},
{4, 5},
{4, 7},
{5, 6},
},
nodes = {
-- 1
{
id = 'puncture_proof_tire',
icon = 'PUNCTURE-RESISTANT-TIRE.png',
link_to = 'Puncture-Proof Tire',
label = 'Puncture-Proof Tire',
slot = {1, 4},
},
-- 2
{
id = 'spare_tire',
icon = 'Spare_Tire_Icon.png',
link_to = 'Spare Tire',
label = 'Spare Tire',
slot = {2, 1},
},
-- 3
{
id = 'summer_tire',
icon = 'Summer_Tire_Icon.png',
link_to = 'Summer Tire',
label = 'Summer Tire',
slot = {2, 2},
},
-- 4
{
id = 'offroad_tire',
icon = 'OFFROAD-TIRE.png',
link_to = 'Offroad Tire',
label = 'Offroad Tire',
slot = {2, 3},
},
-- 5
{
id = 'all_terrain_tire',
icon = 'ADAPTIVE-TIRE.png',
link_to = 'All-Terrain Tire',
label = 'All-Terrain Tire',
slot = {2, 4},
},
-- 6
{
id = 'power_grip_tire',
icon = 'POWER-GRIP-TIRE.png',
link_to = 'Power Grip Tires',
label = 'Power Grip Tires',
slot = {2, 5},
},
-- 7
{
id = 'paddle_tire',
icon = 'WATER-TIRE.png',
link_to = 'Paddle Tire',
label = 'Paddle Tire',
slot = {3, 4},
},
},
},
}
function css_px( n )
return string.format('%spx', n)
end
-- returns inverted order because cols produce x, rows produce y
function get_canvas_size( tab )
return {
p.consts.canvas_padding * 2 + tab.canvas_slots[2] * p.consts.node_size[2] + (tab.canvas_slots[2] - 1) * p.consts.node_spacing[2],
p.consts.canvas_padding * 2 + tab.canvas_slots[1] * p.consts.node_size[1] + (tab.canvas_slots[1] - 1) * p.consts.node_spacing[1],
}
end
-- returns inverted order because cols produce x, rows produce y
function get_node_anchor_pos( node_slot )
return {
p.consts.canvas_padding + (node_slot[2] - 1) * (p.consts.node_size[2] + p.consts.node_spacing[2]),
p.consts.canvas_padding + (node_slot[1] - 1) * (p.consts.node_size[1] + p.consts.node_spacing[1]),
}
end
-- does not return inverted order because it's already been inverted by get_node_anchor_pos
function get_node_graph_anchor_pos( node_slot )
local anchor_pos = get_node_anchor_pos(node_slot)
local offset_x = p.consts.node_size[1] / 2
local offset_y = offset_x - p.consts.node_padding[1] - p.consts.icon_edge_thickness
return { anchor_pos[1] + offset_x, anchor_pos[2] + offset_y }
end
function render_node_label( html_ref, node )
return html_ref
:tag('div')
:css({
['font-family'] = 'var(--font-family-monospace)',
['font-size'] = css_px(p.consts.label_font_size),
['line-height'] = '1em',
['color'] = 'white',
['width'] = css_px(p.consts.node_icon_container_size),
['text-align'] = 'end'
})
:wikitext(node.label)
:done()
end
function render_node_icon( html_ref, node )
return html_ref
:tag('div')
:css({
['position'] = 'relative',
['border'] = '6px double white',
['width'] = css_px(p.consts.node_icon_container_size),
['height'] = css_px(p.consts.node_icon_container_size),
['padding'] = node.no_icon_padding and '0px' or css_px(p.consts.node_icon_padding),
})
:wikitext(string.format(p.consts.wikitext_template_link, node.link_to))
:newline()
:wikitext(string.format(p.consts.wikitext_template_icon, node.icon, p.consts.node_icon_size + (node.no_icon_padding and p.consts.node_icon_padding * 2 or 0)))
:done()
end
function render_node( html_ref, node )
local res = html_ref
local anchor_pos = get_node_anchor_pos(node.slot)
local padding = p.consts.node_padding
res = html_ref
:tag('div')
:css({
['position'] = 'absolute',
['padding'] = string.format('%spx %spx %spx %spx', padding[1], padding[2], padding[3], padding[4]),
['width'] = css_px(p.consts.node_size[1]),
['height'] = css_px(p.consts.node_size[2]),
['background-color'] = p.consts.bg_color,
['transform'] = string.format('translate(%spx, %spx)', anchor_pos[1], anchor_pos[2])
})
res = render_node_icon(res, node)
res = render_node_label(res, node)
return res:done()
end
function render_edge( html_ref, node_slot_1, node_slot_2 )
local pos_1 = get_node_graph_anchor_pos(node_slot_1)
local pos_2 = get_node_graph_anchor_pos(node_slot_2)
local delta_x = pos_2[1] - pos_1[1]
local delta_y = pos_2[2] - pos_1[2]
local edge_len = (delta_x ^ 2 + delta_y ^ 2) ^ 0.5
local center_tgt = { pos_1[1] + delta_x / 2, pos_1[2] + delta_y / 2 }
local center_orig = { edge_len / 2, 0 }
local translate_by = { center_tgt[1] - center_orig[1], center_tgt[2] - center_orig[2] }
local rotate_by = math.atan(delta_y / delta_x)
return html_ref
:tag('div')
:css({
['position'] = 'absolute',
['width'] = css_px(edge_len),
['height'] = css_px(p.consts.icon_edge_thickness),
['background-color'] = 'white',
['transform'] = string.format('translate(%spx, %spx) rotate(%srad)', translate_by[1], translate_by[2], rotate_by)
})
:done()
end
function p.main(frame)
local tab_name = frame.args.tab
local tab = p.tabs[tab_name]
local tab_canvas_size = get_canvas_size(tab)
local viewport_size = {
tab_canvas_size[1] + 10,
math.min(tab_canvas_size[2], 390) + 10
}
local html_ref = mw.html.create('div')
:css({
['max-width'] = '100%',
['width'] = css_px(viewport_size[1]),
['height'] = css_px(viewport_size[2]),
['overflow'] = 'auto'
})
:tag('div')
:css({
['position'] = 'relative',
['width'] = css_px(tab_canvas_size[1]),
['height'] = css_px(tab_canvas_size[2]),
['background-color'] = p.consts.bg_color
})
for k, v in pairs(tab.edges) do
html_ref = render_edge(html_ref, tab.nodes[v[1]].slot, tab.nodes[v[2]].slot)
end
for k, v in pairs(tab.nodes) do
html_ref = render_node(html_ref, v)
end
return tostring(html_ref:allDone())
end
return p