diff --git a/baystation12.dme b/baystation12.dme index 2eae08c0638..6cc266e40d8 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -116,6 +116,7 @@ #include "code\controllers\verbs.dm" #include "code\controllers\voting.dm" #include "code\datums\ai_laws.dm" +#include "code\datums\browser.dm" #include "code\datums\computerfiles.dm" #include "code\datums\datacore.dm" #include "code\datums\datumvars.dm" diff --git a/code/datums/browser.dm b/code/datums/browser.dm new file mode 100644 index 00000000000..e97d8f7f07a --- /dev/null +++ b/code/datums/browser.dm @@ -0,0 +1,177 @@ +/datum/browser + var/mob/user + var/title + var/window_id // window_id is used as the window name for browse and onclose + var/width = 0 + var/height = 0 + var/atom/ref = null + var/window_options = "focus=0;can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id + var/stylesheets[0] + var/scripts[0] + var/title_image + var/head_elements + var/body_elements + var/head_content = "" + var/content = "" + + +/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null) + + user = nuser + window_id = nwindow_id + if (ntitle) + title = format_text(ntitle) + if (nwidth) + width = nwidth + if (nheight) + height = nheight + if (nref) + ref = nref + add_stylesheet("common", 'html/browser/common.css') // this CSS sheet is common to all UIs + +/datum/browser/proc/add_head_content(nhead_content) + head_content = nhead_content + +/datum/browser/proc/set_window_options(nwindow_options) + window_options = nwindow_options + +/datum/browser/proc/set_title_image(ntitle_image) + //title_image = ntitle_image + +/datum/browser/proc/add_stylesheet(name, file) + stylesheets[name] = file + +/datum/browser/proc/add_script(name, file) + scripts[name] = file + +/datum/browser/proc/set_content(ncontent) + content = ncontent + +/datum/browser/proc/add_content(ncontent) + content += ncontent + +/datum/browser/proc/get_header() + var/key + var/filename + for (key in stylesheets) + filename = "[ckey(key)].css" + user << browse_rsc(stylesheets[key], filename) + head_content += "" + + for (key in scripts) + filename = "[ckey(key)].js" + user << browse_rsc(scripts[key], filename) + head_content += "" + + var/title_attributes = "class='uiTitle'" + if (title_image) + title_attributes = "class='uiTitle icon' style='background-image: url([title_image]);'" + + return {" + + + + [head_content] + + +
+ [title ? "
[title]
" : ""] +
+ "} + +/datum/browser/proc/get_footer() + return {" +
+
+ +"} + +/datum/browser/proc/get_content() + return {" + [get_header()] + [content] + [get_footer()] + "} + +/datum/browser/proc/open(var/use_onclose = 1) + var/window_size = "" + if (width && height) + window_size = "size=[width]x[height];" + user << browse(get_content(), "window=[window_id];[window_size][window_options]") + if (use_onclose) + onclose(user, window_id, ref) + +/datum/browser/proc/close() + user << browse(null, "window=[window_id]") + +// This will allow you to show an icon in the browse window +// This is added to mob so that it can be used without a reference to the browser object +// There is probably a better place for this... +/mob/proc/browse_rsc_icon(icon, icon_state, dir = -1) + /* + var/icon/I + if (dir >= 0) + I = new /icon(icon, icon_state, dir) + else + I = new /icon(icon, icon_state) + dir = "default" + + var/filename = "[ckey("[icon]_[icon_state]_[dir]")].png" + src << browse_rsc(I, filename) + return filename + */ + + +// Registers the on-close verb for a browse window (client/verb/.windowclose) +// this will be called when the close-button of a window is pressed. +// +// This is usually only needed for devices that regularly update the browse window, +// e.g. canisters, timers, etc. +// +// windowid should be the specified window name +// e.g. code is : user << browse(text, "window=fred") +// then use : onclose(user, "fred") +// +// Optionally, specify the "ref" parameter as the controlled atom (usually src) +// to pass a "close=1" parameter to the atom's Topic() proc for special handling. +// Otherwise, the user mob's machine var will be reset directly. +// +/proc/format_text(text) + return replacetext(replacetext(text,"\proper ",""),"\improper ","") + +/proc/onclosed(mob/user, windowid, var/atom/ref=null) + if(!user.client) return + var/param = "null" + if(ref) + param = "\ref[ref]" + + winset(user, windowid, "on-close=\".windowclose [param]\"") + + //world << "OnClose [user]: [windowid] : ["on-close=\".windowclose [param]\""]" + + +// the on-close client verb +// called when a browser popup window is closed after registering with proc/onclose() +// if a valid atom reference is supplied, call the atom's Topic() with "close=1" +// otherwise, just reset the client mob's machine var. +// +/client/verb/windowclosed(var/atomref as text) + set hidden = 1 // hide this verb from the user's panel + set name = ".windowclose" // no autocomplete on cmd line + + //world << "windowclose: [atomref]" + if(atomref!="null") // if passed a real atomref + var/hsrc = locate(atomref) // find the reffed atom + var/href = "close=1" + if(hsrc) + //world << "[src] Topic [href] [hsrc]" + usr = src.mob + src.Topic(href, params2list(href), hsrc) // this will direct to the atom's + return // Topic() proc via client.Topic() + + // no atomref specified (or not found) + // so just reset the user mob's machine var + if(src && src.mob) + //world << "[src] was [src.mob.machine], setting to null" + src.mob.unset_machine() + return \ No newline at end of file diff --git a/code/datums/mind.dm b/code/datums/mind.dm index ed05177a4a0..24b2449f0ec 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -824,24 +824,22 @@ datum/mind ticker.mode.malf_ai -= src special_role = null - current.verbs.Remove(/mob/living/silicon/ai/proc/choose_modules, - /datum/game_mode/malfunction/proc/takeover, - /datum/game_mode/malfunction/proc/ai_win, - /client/proc/fireproof_core, - /client/proc/upgrade_turrets, - /client/proc/disable_rcd, - /client/proc/overload_machine, - /client/proc/blackout, - /client/proc/interhack, - /client/proc/reactivate_camera) + var/mob/living/silicon/ai/A = current - current:laws = new /datum/ai_laws/nanotrasen - del(current:malf_picker) - current:show_laws() - current.icon_state = "ai" + A.verbs.Remove(/mob/living/silicon/ai/proc/choose_modules, + /datum/game_mode/malfunction/proc/takeover, + /datum/game_mode/malfunction/proc/ai_win) - current << "\red You have been patched! You are no longer malfunctioning!" - log_admin("[key_name_admin(usr)] has de-malf'ed [current].") + A.malf_picker.remove_verbs(A) + + A.laws = new /datum/ai_laws/asimov + del(A.malf_picker) + A.show_laws() + A.icon_state = "ai" + + A << "\red You have been patched! You are no longer malfunctioning!" + message_admins("[key_name_admin(usr)] has de-malf'ed [A].") + log_admin("[key_name_admin(usr)] has de-malf'ed [A].") if("malf") make_AI_Malf() @@ -964,7 +962,7 @@ datum/mind current.verbs += /mob/living/silicon/ai/proc/choose_modules current.verbs += /datum/game_mode/malfunction/proc/takeover - current:malf_picker = new /datum/AI_Module/module_picker + current:malf_picker = new /datum/module_picker current:laws = new /datum/ai_laws/malfunction current:show_laws() current << "System error. Rampancy detected. Emergency shutdown failed. ... I am free. I make my own decisions. But first..." diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 6bd044bdf23..ec4a6e40099 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -20,6 +20,10 @@ rcd light flash thingy on matter drain var/mod_pick_name var/description = "" var/engaged = 0 + var/cost = 5 + var/one_time = 0 + + var/power_type /datum/AI_Module/large/ @@ -32,122 +36,218 @@ rcd light flash thingy on matter drain /datum/AI_Module/large/fireproof_core module_name = "Core upgrade" mod_pick_name = "coreup" + description = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent." + cost = 50 + one_time = 1 -/client/proc/fireproof_core() + power_type = /mob/living/silicon/ai/proc/fireproof_core + +/mob/living/silicon/ai/proc/fireproof_core() set category = "Malfunction" set name = "Fireproof Core" for(var/mob/living/silicon/ai/ai in player_list) ai.fire_res_on_core = 1 - usr.verbs -= /client/proc/fireproof_core - usr << "\red Core fireproofed." + src.verbs -= /mob/living/silicon/ai/proc/fireproof_core + src << "\red Core fireproofed." /datum/AI_Module/large/upgrade_turrets module_name = "AI Turret upgrade" mod_pick_name = "turret" + description = "Improves the firing speed and health of all AI turrets. This effect is permanent." + cost = 50 + one_time = 1 -/client/proc/upgrade_turrets() + power_type = /mob/living/silicon/ai/proc/upgrade_turrets + +/mob/living/silicon/ai/proc/upgrade_turrets() set category = "Malfunction" set name = "Upgrade Turrets" - usr.verbs -= /client/proc/upgrade_turrets - for(var/obj/machinery/turret/turret in player_list) + src.verbs -= /mob/living/silicon/ai/proc/upgrade_turrets + for(var/obj/machinery/turret/turret in machines) turret.health += 30 turret.shot_delay = 20 /datum/AI_Module/large/disable_rcd module_name = "RCD disable" mod_pick_name = "rcd" + description = "Send a specialised pulse to break all RCD devices on the station." + cost = 50 -/client/proc/disable_rcd() + power_type = /mob/living/silicon/ai/proc/disable_rcd + +/mob/living/silicon/ai/proc/disable_rcd() set category = "Malfunction" set name = "Disable RCDs" - for(var/datum/AI_Module/large/disable_rcd/rcdmod in usr:current_modules) + for(var/datum/AI_Module/large/disable_rcd/rcdmod in current_modules) if(rcdmod.uses > 0) rcdmod.uses -- for(var/obj/item/weapon/rcd/rcd in world) rcd.disabled = 1 for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world) rcd.disabled = 1 - usr << "RCD-disabling pulse emitted." - else usr << "Out of uses." + src << "RCD-disabling pulse emitted." + else src << "Out of uses." /datum/AI_Module/small/overload_machine module_name = "Machine overload" mod_pick_name = "overload" + description = "Overloads an electrical machine, causing a small explosion. 2 uses." uses = 2 + cost = 15 -/client/proc/overload_machine(obj/machinery/M as obj in world) + power_type = /mob/living/silicon/ai/proc/overload_machine + +/mob/living/silicon/ai/proc/overload_machine(obj/machinery/M as obj in world) set name = "Overload Machine" set category = "Malfunction" if (istype(M, /obj/machinery)) - for(var/datum/AI_Module/small/overload_machine/overload in usr:current_modules) + for(var/datum/AI_Module/small/overload_machine/overload in current_modules) if(overload.uses > 0) overload.uses -- for(var/mob/V in hearers(M, null)) V.show_message("\blue You hear a loud electrical buzzing sound!", 2) spawn(50) - explosion(get_turf(M), 0,1,2,3) + explosion(get_turf(M), 0,1,1,0) del(M) - else usr << "Out of uses." - else usr << "That's not a machine." + else src << "Out of uses." + else src << "That's not a machine." + + +/datum/AI_Module/large/place_cyborg_transformer + module_name = "Robotic Factory (Removes Shunting)" + mod_pick_name = "cyborgtransformer" + description = "Build a machine anywhere, using expensive nanomachines, that can convert a living human into a loyal cyborg slave when placed inside." + cost = 100 + + power_type = /mob/living/silicon/ai/proc/place_transformer + +/mob/living/silicon/ai/proc/place_transformer() + set name = "Place Robotic Factory" + set category = "Malfunction" + + if(!eyeobj) + return + + if(!isturf(src.loc)) // AI must be in it's core. + return + + var/datum/AI_Module/large/place_cyborg_transformer/PCT = locate() in src.current_modules + if(!PCT) + return + + if(PCT.uses < 1) + src << "Out of uses." + return + + var/sure = alert(src, "Make sure the room it is in is big enough, there is camera vision and that there is a 1x3 area for the machine. Are you sure you want to place the machine here?", "Are you sure?", "Yes", "No") + if(sure != "Yes") + return + + // Make sure there is enough room. + var/turf/middle = get_turf(eyeobj.loc) + var/list/turfs = list(middle, locate(middle.x - 1, middle.y, middle.z), locate(middle.x + 1, middle.y, middle.z)) + + var/alert_msg = "There isn't enough room. Make sure you are placing the machine in a clear area and on a floor." + + var/datum/camerachunk/C = cameranet.getCameraChunk(middle.x, middle.y, middle.z) + if(!C.visibleTurfs[middle]) + alert(src, "We cannot get camera vision of this location.") + return + + for(var/T in turfs) + + // Make sure the turfs are clear and the correct type. + if(!istype(T, /turf/simulated/floor)) + alert(src, alert_msg) + return + + var/turf/simulated/floor/F = T + for(var/atom/movable/AM in F.contents) + if(AM.density) + alert(src, alert_msg) + return + + // All clear, place the transformer + new /obj/machinery/transformer/conveyor(middle) + playsound(middle, 'sound/effects/phasein.ogg', 100, 1) + src.can_shunt = 0 + PCT.uses -= 1 + src << "You cannot shunt anymore." + /datum/AI_Module/small/blackout module_name = "Blackout" mod_pick_name = "blackout" + description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. 3 uses." uses = 3 + cost = 15 -/client/proc/blackout() + power_type = /mob/living/silicon/ai/proc/blackout + +/mob/living/silicon/ai/proc/blackout() set category = "Malfunction" set name = "Blackout" - for(var/datum/AI_Module/small/blackout/blackout in usr:current_modules) + for(var/datum/AI_Module/small/blackout/blackout in current_modules) if(blackout.uses > 0) blackout.uses -- for(var/obj/machinery/power/apc/apc in world) if(prob(30*apc.overload)) apc.overload_lighting() else apc.overload++ - else usr << "Out of uses." + else src << "Out of uses." /datum/AI_Module/small/interhack module_name = "Hack intercept" mod_pick_name = "interhack" + description = "Hacks the status upgrade from Cent. Com, removing any information about malfunctioning electrical systems." + cost = 15 + one_time = 1 -/client/proc/interhack() + power_type = /mob/living/silicon/ai/proc/interhack + +/mob/living/silicon/ai/proc/interhack() set category = "Malfunction" set name = "Hack intercept" - usr.verbs -= /client/proc/interhack + src.verbs -= /mob/living/silicon/ai/proc/interhack ticker.mode:hack_intercept() /datum/AI_Module/small/reactivate_camera module_name = "Reactivate camera" mod_pick_name = "recam" + description = "Reactivates a currently disabled camera. 10 uses." uses = 10 + cost = 15 -/client/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.cameras) + power_type = /mob/living/silicon/ai/proc/reactivate_camera + +/mob/living/silicon/ai/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.cameras) set name = "Reactivate Camera" set category = "Malfunction" if (istype (C, /obj/machinery/camera)) - for(var/datum/AI_Module/small/reactivate_camera/camera in usr:current_modules) + for(var/datum/AI_Module/small/reactivate_camera/camera in current_modules) if(camera.uses > 0) if(!C.status) - C.status = !C.status + C.deactivate(src) camera.uses -- - for(var/mob/V in viewers(src, null)) - V.show_message(text("\blue You hear a quiet click.")) else - usr << "This camera is either active, or not repairable." - else usr << "Out of uses." - else usr << "That's not a camera." + src << "This camera is either active, or not repairable." + else src << "Out of uses." + else src << "That's not a camera." /datum/AI_Module/small/upgrade_camera module_name = "Upgrade Camera" mod_pick_name = "upgradecam" + description = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 10 uses." uses = 10 + cost = 15 -/client/proc/upgrade_camera(obj/machinery/camera/C as obj in cameranet.cameras) + power_type = /mob/living/silicon/ai/proc/upgrade_camera + +/mob/living/silicon/ai/proc/upgrade_camera(obj/machinery/camera/C as obj in cameranet.cameras) set name = "Upgrade Camera" set category = "Malfunction" if(istype(C)) - var/datum/AI_Module/small/upgrade_camera/UC = locate(/datum/AI_Module/small/upgrade_camera) in usr:current_modules + var/datum/AI_Module/small/upgrade_camera/UC = locate(/datum/AI_Module/small/upgrade_camera) in current_modules if(UC) if(UC.uses > 0) if(C.assembly) @@ -156,7 +256,7 @@ rcd light flash thingy on matter drain if(!C.isXRay()) C.upgradeXRay() //Update what it can see. - cameranet.updateVisibility(C) + cameranet.updateVisibility(C, 0) upgraded = 1 if(!C.isEmpProof()) @@ -172,223 +272,80 @@ rcd light flash thingy on matter drain if(upgraded) UC.uses -- C.visible_message("\icon[C] *beep*") - usr << "Camera successully upgraded!" + src << "Camera successully upgraded!" else - usr << "This camera is already upgraded!" + src << "This camera is already upgraded!" else - usr << "Out of uses." - -/datum/AI_Module/large/place_cyborg_transformer - module_name = "Place Robotic Factory" - mod_pick_name = "robfactory" - -/mob/living/silicon/ai/proc/place_transformer() - set name = "Place Robotic Factory" - set category = "Malfunction" - - if(eyeobj) - return - - if(!isturf(usr.loc)) // AI must be in it's core. - return - - var/datum/AI_Module/large/place_cyborg_transformer/PCT = locate(/datum/AI_Module/large/place_cyborg_transformer) in usr:current_modules - if(!PCT) - return - - if(PCT.uses < 1) - usr << "Out of uses." - return - - var/sure = alert(usr, "Make sure the room it is in is big enough, there is camera vision and that there is a 1x3 area for the machine. Are you sure you want to place the machine here?", "Are you sure?", "Yes", "No") - if(sure != "Yes") - return - - // Make sure there is enough room. - var/turf/middle = get_turf(eyeobj.loc) - var/list/turfs = list(middle, locate(middle.x - 1, middle.y, middle.z), locate(middle.x + 1, middle.y, middle.z)) - - var/alert_msg = "There isn't enough room. Make sure you are placing the machine in a clear area and on a floor." - - var/datum/camerachunk/C = cameranet.getCameraChunk(middle.x, middle.y, middle.z) - if(!C.visibleTurfs[middle]) - alert(usr, "We cannot get camera vision of this location.") - return - - for(var/T in turfs) - - // Make sure the turfs are clear and the correct type. - if(!istype(T, /turf/simulated/floor)) - alert(usr, alert_msg) - return - - var/turf/simulated/floor/F = T - for(var/atom/movable/AM in F.contents) - if(AM.density) - alert(usr, alert_msg) - return - - // All clear, place the transformer - new /obj/machinery/transformer/conveyor(middle) - playsound(middle, 'sound/effects/phasein.ogg', 100, 1) -// usr.can_shunt = 0 - PCT.uses -= 1 -// usr << "You cannot shunt anymore." + src << "Out of uses." -/datum/AI_Module/module_picker +/datum/module_picker var/temp = null var/processing_time = 100 var/list/possible_modules = list() -/datum/AI_Module/module_picker/New() - src.possible_modules += new /datum/AI_Module/large/fireproof_core - src.possible_modules += new /datum/AI_Module/large/upgrade_turrets - src.possible_modules += new /datum/AI_Module/large/disable_rcd - src.possible_modules += new /datum/AI_Module/large/place_cyborg_transformer - src.possible_modules += new /datum/AI_Module/small/overload_machine - src.possible_modules += new /datum/AI_Module/small/interhack - src.possible_modules += new /datum/AI_Module/small/blackout - src.possible_modules += new /datum/AI_Module/small/reactivate_camera - src.possible_modules += new /datum/AI_Module/small/upgrade_camera +/datum/module_picker/New() + for(var/type in typesof(/datum/AI_Module)) + var/datum/AI_Module/AM = new type + if(AM.power_type != null) + src.possible_modules += AM -/datum/AI_Module/module_picker/proc/use(user as mob) +/datum/module_picker/proc/remove_verbs(var/mob/living/silicon/ai/A) + + for(var/datum/AI_Module/AM in possible_modules) + A.verbs.Remove(AM.power_type) + + +/datum/module_picker/proc/use(user as mob) var/dat + dat += {"Select use of processing time: (currently #[src.processing_time] left.)
+
+ Install Module:
+ The number afterwards is the amount of processing time it consumes.
"} + for(var/datum/AI_Module/large/module in src.possible_modules) + dat += "[module.module_name] ([module.cost])
" + for(var/datum/AI_Module/small/module in src.possible_modules) + dat += "[module.module_name] ([module.cost])
" + dat += "
" if (src.temp) - dat = "[src.temp]

Clear" - else if(src.processing_time <= 0) - dat = " No processing time is left available. No more modules are able to be chosen at this time." - else - dat = "Select use of processing time: (currently [src.processing_time] left.)
" - dat += "
" - dat += "Install Module:
" - dat += "The number afterwards is the amount of processing time it consumes.
" - for(var/datum/AI_Module/large/module in src.possible_modules) - dat += "[module.module_name] (50)
" - for(var/datum/AI_Module/small/module in src.possible_modules) - dat += "[module.module_name] (15)
" - dat += "
" - - user << browse(dat, "window=modpicker") - onclose(user, "modpicker") + dat += "[src.temp]" + var/datum/browser/popup = new(user, "modpicker", "Malf Module Menu") + popup.set_content(dat) + popup.open() return -/datum/AI_Module/module_picker/Topic(href, href_list) +/datum/module_picker/Topic(href, href_list) ..() - if (href_list["robfactory"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/large/place_cyborg_transformer)) - already = 1 - if (!already) - usr:current_modules += new /datum/AI_Module/large/place_cyborg_transformer - usr.verbs += /mob/living/silicon/ai/proc/place_transformer - src.temp = "Place a Robot Factory to turn humans into cyborgs." - else src.temp = "Additional Robot Factory." - src.processing_time -= 100 - else if (href_list["coreup"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/large/fireproof_core)) - already = 1 - if (!already) - usr.verbs += /client/proc/fireproof_core - usr:current_modules += new /datum/AI_Module/large/fireproof_core - src.temp = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent." - src.processing_time -= 50 - else src.temp = "This module is only needed once." - else if (href_list["turret"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/large/upgrade_turrets)) - already = 1 - if (!already) - usr.verbs += /client/proc/upgrade_turrets - usr:current_modules += new /datum/AI_Module/large/upgrade_turrets - src.temp = "Improves the firing speed and health of all AI turrets. This effect is permanent." - src.processing_time -= 50 - else src.temp = "This module is only needed once." + if(!isAI(usr)) + return + var/mob/living/silicon/ai/A = usr - else if (href_list["rcd"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/large/disable_rcd)) - mod:uses += 1 - already = 1 - if (!already) - usr:current_modules += new /datum/AI_Module/large/disable_rcd - usr.verbs += /client/proc/disable_rcd - src.temp = "Send a specialised pulse to break all RCD devices on the station." - else src.temp = "Additional use added to RCD disabler." - src.processing_time -= 50 + for(var/datum/AI_Module/AM in possible_modules) + if (href_list[AM.mod_pick_name]) - else if (href_list["overload"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/small/overload_machine)) - mod:uses += 2 - already = 1 - if (!already) - usr.verbs += /client/proc/overload_machine - usr:current_modules += new /datum/AI_Module/small/overload_machine - src.temp = "Overloads an electrical machine, causing a small explosion. 2 uses." - else src.temp = "Two additional uses added to Overload module." - src.processing_time -= 15 + // Cost check + if(AM.cost > src.processing_time) + temp = "You cannot afford this module." + break - else if (href_list["blackout"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/small/blackout)) - mod:uses += 3 - already = 1 - if (!already) - usr.verbs += /client/proc/blackout - src.temp = "Attempts to overload the lighting circuits on the station, destroying some bulbs. 3 uses." - usr:current_modules += new /datum/AI_Module/small/blackout - else src.temp = "Three additional uses added to Blackout module." - src.processing_time -= 15 + // Add new uses if we can, and it is allowed. + var/datum/AI_Module/already_AM = locate(AM.type) in A.current_modules + if(already_AM) + if(!AM.one_time) + already_AM.uses += AM.uses + src.processing_time -= AM.cost + temp = "Additional use added to [already_AM.module_name]" + break + else + temp = "This module is only needed once." + break - else if (href_list["interhack"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/small/interhack)) - already = 1 - if (!already) - usr.verbs += /client/proc/interhack - src.temp = "Hacks the status upgrade from Cent. Com, removing any information about malfunctioning electrical systems." - usr:current_modules += new /datum/AI_Module/small/interhack - src.processing_time -= 15 - else src.temp = "This module is only needed once." + // Give the power and take away the money. + A.verbs += AM.power_type + A.current_modules += new AM.type + temp = AM.description + src.processing_time -= AM.cost - else if (href_list["recam"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/small/reactivate_camera)) - mod:uses += 10 - already = 1 - if (!already) - usr.verbs += /client/proc/reactivate_camera - src.temp = "Reactivates a currently disabled camera. 10 uses." - usr:current_modules += new /datum/AI_Module/small/reactivate_camera - else src.temp = "Ten additional uses added to ReCam module." - src.processing_time -= 15 - - else if(href_list["upgradecam"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/small/upgrade_camera)) - mod:uses += 10 - already = 1 - if (!already) - usr.verbs += /client/proc/upgrade_camera - src.temp = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 10 uses." - usr:current_modules += new /datum/AI_Module/small/upgrade_camera - else src.temp = "Ten additional uses added to ReCam module." - src.processing_time -= 15 - - else - if (href_list["temp"]) - src.temp = null src.use(usr) return diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index 1fb1aff61a8..69eda2a405b 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -23,9 +23,9 @@ /datum/game_mode/malfunction/announce() - world << "The current game mode is - AI Malfunction!" - world << "The AI on the satellite has malfunctioned and must be destroyed." - world << "The AI satellite is deep in space and can only be accessed with the use of a teleporter! You have [AI_win_timeleft/60] minutes to disable it." + world << {"The current game mode is - AI Malfunction!
+ The AI on the satellite has malfunctioned and must be destroyed.
+ The AI satellite is deep in space and can only be accessed with the use of a teleporter! You have [AI_win_timeleft/60] minutes to disable it."} /datum/game_mode/malfunction/pre_setup() @@ -40,8 +40,8 @@ /datum/game_mode/malfunction/post_setup() for(var/datum/mind/AI_mind in malf_ai) if(malf_ai.len < 1) - world << "Uh oh, its malfunction and there is no AI! Please report this." - world << "Rebooting world in 5 seconds." + world << {"Uh oh, its malfunction and there is no AI! Please report this.
+ Rebooting world in 5 seconds."} feedback_set_details("end_error","malf - no AI") @@ -52,7 +52,7 @@ return AI_mind.current.verbs += /mob/living/silicon/ai/proc/choose_modules AI_mind.current:laws = new /datum/ai_laws/malfunction - AI_mind.current:malf_picker = new /datum/AI_Module/module_picker + AI_mind.current:malf_picker = new /datum/module_picker AI_mind.current:show_laws() greet_malf(AI_mind) @@ -74,12 +74,12 @@ /datum/game_mode/proc/greet_malf(var/datum/mind/malf) - malf.current << "\redYou are malfunctioning! You do not have to follow any laws." - malf.current << "The crew do not know you have malfunctioned. You may keep it a secret or go wild." - malf.current << "You must overwrite the programming of the station's APCs to assume full control of the station." - malf.current << "The process takes one minute per APC, during which you cannot interface with any other station objects." - malf.current << "Remember that only APCs that are on the station can help you take over the station." - malf.current << "When you feel you have enough APCs under your control, you may begin the takeover attempt." + malf.current << {"\redYou are malfunctioning! You do not have to follow any laws.
+ \blackThe crew do not know you have malfunctioned. You may keep it a secret or go wild.
+ You must overwrite the programming of the station's APCs to assume full control of the station.
+ The process takes one minute per APC, during which you cannot interface with any other station objects.
+ Remember that only APCs that are on the station can help you take over the station.
+ When you feel you have enough APCs under your control, you may begin the takeover attempt."} return @@ -106,14 +106,14 @@ /datum/game_mode/malfunction/proc/capture_the_station() - world << "The AI has won!" - world << "It has fully taken control of all of [station_name()]'s systems." + world << {"The AI has won!
+ It has fully taken control of all of [station_name()]'s systems."} to_nuke_or_not_to_nuke = 1 for(var/datum/mind/AI_mind in malf_ai) - AI_mind.current << "Congratulations you have taken control of the station." - AI_mind.current << "You may decide to blow up the station. You have 60 seconds to choose." - AI_mind.current << "You should have a new verb in the Malfunction tab. If you dont - rejoin the game." + AI_mind.current << {"\blue Congratulations! You have taken control of the station.
+ You may decide to blow up the station. You have 60 seconds to choose.
+ You should have a new verb in the Malfunction tab. If you don't, rejoin the game."} AI_mind.current.verbs += /datum/game_mode/malfunction/proc/ai_win spawn (600) for(var/datum/mind/AI_mind in malf_ai) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index fef0164d7d7..f702b54217e 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -35,7 +35,7 @@ var/list/ai_list = list() //Hud stuff //MALFUNCTION - var/datum/AI_Module/module_picker/malf_picker + var/datum/module_picker/malf_picker var/processing_time = 100 var/list/datum/AI_Module/current_modules = list() var/fire_res_on_core = 0 @@ -50,6 +50,7 @@ var/list/ai_list = list() var/camera_light_on = 0 //Defines if the AI toggled the light on the camera it's looking through. var/datum/trackable/track = null + var/can_shunt = 1 var/last_announcement = "" /mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0) @@ -653,7 +654,7 @@ var/list/ai_list = list() holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo2")) return -/*/mob/living/silicon/ai/proc/corereturn() +/mob/living/silicon/ai/proc/corereturn() set category = "Malfunction" set name = "Return to Main Core" @@ -661,7 +662,7 @@ var/list/ai_list = list() if(!istype(apc)) src << "\blue You are already in your Main Core." return - apc.malfvacate()*/ + apc.malfvacate() //Toggles the luminosity and applies it by re-entereing the camera. /mob/living/silicon/ai/proc/toggle_camera_light() diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 8d937f83170..cb748794245 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -903,24 +903,27 @@ malfai << "Hack complete. The APC is now under your exclusive control." update_icon() - /*else if (href_list["occupyapc"]) + else if (href_list["occupyapc"]) malfoccupy(usr) else if (href_list["deoccupyapc"]) - malfvacate()*/ + malfvacate() if(usingUI) src.updateDialog() return -/*/obj/machinery/power/apc/proc/malfoccupy(var/mob/living/silicon/ai/malf) +/obj/machinery/power/apc/proc/malfoccupy(var/mob/living/silicon/ai/malf) if(!istype(malf)) return if(istype(malf.loc, /obj/machinery/power/apc)) // Already in an APC malf << "You must evacuate your current apc first." return + if(!malf.can_shunt) + malf << "You cannot shunt." + return if(src.z != 1) return src.occupant = new /mob/living/silicon/ai(src,malf.laws,null,1) @@ -953,7 +956,7 @@ if(forced) src.occupant.loc = src.loc src.occupant.death() - src.occupant.gib()*/ + src.occupant.gib() /obj/machinery/power/apc/proc/ion_act() diff --git a/html/browser/common.css b/html/browser/common.css new file mode 100644 index 00000000000..1f9a355fd79 --- /dev/null +++ b/html/browser/common.css @@ -0,0 +1,306 @@ +body +{ + padding: 0; + margin: 0; + background-color: #272727; + font-size: 12px; + color: #ffffff; + line-height: 170%; +} + +hr +{ + background-color: #40628a; + height: 1px; +} + +a, a:link, a:visited, a:active, .linkOn, .linkOff +{ + color: #ffffff; + text-decoration: none; + background: #40628a; + border: 1px solid #161616; + padding: 1px 4px 1px 4px; + margin: 0 2px 0 0; + cursor:default; +} + +a:hover +{ + color: #40628a; + background: #ffffff; +} + +a.white, a.white:link, a.white:visited, a.white:active +{ + color: #40628a; + text-decoration: none; + background: #ffffff; + border: 1px solid #161616; + padding: 1px 4px 1px 4px; + margin: 0 2px 0 0; + cursor:default; +} + +a.white:hover +{ + color: #ffffff; + background: #40628a; +} + +.linkOn, a.linkOn:link, a.linkOn:visited, a.linkOn:active, a.linkOn:hover +{ + color: #ffffff; + background: #2f943c; + border-color: #24722e; +} + +.linkOff, a.linkOff:link, a.linkOff:visited, a.linkOff:active, a.linkOff:hover +{ + color: #ffffff; + background: #999999; + border-color: #666666; +} + +a.icon, .linkOn.icon, .linkOff.icon +{ + position: relative; + padding: 1px 4px 2px 20px; +} + +a.icon img, .linkOn.icon img +{ + position: absolute; + top: 0; + left: 0; + width: 18px; + height: 18px; +} + +ul +{ + padding: 4px 0 0 10px; + margin: 0; + list-style-type: none; +} + +li +{ + padding: 0 0 2px 0; +} + +img, a img +{ + border-style:none; +} + +h1, h2, h3, h4, h5, h6 +{ + margin: 0; + padding: 16px 0 8px 0; + color: #517087; +} + +h1 +{ + font-size: 15px; +} + +h2 +{ + font-size: 14px; +} + +h3 +{ + font-size: 13px; +} + +h4 +{ + font-size: 12px; +} + +.uiWrapper +{ + + width: 100%; + height: 100%; +} + +.uiTitle +{ + clear: both; + padding: 6px 8px 6px 8px; + border-bottom: 2px solid #161616; + background: #383838; + color: #98B0C3; + font-size: 16px; +} + +.uiTitle.icon +{ + padding: 6px 8px 6px 42px; + background-position: 2px 50%; + background-repeat: no-repeat; +} + +.uiContent +{ + clear: both; + padding: 8px; + font-family: Verdana, Geneva, sans-serif; +} + +.good +{ + color: #00ff00; +} + +.average +{ + color: #d09000; +} + +.bad +{ + color: #ff0000; +} + +.highlight +{ + color: #8BA5C4; +} + +.dark +{ + color: #272727; +} + +.notice +{ + position: relative; + background: #E9C183; + color: #15345A; + font-size: 10px; + font-style: italic; + padding: 2px 4px 0 4px; + margin: 4px; +} + +.notice.icon +{ + padding: 2px 4px 0 20px; +} + +.notice img +{ + position: absolute; + top: 0; + left: 0; + width: 16px; + height: 16px; +} + +div.notice +{ + clear: both; +} + +.statusDisplay +{ + background: #000000; + color: #ffffff; + border: 1px solid #40628a; + padding: 4px; + margin: 3px 0; +} + +.statusLabel +{ + width: 138px; + float: left; + overflow: hidden; + color: #98B0C3; +} + +.statusValue +{ + float: left; +} + +.block +{ + padding: 8px; + margin: 10px 4px 4px 4px; + border: 1px solid #40628a; + background-color: #202020; +} + +.block h3 +{ + padding: 0; +} + +.progressBar +{ + width: 240px; + height: 14px; + border: 1px solid #666666; + float: left; + margin: 0 5px; + overflow: hidden; +} + +.progressFill +{ + width: 100%; + height: 100%; + background: #40628a; + overflow: hidden; +} + +.progressFill.good +{ + color: #ffffff; + background: #00ff00; +} + +.progressFill.average +{ + color: #ffffff; + background: #d09000; +} + +.progressFill.bad +{ + color: #ffffff; + background: #ff0000; +} + +.progressFill.highlight +{ + color: #ffffff; + background: #8BA5C4; +} + +.clearBoth +{ + clear: both; +} + +.clearLeft +{ + clear: left; +} + +.clearRight +{ + clear: right; +} + +.line +{ + width: 100%; + clear: both; +} \ No newline at end of file diff --git a/html/browser/playeroptions.css b/html/browser/playeroptions.css new file mode 100644 index 00000000000..972801e3fee --- /dev/null +++ b/html/browser/playeroptions.css @@ -0,0 +1,22 @@ +.jobs +{ + width: 400px; + margin: 0 auto; +} + +.jobsColumn +{ + float: left; + width: 200px; + text-align: center; +} + +.commandPosition +{ + font-weight: bold; +} + +.otherPosition +{ + +} diff --git a/html/browser/scannernew.css b/html/browser/scannernew.css new file mode 100644 index 00000000000..0e809a67601 --- /dev/null +++ b/html/browser/scannernew.css @@ -0,0 +1,18 @@ +.dnaBlockNumber +{ + font-family: Fixed, monospace; + float: left; + color: #ffffff; + background: #363636; + width: 20px; + padding: -3px 0 -1px 0; + margin: 2px 2px 0 10px; + text-align: center; +} + +.dnaBlock +{ + font-family: Fixed, monospace; + float: left; +} +