From 5b4dfdda9c301cdce2a70262fcb4932a25ce9c74 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Tue, 16 Jun 2015 17:37:38 +0200 Subject: [PATCH] Allows one to define list of random selection items. Includes a default list with a couple of semi-randomly selected probabilities. --- baystation12.dme | 5 +- code/game/antagonist/antagonist.dm | 6 +- code/game/antagonist/station/traitor.dm | 6 +- code/game/gamemodes/game_mode.dm | 76 --- .../items/devices/radio/encryptionkey.dm | 2 +- .../items/devices/{uplinks.dm => uplink.dm} | 216 ++------ .../items/devices/uplink_categories.dm | 40 ++ .../objects/items/devices/uplink_items.dm | 504 ++++++++++++++++++ .../items/devices/uplink_random_lists.dm | 103 ++++ nano/templates/uplink.tmpl | 68 ++- 10 files changed, 736 insertions(+), 290 deletions(-) rename code/game/objects/items/devices/{uplinks.dm => uplink.dm} (55%) create mode 100644 code/game/objects/items/devices/uplink_categories.dm create mode 100644 code/game/objects/items/devices/uplink_items.dm create mode 100644 code/game/objects/items/devices/uplink_random_lists.dm diff --git a/baystation12.dme b/baystation12.dme index a8eeac7aede..86d2a2d5028 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -601,7 +601,10 @@ #include "code\game\objects\items\devices\taperecorder.dm" #include "code\game\objects\items\devices\traitordevices.dm" #include "code\game\objects\items\devices\transfer_valve.dm" -#include "code\game\objects\items\devices\uplinks.dm" +#include "code\game\objects\items\devices\uplink.dm" +#include "code\game\objects\items\devices\uplink_categories.dm" +#include "code\game\objects\items\devices\uplink_items.dm" +#include "code\game\objects\items\devices\uplink_random_lists.dm" #include "code\game\objects\items\devices\violin.dm" #include "code\game\objects\items\devices\whistle.dm" #include "code\game\objects\items\devices\PDA\cart.dm" diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index aad02b1c6c6..02b048a6ee4 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -192,14 +192,12 @@ var/uplink_true = 0 var/purchases = "" for(var/obj/item/device/uplink/H in world_uplinks) - if(H && H.uplink_owner && H.uplink_owner == ply) + if(H && H.owner && H.owner == ply) TC_uses += H.used_TC uplink_true = 1 var/list/refined_log = new() for(var/datum/uplink_item/UI in H.purchase_log) - var/obj/I = new UI.path - refined_log.Add("[H.purchase_log[UI]]x\icon[I][UI.name]") - qdel(I) + refined_log.Add("[H.purchase_log[UI]]x[UI.log_icon()][UI.name]") purchases = english_list(refined_log, nothing_text = "") if(uplink_true) text += " (used [TC_uses] TC)" diff --git a/code/game/antagonist/station/traitor.dm b/code/game/antagonist/station/traitor.dm index c8b8b95b2a6..c5f4eb72897 100644 --- a/code/game/antagonist/station/traitor.dm +++ b/code/game/antagonist/station/traitor.dm @@ -148,8 +148,7 @@ var/datum/antagonist/traitor/traitors if ((freq % 2) == 0) freq += 1 freq = freqlist[rand(1, freqlist.len)] - var/obj/item/device/uplink/hidden/T = new(R) - T.uplink_owner = traitor_mob.mind + var/obj/item/device/uplink/hidden/T = new(R, traitor_mob.mind) target_radio.hidden_uplink = T target_radio.traitor_frequency = freq traitor_mob << "A portable object teleportation relay has been installed in your [R.name] [loc]. Simply dial the frequency [format_frequency(freq)] to unlock its hidden features." @@ -158,8 +157,7 @@ var/datum/antagonist/traitor/traitors else if (istype(R, /obj/item/device/pda)) // generate a passcode if the uplink is hidden in a PDA var/pda_pass = "[rand(100,999)] [pick("Alpha","Bravo","Delta","Omega")]" - var/obj/item/device/uplink/hidden/T = new(R) - T.uplink_owner = traitor_mob.mind + var/obj/item/device/uplink/hidden/T = new(R, traitor_mob.mind) R.hidden_uplink = T var/obj/item/device/pda/P = R P.lock_code = pda_pass diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index c6b86d16708..74d87dc800b 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -64,82 +64,6 @@ var/global/list/additional_antag_types = list() var/uplink_welcome = "Illegal Uplink Console:" var/uplink_uses = 12 - var/list/datum/uplink_item/uplink_items = list( - "Ammunition" = list( - new/datum/uplink_item(/obj/item/ammo_magazine/a357, 2, ".357", "RA"), - new/datum/uplink_item(/obj/item/ammo_magazine/mc9mm, 2, "9mm", "R9"), - new/datum/uplink_item(/obj/item/ammo_magazine/chemdart, 2, "Darts", "AD"), - new/datum/uplink_item(/obj/item/weapon/storage/box/sniperammo, 2, "14.5mm", "SA") - ), - "Highly Visible and Dangerous Weapons" = list( - new/datum/uplink_item(/obj/item/weapon/storage/box/emps, 3, "5 EMP Grenades", "EM"), - new/datum/uplink_item(/obj/item/weapon/melee/energy/sword, 4, "Energy Sword", "ES"), - new/datum/uplink_item(/obj/item/weapon/gun/projectile/dartgun, 5, "Dart Gun", "DG"), - new/datum/uplink_item(/obj/item/weapon/gun/energy/crossbow, 5, "Energy Crossbow", "XB"), - new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/g9mm, 5, "Silenced 9mm", "S9"), - new/datum/uplink_item(/obj/item/mecha_parts/mecha_equipment/weapon/energy/riggedlaser, 6, "Exosuit Rigged Laser", "RL"), - new/datum/uplink_item(/obj/item/weapon/gun/projectile/revolver, 6, "Revolver", "RE"), - new/datum/uplink_item(/obj/item/weapon/storage/box/syndicate, 10, "Mercenary Bundle", "BU"), - new/datum/uplink_item(/obj/item/weapon/gun/projectile/heavysniper, 12, "Anti-materiel Rifle", "AMR") - ), - "Stealthy and Inconspicuous Weapons" = list( - new/datum/uplink_item(/obj/item/weapon/soap/syndie, 1, "Subversive Soap", "SP"), - new/datum/uplink_item(/obj/item/weapon/cane/concealed, 2, "Concealed Cane Sword", "CC"), - new/datum/uplink_item(/obj/item/weapon/cartridge/syndicate, 3, "Detomatix PDA Cartridge", "DC"), - new/datum/uplink_item(/obj/item/weapon/pen/reagent/paralysis, 3, "Paralysis Pen", "PP"), - new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/cigarette, 4, "Cigarette Kit", "BH"), - new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/toxin, 4, "Random Toxin - Beaker", "RT") - ), - "Stealth and Camouflage Items" = list( - new/datum/uplink_item(/obj/item/weapon/card/id/syndicate, 2, "Agent ID card", "AC"), - new/datum/uplink_item(/obj/item/clothing/shoes/syndigaloshes, 2, "No-Slip Shoes", "SH"), - new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/spy, 2, "Bug Kit", "BK"), - new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/chameleon, 3, "Chameleon Kit", "CB"), - new/datum/uplink_item(/obj/item/device/chameleon, 4, "Chameleon-Projector", "CP"), - new/datum/uplink_item(/obj/item/clothing/mask/gas/voice, 4, "Voice Changer", "VC"), - new/datum/uplink_item(/obj/item/weapon/disk/file/cameras/syndicate, 6, "Camera Network Access - Floppy", "SF") - ), - "Devices and Tools" = list( - new/datum/uplink_item(/obj/item/weapon/storage/toolbox/syndicate, 1, "Fully Loaded Toolbox", "ST"), - new/datum/uplink_item(/obj/item/weapon/plastique, 2, "C-4 (Destroys walls)", "C4"), - new/datum/uplink_item(/obj/item/device/encryptionkey/syndicate, 2, "Encrypted Radio Channel Key", "ER"), - new/datum/uplink_item(/obj/item/device/encryptionkey/binary, 3, "Binary Translator Key", "BT"), - new/datum/uplink_item(/obj/item/weapon/card/emag, 3, "Cryptographic Sequencer", "EC"), - new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/clerical, 3, "Morphic Clerical Kit", "CK"), - new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/space, 3, "Space Suit", "SS"), - new/datum/uplink_item(/obj/item/clothing/glasses/thermal/syndi, 3, "Thermal Imaging Glasses", "TM"), - new/datum/uplink_item(/obj/item/clothing/suit/storage/vest/heavy/merc, 4, "Heavy Armor Vest", "HAV"), - new/datum/uplink_item(/obj/item/weapon/aiModule/syndicate, 7, "Hacked AI Upload Module", "AI"), - new/datum/uplink_item(/obj/item/device/powersink, 5, "Powersink (DANGER!)", "PS",), - new/datum/uplink_item(/obj/item/device/radio/beacon/syndicate, 7, "Singularity Beacon (DANGER!)", "SB"), - new/datum/uplink_item(/obj/item/weapon/circuitboard/teleporter, 20, "Teleporter Circuit Board", "TP") - ), - "Implants" = list( - new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/imp_freedom, 3, "Freedom Implant", "FI"), - new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/imp_compress, 4, "Compressed Matter Implant", "CI"), - new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/imp_explosive, 6, "Explosive Implant (DANGER!)", "EI"), - new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/imp_uplink, 10, "Uplink Implant (Contains 5 Telecrystals)", "UI") - ), - "Medical" = list( - new/datum/uplink_item(/obj/item/weapon/storage/box/sinpockets, 1, "Box of Sin-Pockets", "DP"), - new/datum/uplink_item(/obj/item/weapon/storage/firstaid/surgery, 5, "Surgery kit", "SK"), - new/datum/uplink_item(/obj/item/weapon/storage/firstaid/combat, 5, "Combat medical kit", "CM") - ), - "Hardsuit Modules" = list( - new/datum/uplink_item(/obj/item/rig_module/vision/thermal, 2, "Thermal Scanner", "RTS"), - new/datum/uplink_item(/obj/item/rig_module/fabricator/energy_net, 3, "Net Projector", "REN"), - new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/ewar_voice, 4, "Electrowarfare Suite and Voice Synthesiser", "REV"), - new/datum/uplink_item(/obj/item/rig_module/maneuvering_jets, 4, "Maneuvering Jets", "RMJ"), - new/datum/uplink_item(/obj/item/rig_module/mounted/egun, 6, "Mounted Energy Gun", "REG"), - new/datum/uplink_item(/obj/item/rig_module/power_sink, 6, "Power Sink", "RPS"), - new/datum/uplink_item(/obj/item/rig_module/mounted, 8, "Mounted Laser Cannon", "RLC") - ), - "(Pointless) Badassery" = list( - new/datum/uplink_item(/obj/item/toy/syndicateballoon, 10, "For showing that You Are The BOSS (Useless Balloon)", "BS"), - new/datum/uplink_item(/obj/item/toy/nanotrasenballoon, 10, "For showing that you love NT SOO much (Useless Balloon)", "NT") - ) - ) - /datum/game_mode/Topic(href, href_list[]) if(..()) return diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm index 72a99f494ed..8ccc4616c50 100644 --- a/code/game/objects/items/devices/radio/encryptionkey.dm +++ b/code/game/objects/items/devices/radio/encryptionkey.dm @@ -1,6 +1,6 @@ /obj/item/device/encryptionkey/ - name = "standard encrpytion key" + name = "standard encryption key" desc = "An encryption key for a radio headset. Contains cypherkeys." icon = 'icons/obj/radio.dmi' icon_state = "cypherkey" diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplink.dm similarity index 55% rename from code/game/objects/items/devices/uplinks.dm rename to code/game/objects/items/devices/uplink.dm index 96874bd946b..eca572ab621 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplink.dm @@ -6,159 +6,28 @@ A list of items and costs is stored under the datum of every game mode, alongsid */ -/datum/uplink_item/ - var/name = "" - var/cost = 0 - var/path = null - var/reference = "" - var/description = "" - -datum/uplink_item/New(var/itemPath, var/itemCost, var/itemName, var/itemReference, var/itemDescription) - cost = itemCost - path = itemPath - name = itemName - reference = itemReference - description = itemDescription - -datum/uplink_item/proc/description() - if(!description) - // Fallback description - var/obj/temp = src.path - description = replacetext(initial(temp.desc), "\n", "
") - return description - -/datum/uplink_item/proc/generate_item(var/newloc) - var/list/L = list() - if(ispath(path)) - L += new path(newloc) - else if(islist(path)) - for(var/item_path in path) - L += new item_path(newloc) - return L - -datum/nano_item_lists - var/list/items_nano - var/list/items_reference - /obj/item/device/uplink var/welcome // Welcoming menu message var/uses // Numbers of crystals - var/list/ItemsCategory // List of categories with lists of items - var/list/ItemsReference // List of references with an associated item - var/list/nanoui_items // List of items for NanoUI use - var/nanoui_menu = 0 // The current menu we are in - var/list/nanoui_data = new // Additional data for NanoUI use - - var/list/purchase_log = new - var/uplink_owner = null//text-only + var/list/purchase_log + var/datum/mind/owner = null var/used_TC = 0 /obj/item/device/uplink/nano_host() return loc -/obj/item/device/uplink/New() +/obj/item/device/uplink/New(var/location, var/datum/mind/owner) ..() welcome = ticker.mode.uplink_welcome uses = ticker.mode.uplink_uses - ItemsCategory = ticker.mode.uplink_items - + src.owner = owner + purchase_log = list() world_uplinks += src /obj/item/device/uplink/Destroy() world_uplinks -= src ..() -/obj/item/device/uplink/proc/generate_items() - var/datum/nano_item_lists/IL = generate_item_lists() - nanoui_items = IL.items_nano - ItemsReference = IL.items_reference - -// BS12 no longer use this menu but there are forks that do, hency why we keep it -/obj/item/device/uplink/proc/generate_menu() - var/dat = "[src.welcome]
" - dat += "Tele-Crystals left: [src.uses]
" - dat += "
" - dat += "Request item:
" - dat += "Each item costs a number of tele-crystals as indicated by the number following their name.
" - - var/category_items = 1 - for(var/category in ItemsCategory) - if(category_items < 1) - dat += "We apologize, as you could not afford anything from this category.
" - dat += "
" - dat += "[category]
" - category_items = 0 - - for(var/datum/uplink_item/I in ItemsCategory[category]) - if(I.cost > uses) - continue - dat += "[I.name] ([I.cost])
" - category_items++ - - dat += "Random Item (??)
" - dat += "
" - return dat - -/* - Built the item lists for use with NanoUI -*/ -/obj/item/device/uplink/proc/generate_item_lists() - var/list/nano = new - var/list/reference = new - - for(var/category in ItemsCategory) - nano[++nano.len] = list("Category" = category, "items" = list()) - for(var/datum/uplink_item/I in ItemsCategory[category]) - nano[nano.len]["items"] += list(list("Name" = I.name, "Description" = I.description(),"Cost" = I.cost, "obj_path" = I.reference)) - reference[I.reference] = I - - var/datum/nano_item_lists/result = new - result.items_nano = nano - result.items_reference = reference - return result - -//If 'random' was selected -/obj/item/device/uplink/proc/chooseRandomItem() - if(uses <= 0) - return - - var/list/random_items = new - for(var/IR in ItemsReference) - var/datum/uplink_item/UI = ItemsReference[IR] - if(UI.cost <= uses) - random_items += UI - return pick(random_items) - -/obj/item/device/uplink/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["buy_item"] == "random") - var/datum/uplink_item/UI = chooseRandomItem() - href_list["buy_item"] = UI.reference - return buy(UI, "RN") - else - var/datum/uplink_item/UI = ItemsReference[href_list["buy_item"]] - return buy(UI, UI ? UI.reference : "") - return 0 - -/obj/item/device/uplink/proc/buy(var/datum/uplink_item/UI, var/reference) - if(UI && UI.cost <= uses) - uses -= UI.cost - used_TC += UI.cost - feedback_add_details("traitor_uplink_items_bought", reference) - - var/list/L = UI.generate_item(get_turf(usr)) - if(ishuman(usr)) - var/mob/living/carbon/human/A = usr - for(var/obj/I in L) - A.put_in_any_hand_if_possible(I) - - purchase_log[UI] = purchase_log[UI] + 1 - - return 1 - return 0 - // HIDDEN UPLINK - Can be stored in anything but the host item has to have a trigger for it. /* How to create an uplink in 3 easy steps! @@ -175,6 +44,11 @@ datum/nano_item_lists name = "hidden uplink" desc = "There is something wrong if you're examining this." var/active = 0 + var/nanoui_menu = 0 // The current menu we are in + var/datum/uplink_category/category = 0 // The current category we are in + var/exploit_id // Id of the current exploit record we are viewing + var/list/nanoui_data // Data for NanoUI use + // The hidden uplink MUST be inside an obj/item's contents. /obj/item/device/uplink/hidden/New() @@ -182,6 +56,8 @@ datum/nano_item_lists if(!istype(src.loc, /obj/item)) qdel(src) ..() + nanoui_data = list() + update_nano_data() // Toggles the uplink on and off. Normally this will bypass the item's normal functions and go to the uplink menu, if activated. /obj/item/device/uplink/hidden/proc/toggle() @@ -212,20 +88,13 @@ datum/nano_item_lists data["welcome"] = welcome data["crystals"] = uses data["menu"] = nanoui_menu - if(!nanoui_items) - generate_items() - data["nano_items"] = nanoui_items data += nanoui_data // update the ui if it exists, returns null if no ui is passed/found ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm + if (!ui) // No auto-refresh ui = new(user, src, ui_key, "uplink.tmpl", title, 450, 600, state = inventory_state) - // when the ui is first opened this is the data it will use ui.set_initial_data(data) - // open the new ui window ui.open() @@ -235,43 +104,54 @@ datum/nano_item_lists // The purchasing code. /obj/item/device/uplink/hidden/Topic(href, href_list) - if (usr.stat || usr.restrained()) + if(..()) return 1 - if (!( istype(usr, /mob/living/carbon/human))) - return 1 var/mob/user = usr - var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") - if ((usr.contents.Find(src.loc) || (in_range(src.loc, usr) && istype(src.loc.loc, /turf)))) - usr.set_machine(src) - if(..(href, href_list)) - return 1 - else if(href_list["lock"]) - toggle() - ui.close() - return 1 - if(href_list["return"]) - nanoui_menu = round(nanoui_menu/10) - update_nano_data() - if(href_list["menu"]) - nanoui_menu = text2num(href_list["menu"]) - update_nano_data(href_list["id"]) + if(href_list["buy_item"]) + var/datum/uplink_item/UI = (locate(href_list["buy_item"]) in uplink.items) + UI.buy(src, usr) + else if(href_list["lock"]) + toggle() + var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") + ui.close() + else if(href_list["return"]) + nanoui_menu = round(nanoui_menu/10) + else if(href_list["menu"]) + nanoui_menu = text2num(href_list["menu"]) + if(href_list["id"]) + exploit_id = href_list["id"] + if(href_list["category"]) + category = locate(href_list["category"]) in uplink.categories - interact(usr) + update_nano_data() return 1 -/obj/item/device/uplink/hidden/proc/update_nano_data(var/id) - if(nanoui_menu == 1) +/obj/item/device/uplink/hidden/proc/update_nano_data() + if(nanoui_menu == 0) + var/categories[0] + for(var/datum/uplink_category/category in uplink.categories) + if(category.can_view(src)) + categories[++categories.len] = list("name" = category.name, "ref" = "\ref[category]") + nanoui_data["categories"] = categories + else if(nanoui_menu == 1) + var/items[0] + for(var/datum/uplink_item/item in category.items) + if(item.can_view(src)) + var/cost = item.cost() + if(!cost) cost = "???" + items[++items.len] = list("name" = item.name, "description" = replacetext(item.description(), "\n", "
"), "can_buy" = item.can_buy(src), "cost" = cost, "ref" = "\ref[item]") + nanoui_data["items"] = items + else if(nanoui_menu == 2) var/permanentData[0] for(var/datum/data/record/L in sortRecord(data_core.locked)) permanentData[++permanentData.len] = list(Name = L.fields["name"],"id" = L.fields["id"]) nanoui_data["exploit_records"] = permanentData - - if(nanoui_menu == 11) + else if(nanoui_menu == 21) nanoui_data["exploit_exists"] = 0 for(var/datum/data/record/L in data_core.locked) - if(L.fields["id"] == id) + if(L.fields["id"] == exploit_id) nanoui_data["exploit"] = list() // Setting this to equal L.fields passes it's variables that are lists as reference instead of value. // We trade off being able to automatically add shit for more control over what gets passed to json // and if it's sanitized for html. diff --git a/code/game/objects/items/devices/uplink_categories.dm b/code/game/objects/items/devices/uplink_categories.dm new file mode 100644 index 00000000000..f90c4797bc5 --- /dev/null +++ b/code/game/objects/items/devices/uplink_categories.dm @@ -0,0 +1,40 @@ +/datum/uplink_category + var/name = "" + var/list/datum/uplink_item/items + +/datum/uplink_category/New() + ..() + items = list() + +/datum/uplink_category/proc/can_view(obj/item/device/uplink/U) + for(var/datum/uplink_item/item in items) + if(item.can_view(U)) + return 1 + return 0 + +/datum/uplink_category/ammunition + name = "Ammunition" + +/datum/uplink_category/visible_weapons + name = "Highly Visible and Dangerous Weapons" + +/datum/uplink_category/stealthy_weapons + name = "Stealthy and Inconspicuous Weapons" + +/datum/uplink_category/stealth_items + name = "Stealth and Camouflage Items" + +/datum/uplink_category/tools + name = "Devices and Tools" + +/datum/uplink_category/implants + name = "Implants" + +/datum/uplink_category/medical + name = "Medical" + +/datum/uplink_category/hardsuit_modules + name = "Hardsuit Modules" + +/datum/uplink_category/badassery + name = "Badassery" diff --git a/code/game/objects/items/devices/uplink_items.dm b/code/game/objects/items/devices/uplink_items.dm new file mode 100644 index 00000000000..e6edc632a21 --- /dev/null +++ b/code/game/objects/items/devices/uplink_items.dm @@ -0,0 +1,504 @@ +var/datum/uplink/uplink = new() + +/datum/uplink + var/list/items_assoc + var/list/datum/uplink_item/items + var/list/datum/uplink_category/categories + +/datum/uplink/New() + items_assoc = list() + items = init_subtypes(/datum/uplink_item) + categories = init_subtypes(/datum/uplink_category) + + for(var/datum/uplink_item/item in items) + if(!item.name) + items -= item + continue + + items_assoc[item.type] = item + + for(var/datum/uplink_category/category in categories) + if(item.category == category.type) + category.items += item + + for(var/datum/uplink_category/category in categories) + category.items = dd_sortedObjectList(category.items) + +/datum/uplink_item + var/name + var/desc + var/item_cost = 0 + var/datum/uplink_category/category // Item category + var/list/datum/antagonist/antag_roles // Antag roles this item is displayed to. If empty, display to all. + +/datum/uplink_item/item + var/path = null + +/datum/uplink_item/New() + ..() + antag_roles = list() + +/datum/uplink_item/proc/buy(var/obj/item/device/uplink/U, var/mob/user) + var/cost = max(0, cost(U.uses)) + var/obj/item/I = get_goods(get_turf(user)) + if(istype(I) && ishuman(user)) + var/mob/living/carbon/human/A = user + A.put_in_any_hand_if_possible(I) + U.uses -= cost + U.used_TC += cost + purchase_log(U) + + return cost + +/datum/uplink_item/proc/get_goods(var/loc) + return 0 + +/datum/uplink_item/proc/can_buy(obj/item/device/uplink/U) + if(cost(U.uses) > U.uses) + return 0 + + return can_view(U) + +/datum/uplink_item/proc/can_view(obj/item/device/uplink/U) + // Making the assumption that if no uplink was supplied, then we don't care about antag roles + if(!U || !antag_roles.len) + return 1 + + // With no owner, there's no need to check antag status. + if(!U.owner) + return 0 + + for(var/antag_role in antag_roles) + var/datum/antagonist/antag = all_antag_types[antag_role] + if(antag.is_antagonist(U.owner)) + return 1 + return 0 + +/datum/uplink_item/proc/cost() + return item_cost + +/datum/uplink_item/proc/description() + return desc + +/datum/uplink_item/proc/log_icon() + return + +/datum/uplink_item/proc/purchase_log(obj/item/device/uplink/U) + feedback_add_details("traitor_uplink_items_bought", "[src]") + U.purchase_log[src] = U.purchase_log[src] + 1 + +datum/uplink_item/dd_SortValue() + return cost(INFINITY) + +/******************************** +* * +* Physical Uplink Entires * +* * +********************************/ +/datum/uplink_item/item/get_goods(var/loc) + var/obj/item/I = new path(loc) + return I + +/datum/uplink_item/item/description() + if(!desc) + // Fallback description + var/obj/temp = src.path + desc = initial(temp.desc) + return ..() + +/datum/uplink_item/item/log_icon() + var/obj/I = path + return "\icon[I]" + +/************* +* Ammunition * +*************/ +/datum/uplink_item/item/ammo + item_cost = 2 + category = /datum/uplink_category/ammunition + +/datum/uplink_item/item/ammo/a357 + name = ".357" + path = /obj/item/ammo_magazine/a357 + +/datum/uplink_item/item/ammo/mc9mm + name = ".9mm" + path = /obj/item/ammo_magazine/mc9mm + +/datum/uplink_item/item/ammo/darts + name = "Darts" + path = /obj/item/ammo_magazine/chemdart + +/datum/uplink_item/item/ammo/sniperammo + name = "14.5mm" + path = /obj/item/weapon/storage/box/sniperammo + +/*************************************** +* Highly Visible and Dangerous Weapons * +***************************************/ +/datum/uplink_item/item/visible_weapons + category = /datum/uplink_category/visible_weapons + +/datum/uplink_item/item/visible_weapons/emp + name = "5xEMP Grenades" + item_cost = 3 + path = /obj/item/weapon/storage/box/emps + +/datum/uplink_item/item/visible_weapons/energy_sword + name = "Energy Sword" + item_cost = 4 + path = /obj/item/weapon/melee/energy/sword + +/datum/uplink_item/item/visible_weapons/dartgun + name = "Dart Gun" + item_cost = 5 + path = /obj/item/weapon/gun/projectile/dartgun + +/datum/uplink_item/item/visible_weapons/crossbow + name = "Energy Crossbow" + item_cost = 5 + path = /obj/item/weapon/gun/energy/crossbow + +/datum/uplink_item/item/visible_weapons/g9mm + name = "Silenced 9mm" + item_cost = 5 + path = /obj/item/weapon/storage/box/syndie_kit/g9mm + +/datum/uplink_item/item/visible_weapons/riggedlaser + name = "Exosuit Rigged Laser" + item_cost = 6 + path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/riggedlaser + +/datum/uplink_item/item/visible_weapons/revolver + name = "Revolver" + item_cost = 6 + path = /obj/item/weapon/gun/projectile/revolver + +/datum/uplink_item/item/visible_weapons/heavysniper + name = "Anti-materiel Rifle" + path = /obj/item/weapon/gun/projectile/heavysniper + +/datum/uplink_item/item/visible_weapons/heavysniper/cost() + return (ticker && ticker.mode && ticker.mode.uplink_uses) ? ticker.mode.uplink_uses : INFINITY + +/************************************* +* Stealthy and Inconspicuous Weapons * +*************************************/ +/datum/uplink_item/item/stealthy_weapons + category = /datum/uplink_category/stealthy_weapons + +/datum/uplink_item/item/stealthy_weapons/soap + name = "Subversive Soap" + item_cost = 1 + path = /obj/item/weapon/soap/syndie + +/datum/uplink_item/item/stealthy_weapons/concealed_cane + name = "Concealed Cane Sword" + item_cost = 1 + path = /obj/item/weapon/cane/concealed + +/datum/uplink_item/item/stealthy_weapons/detomatix + name = "Detomatix PDA Cartridge" + item_cost = 3 + path = /obj/item/weapon/cartridge/syndicate + +/datum/uplink_item/item/stealthy_weapons/parapen + name = "Paralysis Pen" + item_cost = 3 + path = /obj/item/weapon/pen/reagent/paralysis + +/datum/uplink_item/item/stealthy_weapons/cigarette_kit + name = "Cigarette Kit" + item_cost = 3 + path = /obj/item/weapon/storage/box/syndie_kit/cigarette + +/datum/uplink_item/item/stealthy_weapons/random_toxin + name = "Random Toxin - Beaker" + item_cost = 3 + path = /obj/item/weapon/storage/box/syndie_kit/toxin + +/******************************* +* Stealth and Camouflage Items * +*******************************/ +/datum/uplink_item/item/stealth_items + category = /datum/uplink_category/stealth_items + +/datum/uplink_item/item/stealth_items/id + name = "Agent ID card" + item_cost = 2 + path = /obj/item/weapon/card/id/syndicate + +/datum/uplink_item/item/stealth_items/syndigaloshes + name = "No-Slip Shoes" + item_cost = 2 + path = /obj/item/clothing/shoes/syndigaloshes + +/datum/uplink_item/item/stealth_items/spy + name = "Bug Kit" + item_cost = 2 + path = /obj/item/weapon/storage/box/syndie_kit/spy + +/datum/uplink_item/item/stealth_items/chameleon_kit + name = "Chameleon Kit" + item_cost = 3 + path = /obj/item/weapon/storage/box/syndie_kit/chameleon + +/datum/uplink_item/item/stealth_items/chameleon_projector + name = "Chameleon-Projector" + item_cost = 4 + path = /obj/item/device/chameleon + +/datum/uplink_item/item/stealth_items/chameleon_projector + name = "Chameleon-Projector" + item_cost = 4 + path = /obj/item/device/chameleon + +/datum/uplink_item/item/stealth_items/voice + name = "Voice Changer" + item_cost = 4 + path = /obj/item/clothing/mask/gas/voice + +/datum/uplink_item/item/stealth_items/camera_floppy + name = "Camera Network Access - Floppy" + item_cost = 6 + path = /obj/item/weapon/disk/file/cameras/syndicate + +/******************** +* Devices and Tools * +********************/ +/datum/uplink_item/item/tools + category = /datum/uplink_category/tools + +/datum/uplink_item/item/tools/toolbox + name = "Fully Loaded Toolbox" + item_cost = 1 + path = /obj/item/weapon/storage/toolbox/syndicate + +/datum/uplink_item/item/tools/plastique + name = "C-4 (Destroys walls)" + item_cost = 2 + path = /obj/item/weapon/plastique + +/datum/uplink_item/item/tools/encryptionkey_radio + name = "Encrypted Radio Channel Key" + item_cost = 2 + path = /obj/item/device/encryptionkey/syndicate + +/datum/uplink_item/item/tools/encryptionkey_binary + name = "Binary Translator Key" + item_cost = 3 + path = /obj/item/device/encryptionkey/binary + +/datum/uplink_item/item/tools/emag + name = "Cryptographic Sequencer" + item_cost = 3 + path = /obj/item/weapon/card/emag + +/datum/uplink_item/item/tools/clerical + name = "Morphic Clerical Kit" + item_cost = 3 + path = /obj/item/weapon/storage/box/syndie_kit/clerical + +/datum/uplink_item/item/tools/space_suit + name = "Space Suit" + item_cost = 3 + path = /obj/item/weapon/storage/box/syndie_kit/space + +/datum/uplink_item/item/tools/thermal + name = "Thermal Imaging Glasses" + item_cost = 3 + path = /obj/item/clothing/glasses/thermal/syndi + +/datum/uplink_item/item/tools/heavy_vest + name = "Heavy Armor Vest" + item_cost = 4 + path = /obj/item/clothing/suit/storage/vest/heavy/merc + +/datum/uplink_item/item/tools/powersink + name = "Powersink (DANGER!)" + item_cost = 5 + path = /obj/item/device/powersink + +/datum/uplink_item/item/tools/ai_module + name = "Hacked AI Upload Module" + item_cost = 7 + path = /obj/item/weapon/aiModule/syndicate + +/datum/uplink_item/item/tools/singularity_beacon + name = "Singularity Beacon (DANGER!)" + item_cost = 7 + path = /obj/item/device/radio/beacon/syndicate + +/datum/uplink_item/item/tools/teleporter + name = "Teleporter Circuit Board" + item_cost = 20 + path = /obj/item/weapon/circuitboard/teleporter + +/datum/uplink_item/item/tools/teleporter/New() + ..() + antag_roles = list(MODE_MERCENARY) + +/*********** +* Implants * +***********/ +/datum/uplink_item/item/implants + category = /datum/uplink_category/implants + +/datum/uplink_item/item/implants/imp_freedom + name = "Freedom Implant" + item_cost = 3 + path = /obj/item/weapon/storage/box/syndie_kit/imp_freedom + +/datum/uplink_item/item/implants/imp_compress + name = "Compressed Matter Implant" + item_cost = 4 + path = /obj/item/weapon/storage/box/syndie_kit/imp_compress + +/datum/uplink_item/item/implants/imp_explosive + name = "Explosive Implant (DANGER!)" + item_cost = 6 + path = /obj/item/weapon/storage/box/syndie_kit/imp_explosive + +/datum/uplink_item/item/implants/imp_uplink + name = "Uplink Implant (Contains 5 Telecrystals)" + item_cost = 10 + path = /obj/item/weapon/storage/box/syndie_kit/imp_uplink + +/********** +* Medical * +**********/ +/datum/uplink_item/item/medical + category = /datum/uplink_category/medical + +/datum/uplink_item/item/medical/sinpockets + name = "Box of Sin-Pockets" + item_cost = 1 + path = /obj/item/weapon/storage/box/sinpockets + +/datum/uplink_item/item/medical/surgery + name = "Surgery kit" + item_cost = 6 + path = /obj/item/weapon/storage/firstaid/surgery + +/datum/uplink_item/item/medical/combat + name = "Combat medical kit" + item_cost = 6 + path = /obj/item/weapon/storage/firstaid/combat + +/******************* +* Hardsuit Modules * +*******************/ +/datum/uplink_item/item/hardsuit_modules + category = /datum/uplink_category/hardsuit_modules + +/datum/uplink_item/item/hardsuit_modules/thermal + name = "Thermal Scanner" + item_cost = 2 + path = /obj/item/rig_module/vision/thermal + +/datum/uplink_item/item/hardsuit_modules/energy_net + name = "Net Projector" + item_cost = 3 + path = /obj/item/rig_module/fabricator/energy_net + +/datum/uplink_item/item/ewar_voice + name = "Electrowarfare Suite and Voice Synthesiser" + item_cost = 4 + path = /obj/item/weapon/storage/box/syndie_kit/ewar_voice + +/datum/uplink_item/item/hardsuit_modules/maneuvering_jets + name = "Maneuvering Jets" + item_cost = 4 + path = /obj/item/rig_module/maneuvering_jets + +/datum/uplink_item/item/hardsuit_modules/egun + name = "Mounted Energy Gun" + item_cost = 6 + path = /obj/item/rig_module/mounted/egun + +/datum/uplink_item/item/hardsuit_modules/power_sink + name = "Power Sink" + item_cost = 6 + path = /obj/item/rig_module/power_sink + +/datum/uplink_item/item/hardsuit_modules/laser_canon + name = "Mounted Laser Cannon" + item_cost = 8 + path = /obj/item/rig_module/mounted + +/************ +* Badassery * +************/ +/datum/uplink_item/item/badassery + category = /datum/uplink_category/badassery + +/datum/uplink_item/item/badassery/balloon + name = "For showing that You Are The BOSS (Useless Balloon)" + path = /obj/item/toy/syndicateballoon + +/datum/uplink_item/item/badassery/balloon/NT + name = "For showing that you love NT SOO much (Useless Balloon)" + path = /obj/item/toy/nanotrasenballoon + +/datum/uplink_item/item/badassery/balloon/cost() + return (ticker && ticker.mode && ticker.mode.uplink_uses) ? ticker.mode.uplink_uses : 10 + +/************** +* Random Item * +**************/ +/datum/uplink_item/item/badassery/random + name = "Random Item" + desc = "Buys you one random item." + +/datum/uplink_item/item/badassery/random/buy(var/obj/item/device/uplink/U, var/mob/user) + var/datum/uplink_item/item = default_uplink_selection.get_random_item(U) + item.buy(U, user) + return 1 + +/datum/uplink_item/item/badassery/random/can_buy(obj/item/device/uplink/U) + return default_uplink_selection.get_random_item(U) != null + +/**************** +* Surplus Crate * +****************/ +/datum/uplink_item/item/badassery/surplus + name = "Surplus Crate" + item_cost = 40 + var/item_worth = 60 + var/icon + +/datum/uplink_item/item/badassery/surplus/New() + ..() + antag_roles = list(MODE_MERCENARY) + desc = "A crate containing [item_worth] telecrystal\s worth of surplus leftovers." + +/datum/uplink_item/item/badassery/surplus/buy(var/obj/item/device/uplink/U, var/mob/user) + var/obj/structure/largecrate/C = new(get_turf(user)) + var/list/bought_items = list() + var/remaining_TC = item_worth + U.uses += (item_worth - item_cost) + U.used_TC -= (item_worth - item_cost) + + while(remaining_TC) + var/datum/uplink_item/I = default_uplink_selection.get_random_item(telecrystals = remaining_TC, bought_items = bought_items) + if(!I) + break + bought_items += I + remaining_TC -= I.cost() + + purchase_log(U) + for(var/datum/uplink_item/item in bought_items) + item.purchase_log(U) + item.get_goods(C) + + U.uses -= item_worth + U.used_TC += item_worth + + return 1 + +/datum/uplink_item/item/badassery/surplus/log_icon() + if(!icon) + var/obj/structure/largecrate/C = /obj/structure/largecrate + icon = image(initial(C.icon), initial(C.icon_state)) + + return "\icon[icon]" diff --git a/code/game/objects/items/devices/uplink_random_lists.dm b/code/game/objects/items/devices/uplink_random_lists.dm new file mode 100644 index 00000000000..18d9d7841de --- /dev/null +++ b/code/game/objects/items/devices/uplink_random_lists.dm @@ -0,0 +1,103 @@ +var/datum/uplink_random_selection/default_uplink_selection = new/datum/uplink_random_selection/default() + +/datum/uplink_random_item + var/uplink_item // The uplink item + var/keep_probability // The probability we'll decide to keep this item if selected + var/reselect_probability // Probability that we'll decide to keep this item if previously selected. + // Is done together with the keep_probability check. Being selected more than once does not affect this probability. + +/datum/uplink_random_item/New(var/uplink_item, var/keep_probability = 100, var/reselect_propbability = 33) + ..() + src.uplink_item = uplink_item + src.keep_probability = keep_probability + src.reselect_probability = reselect_probability + +/datum/uplink_random_selection + var/list/datum/uplink_random_item/items + +/datum/uplink_random_selection/New() + ..() + items = list() + +/datum/uplink_random_selection/proc/get_random_item(obj/item/device/uplink/U, var/telecrystals, var/list/bought_items) + var/const/attempts = 50 + var/remainingTC = telecrystals ? telecrystals : U.uses + + for(var/i = 0; i < attempts; i++) + var/datum/uplink_random_item/RI = pick(items) + if(!prob(RI.keep_probability)) + continue + var/datum/uplink_item/I = uplink.items_assoc[RI.uplink_item] + if(I.cost() > remainingTC) + continue + if(bought_items && (I in bought_items) && !prob(RI.reselect_probability)) + continue + if(U && !I.can_buy(U)) + continue + return I + +/datum/uplink_random_selection/default/New() + ..() + + items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/g9mm) + items += new/datum/uplink_random_item(/datum/uplink_item/item/ammo/mc9mm) + items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/revolver) + items += new/datum/uplink_random_item(/datum/uplink_item/item/ammo/a357) + items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/heavysniper, 15, 0) + items += new/datum/uplink_random_item(/datum/uplink_item/item/ammo/sniperammo, 15, 0) + items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/emp, 50) + items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/crossbow, 33) + items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/energy_sword, 75) + + items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/soap, 5, 100) + items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/concealed_cane, 50, 10) + items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/detomatix, 20, 10) + items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/parapen) + items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/cigarette_kit) + + items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/id) + items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/spy) + items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/chameleon_kit) + items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/chameleon_projector) + items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/voice) + items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/camera_floppy, 10, 0) + + items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/toolbox, reselect_propbability = 10) + items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/plastique) + items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/encryptionkey_radio) + items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/encryptionkey_binary) + items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/emag, 100, 50) + items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/clerical) + items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/space_suit, 50, 10) + items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/thermal) + items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/heavy_vest) + items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/powersink, 10, 10) + items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/ai_module, 25, 0) + items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/teleporter, 10, 0) + + items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_freedom) + items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_compress) + items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_explosive) + + items += new/datum/uplink_random_item(/datum/uplink_item/item/medical/sinpockets, reselect_propbability = 20) + items += new/datum/uplink_random_item(/datum/uplink_item/item/medical/surgery, reselect_propbability = 10) + items += new/datum/uplink_random_item(/datum/uplink_item/item/medical/combat, reselect_propbability = 10) + + items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/thermal, reselect_propbability = 15) + items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/energy_net, reselect_propbability = 15) + items += new/datum/uplink_random_item(/datum/uplink_item/item/ewar_voice, reselect_propbability = 15) + items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/maneuvering_jets, reselect_propbability = 15) + items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/egun, reselect_propbability = 15) + items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/power_sink, reselect_propbability = 15) + items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/laser_canon, reselect_propbability = 5) + +#ifdef DEBUG +/proc/debug_uplink_purchage_log() + for(var/antag_type in all_antag_types) + var/datum/antagonist/A = all_antag_types[antag_type] + A.print_player_summary() + +/proc/debug_uplink_item_assoc_list() + for(var/key in uplink.items_assoc) + world << "[key] - [uplink.items_assoc[key]]" +#endif diff --git a/nano/templates/uplink.tmpl b/nano/templates/uplink.tmpl index e981155622d..a92fe95c6ee 100644 --- a/nano/templates/uplink.tmpl +++ b/nano/templates/uplink.tmpl @@ -12,48 +12,45 @@ Used In File(s): \code\game\objects\items\devices\uplinks.dm
{{:helper.link('Request Items', 'gear', {'menu' : 0}, null, 'fixedLeftWider')}} - {{:helper.link('Exploitable Information', 'gear', {'menu' : 1}, null, 'fixedLeftWider')}} + {{:helper.link('Exploitable Information', 'gear', {'menu' : 2}, null, 'fixedLeftWider')}} {{:helper.link('Return', 'arrowreturn-1-w', {'return' : 1}, null, 'fixedLeft')}} {{:helper.link('Close', 'gear', {'lock' : "1"}, null, 'fixedLeft')}}

