"use strict" /* global action_button, data, scroll_into_view, send_action, view */ function toggle_pieces() { document.getElementById("pieces").classList.toggle("hide") } const SCALE = 1.8 const FLN = 0 const GOV = 1 const FR_XX = 0 const FR_X = 1 const EL_X = 2 const AL_X = 3 const POL = 4 const FAILEK = 5 const BAND = 6 const CADRE = 7 const FRONT = 8 var FRANCE = data.locations["FRANCE"] var MOROCCO = data.locations["MOROCCO"] var TUNISIA = data.locations["TUNISIA"] var ORAN = data.locations["ORAN"] var ALGIERS = data.locations["ALGIERS"] var CONSTANTINE = data.locations["CONSTANTINE"] const OUT_OF_PLAY = 0 const DEPLOY = 1 const ELIMINATED = 2 const UG = 0 const OPS = 1 const PTL = 2 const OC = 3 const BOX_NAMES = ["UG", "OPS", "PTL", "OC"] const area_type_names = [ "none", "rural", "urban", "remote", "country" ] // const area_count = 31 const unit_count = 120 function is_gov_unit(u) { return (u >= 0 && u <= 39) } function is_fln_unit(u) { return (u >= 40 && u <= 119) } function set_has(set, item) { if (!set) return false let a = 0 let b = set.length - 1 while (a <= b) { let m = (a + b) >> 1 let x = set[m] if (item < x) b = m - 1 else if (item > x) a = m + 1 else return true } return false } // :r !python3 tools/genlayout.py // BEGIN LAYOUT DATA const LAYOUT = { "Laghouat-OC": [848, 974], "Laghouat-PTL": [650, 1000], "Laghouat-OPS": [807, 884], "Laghouat-UG": [632, 898], "Laghouat-MK": [734, 932], "Ain Sefra-OC": [466, 1010], "Ain Sefra-PTL": [366, 1011], "Ain Sefra-OPS": [486, 929], "Ain Sefra-UG": [263, 1001], "Ain Sefra-MK": [403, 952], "Mascara-OC": [524, 814], "Mascara-PTL": [454, 840], "Mascara-OPS": [524, 750], "Mascara-UG": [455, 767], "Mascara-MK": [510, 700], "Saida-OC": [379, 879], "Saida-PTL": [304, 898], "Saida-OPS": [364, 763], "Saida-UG": [296, 784], "Saida-MK": [360, 822], "Mecheria-OC": [221, 912], "Mecheria-PTL": [157, 930], "Mecheria-OPS": [213, 818], "Mecheria-UG": [153, 829], "Mecheria-MK": [205, 867], "Mostaganem-OC": [495, 619], "Mostaganem-PTL": [437, 568], "Mostaganem-OPS": [474, 436], "Mostaganem-UG": [419, 469], "Mostaganem-MK": [485, 513], "Sidi Bel Abbes-OC": [369, 640], "Sidi Bel Abbes-PTL": [301, 681], "Sidi Bel Abbes-OPS": [339, 526], "Sidi Bel Abbes-UG": [252, 533], "Sidi Bel Abbes-MK": [285, 625], "Tlemcen-OC": [193, 724], "Tlemcen-PTL": [122, 704], "Tlemcen-OPS": [183, 652], "Tlemcen-UG": [112, 630], "Tlemcen-MK": [164, 577], "Orleansville-OC": [630, 495], "Orleansville-PTL": [565, 460], "Orleansville-OPS": [622, 420], "Orleansville-UG": [557, 381], "Orleansville-MK": [570, 530], "Medea-OC": [752, 492], "Medea-PTL": [702, 539], "Medea-OPS": [769, 427], "Medea-UG": [702, 432], "Medea-MK": [700, 485], "Ain Qussera-OC": [698, 795], "Ain Qussera-PTL": [614, 750], "Ain Qussera-OPS": [700, 643], "Ain Qussera-UG": [602, 662], "Ain Qussera-MK": [685, 695], "Sidi Aissa-OC": [862, 745], "Sidi Aissa-PTL": [793, 783], "Sidi Aissa-OPS": [872, 643], "Sidi Aissa-UG": [788, 614], "Sidi Aissa-MK": [800, 680], "Bougie-OC": [1031, 405], "Bougie-PTL": [972, 402], "Bougie-OPS": [1035, 345], "Bougie-UG": [975, 343], "Bougie-MK": [1005, 450], "Bordj Bou Arreridj-OC": [894, 548], "Bordj Bou Arreridj-PTL": [838, 549], "Bordj Bou Arreridj-OPS": [895, 490], "Bordj Bou Arreridj-UG": [838, 490], "Bordj Bou Arreridj-MK": [952, 505], "Tizi Ouzou-OC": [900, 412], "Tizi Ouzou-PTL": [842, 412], "Tizi Ouzou-OPS": [905, 354], "Tizi Ouzou-UG": [840, 354], "Tizi Ouzou-MK": [905, 302], "Biskra-OC": [1148, 995], "Biskra-PTL": [1006, 970], "Biskra-OPS": [1218, 928], "Biskra-UG": [989, 859], "Biskra-MK": [1090, 904], "Batna-OC": [1287, 861], "Batna-PTL": [1145, 813], "Batna-OPS": [1306, 783], "Batna-UG": [1115, 739], "Batna-MK": [1218, 777], "Tebessa-OC": [1333, 706], "Tebessa-PTL": [1251, 690], "Tebessa-OPS": [1369, 643], "Tebessa-UG": [1178, 640], "Tebessa-MK": [1271, 628], "Barika-OC": [1029, 716], "Barika-PTL": [955, 739], "Barika-OPS": [1084, 622], "Barika-UG": [964, 596], "Barika-MK": [1001, 657], "Souk Ahras-OC": [1388, 552], "Souk Ahras-PTL": [1331, 551], "Souk Ahras-OPS": [1393, 491], "Souk Ahras-UG": [1329, 489], "Souk Ahras-MK": [1383, 401], "Constantine-OC": [1229, 224], "Constantine-PTL": [1172, 224], "Constantine-OPS": [1229, 165], "Constantine-UG": [1172, 165], "Constantine-MK": [1200, 280], "Philippeville-OC": [1246, 541], "Philippeville-PTL": [1253, 457], "Philippeville-OPS": [1308, 403], "Philippeville-UG": [1252, 345], "Philippeville-MK": [1322, 316], "Setif-OC": [1141, 542], "Setif-PTL": [1045, 524], "Setif-OPS": [1166, 377], "Setif-UG": [1106, 409], "Setif-MK": [1119, 473], "Algiers-OC": [743, 239], "Algiers-PTL": [686, 239], "Algiers-OPS": [743, 180], "Algiers-UG": [686, 180], "Algiers-MK": [715, 295], "Oran-OC": [317, 370], "Oran-PTL": [260, 370], "Oran-OPS": [317, 311], "Oran-UG": [260, 311], "Oran-MK": [290, 425], "Morocco-UG": [87, 1007], "Tunisia-UG": [1415, 953], "France-UG": [985, 175], "France-MK": [940, 110], } // END LAYOUT DATA let ui = { status: document.getElementById("status"), player: [ document.getElementById("role_FLN"), document.getElementById("role_Government"), ], ap: document.querySelector("#role_FLN .role_ap"), psl: [ document.querySelector("#role_FLN .role_psl"), document.querySelector("#role_Government .role_psl"), ], markers: { turn: document.getElementById("turn_now"), fln_psl: document.getElementById("fln_psl"), fln_ap: document.getElementById("fln_ap"), gov_psl: document.getElementById("gov_psl"), air_avail: document.getElementById("air_avail"), air_max: document.getElementById("air_max"), helo_avail: document.getElementById("helo_avail"), helo_max: document.getElementById("helo_max"), naval: document.getElementById("naval"), border_zone: document.getElementById("border_zone"), }, container: document.getElementById("pieces"), tracker: [], drm: [], areas: [], areas_u: [], area_markers: [], boxes: [], locations: [], zones: [], units: [], fln_supply: document.getElementById("fln_supply"), gov_supply: document.getElementById("gov_supply"), eliminated: document.getElementById("eliminated"), } const LAYOUT_BOX = [] // remote (1 bit), terrorized (1 bit), gov control (1 bit), fln control (1 bit) const AREA_FLN_CONTROL_SHIFT = 0 const AREA_FLN_CONTROL_MASK = 1 << AREA_FLN_CONTROL_SHIFT const AREA_GOV_CONTROL_SHIFT = 1 const AREA_GOV_CONTROL_MASK = 1 << AREA_GOV_CONTROL_SHIFT const AREA_TERRORIZED_SHIFT = 2 const AREA_TERRORIZED_MASK = 1 << AREA_TERRORIZED_SHIFT const AREA_REMOTE_SHIFT = 3 const AREA_REMOTE_MASK = 1 << AREA_REMOTE_SHIFT // area control function is_area_fln_control(l) { return (view.areas[l] & AREA_FLN_CONTROL_MASK) === AREA_FLN_CONTROL_MASK } function is_area_gov_control(l) { return (view.areas[l] & AREA_GOV_CONTROL_MASK) === AREA_GOV_CONTROL_MASK } // terrorized function is_area_terrorized(l) { return (view.areas[l] & AREA_TERRORIZED_MASK) === AREA_TERRORIZED_MASK } // remote function is_area_remote(l) { return (view.areas[l] & AREA_REMOTE_MASK) === AREA_REMOTE_MASK } function is_area_country(l) { return data.areas[l].type === COUNTRY } function is_area_oas_active(l) { return view.oas === l } // === UNIT STATE === // location (8 bits), op box (2 bits), dispersed (1 bit), airmobile (1 bit), neutralized (1 bit) const UNIT_NEUTRALIZED_SHIFT = 0 const UNIT_NEUTRALIZED_MASK = 1 << UNIT_NEUTRALIZED_SHIFT const UNIT_AIRMOBILE_SHIFT = 1 const UNIT_AIRMOBILE_MASK = 1 << UNIT_AIRMOBILE_SHIFT const UNIT_DISPERSED_SHIFT = 2 const UNIT_DISPERSED_MASK = 1 << UNIT_DISPERSED_SHIFT const UNIT_BOX_SHIFT = 3 const UNIT_BOX_MASK = 3 << UNIT_BOX_SHIFT const UNIT_LOC_SHIFT = 5 const UNIT_LOC_MASK = 255 << UNIT_LOC_SHIFT function is_unit_neutralized(u) { return (view.units[u] & UNIT_NEUTRALIZED_MASK) === UNIT_NEUTRALIZED_MASK } function unit_type(u) { return data.units[u].type } function unit_loc(u) { return (view.units[u] & UNIT_LOC_MASK) >> UNIT_LOC_SHIFT } function unit_box(u) { return (view.units[u] & UNIT_BOX_MASK) >> UNIT_BOX_SHIFT } function is_unit_airmobile(u) { return (view.units[u] & UNIT_AIRMOBILE_MASK) === UNIT_AIRMOBILE_MASK } function is_unit_dispersed(u) { return (view.units[u] & UNIT_DISPERSED_MASK) === UNIT_DISPERSED_MASK } function is_unit_contacted(u) { return set_has(view.contacted, u) } function is_unit_eliminated(u) { return unit_loc(u) === ELIMINATED } function is_unit_action(unit) { return !!(view.actions && view.actions.unit && view.actions.unit.includes(unit)) } function is_unit_selected(unit) { if (Array.isArray(view.selected)) return view.selected.includes(unit) return view.selected === unit } function is_loc_selected(loc) { if (Array.isArray(view.selected_loc)) return view.selected_loc.includes(loc) return view.selected_loc === loc } function is_loc_action(x) { return !!(view.actions && view.actions.loc && view.actions.loc.includes(x)) } // === STACK LAYOUT === var stack_cache = [] var focus = null document.querySelector("#map").addEventListener("mousedown", evt => { if (evt.button === 0) blur_stack() }) function focus_stack(stack) { if (focus !== stack) { focus = stack update_map() return !stack || stack.length <= 1 } return true } function blur_stack() { if (focus !== null) { focus = null } update_map() } function on_click_unit(evt) { if (evt.button === 0) { event.stopPropagation() if (focus_stack(evt.target.my_stack)) send_action('unit', evt.target.my_id) } } function on_click_loc(evt) { if (evt.button === 0) { if (send_action('loc', evt.target.my_id)) evt.stopPropagation() } } function on_focus_loc(evt) { document.getElementById("status").textContent = data.areas[evt.target.my_id].full_name } function on_focus_unit(evt) { document.getElementById("status").textContent = data.units[evt.target.my_id].full_name } function on_blur(_evt) { document.getElementById("status").textContent = "" } let LAYOUT_TRACK = [] let track_count = Array(100).fill(0) function layout_track(track, e) { let n = track_count[track] let x = LAYOUT_TRACK[track][0] - 20 let y = LAYOUT_TRACK[track][1] - 20 let dx = 0 let dy = 41 const DIAG = 24 if (track === 0) dx = DIAG, dy = DIAG else if (track === 29) dx = -DIAG, dy = DIAG else if (track === 50) dx = -DIAG, dy = -DIAG else if (track === 79) dx = DIAG, dy = -DIAG else if (track >= 30 && track <= 49) dx = -41, dy = 0 else if (track >= 51 && track <= 78) dx = 0, dy = -41 else if (track >= 80 && track <= 99) dx = 41, dy = 0 e.style.left = x + (dx * n) + "px" e.style.top = y + (dy * n) + "px" e.style.zIndex = n track_count[track] = n + 1 } function layout_stack(loc_id, box_id) { let stack_id = loc_id * 4 + box_id let stack = stack_cache[stack_id] if (!stack) stack = stack_cache[stack_id] = [] stack.length = 0 for (let u = 0; u < unit_count; ++u) { let loc = unit_loc(u) let box = loc < 6 ? 0 : unit_box(u) if (loc == loc_id && box === box_id) stack.push(ui.units[u]) } let z = 1 let x = LAYOUT_BOX[loc_id * 4 + box_id][0] - 22 let y = LAYOUT_BOX[loc_id * 4 + box_id][1] - 22 let dx = 4 let dy = -4 if (stack === focus) { if (loc_id === MOROCCO) { dx = 0 dy = -45 } else if (loc_id === TUNISIA) { dx = 0 dy = -45 } else { switch (box_id) { case UG: dx = 0, dy = -45; break case PTL: dx = -45, dy = 0; break case OPS: dx = 45, dy = 0; break case OC: dx = 0, dy = 45; break } } } else { if (loc_id === MOROCCO) { dx = 4 dy = -14 } else if (loc_id === TUNISIA) { dx = -4 dy = -14 } else if (stack.length < 4) { dx = 13 dy = -13 } else if (stack.length < 8) { dx = 8 dy = -8 } } // TODO: clamp x,y to fit on map for (let e of stack) { e.my_stack = stack e.style.left = x + "px" e.style.top = y + "px" if (is_unit_selected(e.my_id)) e.style.zIndex = 100 + z++ else e.style.zIndex = z++ x += dx y += dy } } // === BUILD UI === let on_init_once = false function build_units() { function build_unit(u) { let side = is_gov_unit(u) ? "gov" : "fln" let elt = ui.units[u] = document.createElement("div") let klass = data.units[u].class elt.className = `counter unit ${side} u${u} ${klass}` elt.addEventListener("mousedown", on_click_unit) elt.addEventListener("mouseenter", on_focus_unit) elt.addEventListener("mouseleave", on_blur) elt.my_id = u } for (let u = 0; u < unit_count; ++u) { build_unit(u) } } function create_tracker(i, x, y) { let e = ui.tracker[i] = document.createElement("div") if (i % 5 === 0) e.className = "box track5" else e.className = "box track1" e.style.left = x + "px" e.style.top = y + "px" e.textContent = i document.getElementById("decor").appendChild(e) } const DRM_X = 370 const DRM_Y = 140 const DRM_DX = 55 const DRM_DY = 0 function create_border_zone(i, label) { let e = document.createElement("div") e.className = "box drm_track" e.style.left = (DRM_X + i * DRM_DX) + "px" e.style.top = (DRM_Y + i * DRM_DY) + "px" e.textContent = label document.getElementById("boxes").appendChild(e) } const COUNTRY = 4 function create_area(i, _area_id, area_name, _type) { let area_name_css = area_name.replaceAll(' ', '-') let e = ui.areas[i] = document.querySelector(`#svgmap #${area_name_css}`) e.my_id = i e.addEventListener("mousedown", on_click_loc) e.addEventListener("mouseenter", on_focus_loc) e.addEventListener("mouseleave", on_blur) } function create_area_u(i, sel) { let e = document.querySelector(sel) e.my_id = i e.addEventListener("mousedown", on_click_loc) e.addEventListener("mouseenter", on_focus_loc) e.addEventListener("mouseleave", on_blur) return e } function create_area_markers(i, area_id, area_name) { const box_w = 150 const box_h = 50 let layout = LAYOUT[area_name + '-MK'] if (!layout) return let [x, y] = layout let e = document.createElement("div") e.id = `area-marker-${area_id}` e.className = "area_markers" e.style.left = x - (box_w / 2) + "px" e.style.top = y - (box_h / 2) + "px" e.style.width = box_w + "px" e.style.height = box_h + "px" document.getElementById("boxes").appendChild(e) ui.area_markers[i] = {} for (let marker of ['remote', 'fln_control', 'gov_control', 'terror', 'oas_active']) { let em = ui.area_markers[i][marker] = document.createElement("div") em.id = `area-marker-${i}-${marker}` em.className = `counter ${marker} hide` e.appendChild(em) } } const box_type_w = [ 38*2+6, 30*2+6, 27*2, 27*2 ] const box_type_h = [ 30*2+6, 30*2+6, 27*2, 27*2 ] function create_box(i, area_id, area_name, box_id, show) { const box_w = box_type_w[box_id] const box_h = box_type_h[box_id] let [x, y] = LAYOUT[area_name + '-' + BOX_NAMES[box_id]] LAYOUT_BOX[i * 4 + box_id] = [x, y] if (show) { let sh = document.createElement("div") sh.className = "box " + BOX_NAMES[box_id].toLowerCase() + " " + area_type_names[data.areas[i].type] sh.addEventListener("mousedown", on_click_loc) sh.style.left = x - (box_w / 2) + "px" sh.style.top = y - (box_h / 2) + "px" sh.style.width = box_w + "px" sh.style.height = box_h + "px" document.getElementById("decor").appendChild(sh) let tx = document.createElement("div") tx.textContent = BOX_NAMES[box_id] tx.className = "box text" tx.style.left = x - (box_w/2) + "px" if (box_id === 0) tx.style.top = y - 5 + "px" else tx.style.top = y - 9 + "px" tx.style.width = (box_w) + "px" tx.style.height = 20 + "px" document.getElementById("decor").appendChild(tx) } } function on_init() { if (on_init_once) return on_init_once = true // Tracker let x = 3 let y = 3 for (let i = 0; i < 100; ++i) { LAYOUT_TRACK[i] = [x + 22, y + 22] create_tracker(i, x, y) if (i < 29) { x += 50 } else if (i < 50) { y += 50 } else if (i < 79) { x -= 50 } else { y -= 50 } } // Border Zone DRM create_border_zone(0, "0") create_border_zone(1, "-1") create_border_zone(2, "-2") create_border_zone(3, "-3") ui.areas_u[ORAN] = create_area_u(ORAN, "#svgmap #Oran-2") ui.areas_u[ALGIERS] = create_area_u(ALGIERS, "#svgmap #Algiers-2") ui.areas_u[CONSTANTINE] = create_area_u(CONSTANTINE, "#svgmap #Constantine-2") // Areas for (let i = 0; i < data.areas.length; ++i) { let area_id = data.areas[i].id let area_name = data.areas[i].name let type = data.areas[i].type if (type) { create_area(i, area_id, area_name, type) if (type !== COUNTRY) { // Area markers create_area_markers(i, area_id, area_name) // Unit Boxes for (let box_id = 0; box_id < 4; ++box_id) create_box(i, area_id, area_name, box_id, true) } else { create_area_markers(i, area_id, area_name) create_box(i, area_id, area_name, 0, false) } } } build_units() } function update_unit(e, u) { e.classList.toggle("neutralized", is_unit_neutralized(u)) e.classList.toggle("airmobile", is_unit_airmobile(u)) e.classList.toggle("fr_xx_dispersed", is_unit_dispersed(u)) e.classList.toggle("action", is_unit_action(u)) e.classList.toggle("selected", is_unit_selected(u)) e.classList.toggle("contacted", is_unit_contacted(u)) e.classList.toggle("eliminated", is_unit_eliminated(u)) } function animate(e, x0, y0, x1, y1) { const dx = x0 - x1 const dy = y0 - y1 if (!dx && !dy) return const transformFrom = `translate3d(${dx}px, ${dy}px, 0)` const transformTo = `translate3d(0, 0, 0)` e.animate([ { transform: transformFrom }, { transform: transformTo }, ], { duration: 750, easing: 'ease', }) } function update_map() { ui.player[FLN].classList.toggle("active", view.active === "FLN") ui.player[GOV].classList.toggle("active", view.active === "Government") ui.ap.textContent = view.fln_ap ui.psl[FLN].textContent = view.fln_psl ui.psl[GOV].textContent = view.gov_psl track_count.fill(0) layout_track(view.turn % 100, ui.markers.turn) layout_track(view.fln_ap, ui.markers.fln_ap) layout_track(view.fln_psl, ui.markers.fln_psl) layout_track(view.gov_psl, ui.markers.gov_psl) if (view.air_max) layout_track(view.air_avail, ui.markers.air_avail) layout_track(view.air_max, ui.markers.air_max) if (view.helo_max) layout_track(view.helo_avail, ui.markers.helo_avail) layout_track(view.helo_max, ui.markers.helo_max) layout_track(view.naval, ui.markers.naval) // Hide avail markers when no Air / Helo at all ui.markers.air_avail.classList.toggle("hide", !view.air_max) ui.markers.helo_avail.classList.toggle("hide", !view.helo_max) ui.markers.border_zone.style.left = 4 + DRM_X + DRM_DX * (-view.border_zone_drm) + "px" ui.markers.border_zone.style.top = 4 + DRM_Y + DRM_DY * (-view.border_zone_drm) + "px" ui.markers.border_zone.classList.toggle("hide", view.border_zone_drm === null) ui.markers.border_zone.classList.toggle("neutralized", !view.border_zone_active) for (let u = 0; u < unit_count; ++u) { let e = ui.units[u] let loc = unit_loc(u) switch (loc) { case OUT_OF_PLAY: e.remove() break case DEPLOY: if (is_gov_unit(u)) ui.gov_supply.appendChild(e) if (is_fln_unit(u)) ui.fln_supply.appendChild(e) break case ELIMINATED: ui.eliminated.appendChild(e) break default: if (e.parentElement !== ui.container) ui.container.appendChild(e) break } update_unit(e, u) } layout_stack(FRANCE, 0) layout_stack(MOROCCO, 0) layout_stack(TUNISIA, 0) for (let loc = 6; loc < data.areas.length; ++loc) { layout_stack(loc, 0) layout_stack(loc, 1) layout_stack(loc, 2) layout_stack(loc, 3) } for (let loc of [ ORAN, ALGIERS, CONSTANTINE ]) { ui.areas_u[loc].classList.toggle("action", is_loc_action(loc)) ui.areas_u[loc].classList.toggle("target", is_loc_selected(loc)) } for (let loc = 0; loc < data.areas.length; ++loc) { let e = ui.areas[loc] if (e) { e.classList.toggle("action", is_loc_action(loc)) e.classList.toggle("target", is_loc_selected(loc)) let em = ui.area_markers[loc] if (em) { if (!is_area_country(loc)) { em.fln_control.classList.toggle("hide", !is_area_fln_control(loc)) em.gov_control.classList.toggle("hide", !is_area_gov_control(loc)) em.remote.classList.toggle("hide", !is_area_remote(loc)) em.terror.classList.toggle("hide", !is_area_terrorized(loc)) } em.oas_active.classList.toggle("hide", !is_area_oas_active(loc)) } } } } function on_update() { // eslint-disable-line no-unused-vars on_init() update_map() action_button("quick_setup", "Quick Setup") action_button("roll", "Roll") action_button("raise_fln_psl_1d6", "+1d6 FLN PSL") action_button("lower_gov_psl_1d6", "-1d6 Gov PSL") action_button("zone_I", "I") action_button("zone_II", "II") action_button("zone_III", "III") action_button("zone_IV", "IV") action_button("zone_V", "V") action_button("zone_VI", "VI") // gov reinforcement action_button("mobilization", "Mobilization") action_button("activation", "Activation") action_button("acquire_assets", "Acquire Assets") action_button("select_all_inactive", "Select All") action_button("acquire_air_point", "+1 Air") action_button("acquire_helo_point", "+1 Helo") action_button("acquire_naval_point", "+1 Naval") action_button("mobilize_border_zone", "Mobilize Border") action_button("improve_border_zone", "Improve Border") action_button("activate_border_zone", "Activate Border") action_button("remove", "Remove") action_button("activate", "Activate") action_button("build_cadre", "Build Cadre") action_button("build_band", "Build Band") action_button("convert_cadre_to_front", "Convert to Front") action_button("convert_cadre_to_band", "Convert to Band") action_button("convert_band_to_failek", "Convert to Failek") action_button("convert_front_to_cadre", "Convert to Cadre") action_button("change_division_mode", "Change Division Mode") action_button("propaganda", "Propaganda") action_button("strike", "Strike") action_button("move", "Move") action_button("raid", "Raid") action_button("harass", "Harass") action_button("flush", "Flush") action_button("intelligence", "Intelligence") action_button("civil_affairs", "Civil Affairs") action_button("suppression", "Suppression") //action_button("population_resettlement", "Population Resettlement") action_button("population_resettlement", "Resettlement") //action_button("gov_mission", "Government Mission") action_button("gov_mission", "Government") action_button("use_air_point", "Air Point") action_button("airmobilize", "Airmobilize") action_button("no_react", "No React") action_button("auto_pass", "Auto-Pass") action_button("pass", "Pass") action_button("add_fln_psl", "+1 FLN PSL") action_button("add_5_fln_psl", "+5 FLN PSL") action_button("remove_fln_psl", "-1 FLN PSL") action_button("remove_5_fln_psl", "-5 FLN PSL") action_button("add_gov_psl", "+1 Gov PSL") action_button("add_5_gov_psl", "+5 Gov PSL") action_button("remove_gov_psl", "-1 Gov PSL") action_button("remove_5_gov_psl", "-5 Gov PSL") action_button("eliminate_cadre", "Eliminate Cadre") action_button("eliminate_band", "Eliminate Band") action_button("reduce_front", "Reduce Front") action_button("reduce_failek", "Reduce Failek") action_button("end_reinforcement", "End Reinforcement") action_button("end_deployment", "End Deployment") action_button("end_turn", "End Turn") action_button("done", "Done") action_button("undo", "Undo") } const ICONS = { B0: '', B1: '', B2: '', B3: '', B4: '', B5: '', B6: '', W0: '', W1: '', W2: '', W3: '', W4: '', W5: '', W6: '', G1: '', G2: '', G3: '', G4: '', G5: '', G6: '', F1: '', F2: '', F3: '', F4: '', F5: '', F6: '', } function sub_icon(match) { return ICONS[match] } function on_focus_area_tip(x) { // eslint-disable-line no-unused-vars ui.areas[x].classList.add("tip") } function on_blur_area_tip(x) { // eslint-disable-line no-unused-vars ui.areas[x].classList.remove("tip") } function on_click_area_tip(x) { // eslint-disable-line no-unused-vars scroll_into_view(ui.areas[x]) } function sub_area_name(_match, p1, _offset, _string) { let x = p1 | 0 let n = data.areas[x].full_name return `${n}` } function on_focus_unit_tip(x) { // eslint-disable-line no-unused-vars ui.units[x].classList.add("tip") } function on_blur_unit_tip(x) { // eslint-disable-line no-unused-vars ui.units[x].classList.remove("tip") } function on_click_unit_tip(x) { // eslint-disable-line no-unused-vars scroll_into_view(ui.units[x]) } function sub_unit_name(_match, p1, _offset, _string) { let x = p1 | 0 let n = data.units[x].name return `${n}` } function on_log(text) { // eslint-disable-line no-unused-vars let p = document.createElement("div") if (text.match(/^>>/)) { text = text.substring(2) p.className = "ii" } if (text.match(/^>/)) { text = text.substring(1) p.className = "i" } if (text.match(/^\$/)) { text = text.substring(1) p.className = "p" } text = text.replace(/&/g, "&") text = text.replace(//g, ">") text = text.replace(/U(\d+)/g, sub_unit_name) text = text.replace(/A(\d+)/g, sub_area_name) text = text.replace(/\b[BWGF]\d\b/g, sub_icon) if (text.match(/^\.h1/)) { text = text.substring(4) p.className = 'h1' } else if (text.match(/^\.h2/)) { text = text.substring(4) p.className = 'h2' if (text.match(/^FLN/)) { p.classList.add("fln") } else if (text.match(/^Gov/)) { p.classList.add("gov") } else if (text.match(/^OAS/)) { p.classList.add("oas") } } else if (text.match(/^\.h3.gov/)) { text = text.substring(8) p.className = 'h3 gov' } else if (text.match(/^\.h3.fln/)) { text = text.substring(8) p.className = 'h3 fln' } else if (text.match(/^\.h3.oas/)) { text = text.substring(8) p.className = 'h3 oas' } else if (text.match(/^\.h3/)) { text = text.substring(4) p.className = 'h3' } else if (text.match(/^.hr$/)) { p.className = "hr"; text = ""; } p.innerHTML = text return p }