- + +
+
+ Tele-Crystals: +
+
+ {{:data.crystals}} +
+
+ {{if data.menu == 0}} +

Categories:

+ {{for data.categories}} +
+ {{:helper.link(value.name, 'gear', {'menu' : 1, 'category' : value.ref})}} +
+ {{/for}} +{{else data.menu == 1}}

Request items:

Each item costs a number of tele-crystals as indicated by the number following their name. -
-
- Tele-Crystals: -
-
- {{:data.crystals}} -
-
-
- {{for data.nano_items}} -
-

{{:value.Category}}

-
- {{for value.items :itemValue:itemIndex}} -
- {{:helper.link( itemValue.Name, 'gear', {'buy_item' : itemValue.obj_path, 'cost' : itemValue.Cost}, itemValue.Cost > data.crystals ? 'disabled' : null, null)}} - {{:itemValue.Cost}} -
- - {{if itemValue.Cost <= data.crystals}} -
- {{:itemValue.Description}} -
- {{/if}} - {{/for}} -
- {{/for}} - -
- {{:helper.link('Buy Random (??)' , 'gear', {'buy_item' : 'random'}, data.crystals <= 0 ? 'disabled' : null, null)}} -
-{{else data.menu == 1}} + {{for data.items}} +
+ {{:helper.link(value.name, 'gear', {'buy_item' : value.ref}, value.can_buy ? null : 'disabled')}} - {{:value.cost}} +
+ + {{if value.can_buy}} +
+ {{:value.description}} +
+ {{/if}} + {{/for}} +{{else data.menu == 2}}

Information Record List:


@@ -62,11 +59,10 @@ Used In File(s): \code\game\objects\items\devices\uplinks.dm
{{for data.exploit_records}}
- {{:helper.link(value.Name, 'gear', {'menu' : 11, 'id' : value.id}, null, null)}} + {{:helper.link(value.Name, 'gear', {'menu' : 21, 'id' : value.id}, null, null)}}
{{/for}} - -{{else data.menu == 11}} +{{else data.menu == 21}}

Information Record: