diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index 080cd1f72fa..bb05efc975a 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -9,8 +9,9 @@ #define MIDROUND_ANTAG 64 #define SOUND_INSTRUMENTS 128 #define SOUND_SHIP_AMBIENCE 256 +#define SOUND_PRAYERS 512 -#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE) +#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE|SOUND_PRAYERS) //Chat toggles #define CHAT_OOC 1 @@ -42,4 +43,4 @@ #define BE_GANG 4096 #define BE_SHADOWLING 8192 #define BE_ABDUCTOR 16384 -#define BE_REVENANT 32768 \ No newline at end of file +#define BE_REVENANT 32768 diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 9945a13fcad..33b781ad4f8 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -76,12 +76,12 @@ // Used to get a properly sanitized input, of max_length /proc/stripped_input(var/mob/user, var/message = "", var/title = "", var/default = "", var/max_length=MAX_MESSAGE_LEN) var/name = input(user, message, title, default) as text|null - return strip_html_properly(name, max_length) + return html_encode(trim(name, max_length)) //trim is "inside" because html_encode can expand single symbols into multiple symbols (such as turning < into <) // Used to get a properly sanitized multiline input, of max_length /proc/stripped_multiline_input(var/mob/user, var/message = "", var/title = "", var/default = "", var/max_length=MAX_MESSAGE_LEN) var/name = input(user, message, title, default) as message|null - return strip_html_properly(name, max_length) + return html_encode(trim(name, max_length)) //Filters out undesirable characters from names /proc/reject_bad_name(var/t_in, var/allow_numbers=0, var/max_length=MAX_NAME_LEN) @@ -147,56 +147,7 @@ return t_out -//this proc strips html properly, this means that it removes everything between < and >, and between "http" and "://" -//also limit the size of the input, if specified to -/proc/strip_html_properly(var/input,var/max_length=MAX_MESSAGE_LEN) - if(!input) - return - - if(max_length) - input = copytext(input,1,max_length) - - var/sanitized_output - var/next_html_tag = findtext(input, "<") - var/next_http = findtext(input, "http", 1, next_html_tag) - - //the opening and closing of the expression to skip, e.g '<' and '>' - var/opening = non_zero_min(next_html_tag, next_http) - var/closing - - sanitized_output = copytext(input, 1, opening) - - while(next_html_tag || next_http) - - //we treat < ... > - if(opening == next_html_tag) - closing = findtext(input, ">", opening + 1) - if(closing) - next_html_tag = findtext(input, "<", closing) - next_http = findtext(input, "http", closing, next_html_tag) - else //no matching ">" - next_html_tag = 0 - - //we treat "http(s)://" - else - closing = findtext(input, "://", opening + 1) - if(closing) - closing += 2 //skip these extra // - next_http = findtext(input, "http", closing) - next_html_tag = findtext(input, "<", closing, next_http) - else //no matching "://" - next_http = 0 - - //check if we've something to skip - if(closing) - opening = non_zero_min(next_html_tag, next_http) - sanitized_output += copytext(input, closing + 1, opening) - - sanitized_output += copytext(input, opening) //don't forget the remaining text - - return sanitized_output - -//strip_html_properly helper proc that returns the smallest non null of two numbers +//html_encode helper proc that returns the smallest non null of two numbers //or 0 if they're both null (needed because of findtext returning 0 when a value is not present) /proc/non_zero_min(var/a, var/b) if(!a) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 4e82f172059..1ade7e383e6 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -987,25 +987,8 @@ Turf and target are seperate in case you want to teleport some distance from a t /proc/get_turf(atom/A) if (!istype(A)) return - if (isturf(A)) - return A - - var/list/atom/checked_turf_candidates = list() //prevent recursion from badmins being dumbasses - var/atom/turf_candidate = A.loc - - while (!isturf(turf_candidate)) - if (!turf_candidate || turf_candidate in checked_turf_candidates) - return - checked_turf_candidates += turf_candidate - - //SO I BET YOU MIGHT BE WONDERING WHY I'M CHECKING THIS AGAIN. - //I'LL FUCKING TELL YOU WAY, ITS BECAUSE FOR SOME GOD DAMN REASON, WHEN THIS IS CALLED - //IN AN OBJECT'S NEW() PROC, THE FIRST CHECK WILL FUCKING PASS, BUT FUCKING RUNTIME HERE - //BITCHING ABOUT HOW IT CAN'T READ NULL.LOC, SO FUCK IT, WE CHECK THIS TWICE. - if (!turf_candidate) - return - turf_candidate = turf_candidate.loc - return turf_candidate + for(A, A && !isturf(A), A=A.loc); //semicolon is for the empty statement + return A //Gets the turf this atom's *ICON* appears to inhabit diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index c250dc1d2d9..e442f74d14f 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -160,6 +160,8 @@ var/aggressive_changelog = 0 + var/reactionary_explosions = 0 //If we use reactionary explosions, explosions that react to walls and doors + /datum/configuration/New() var/list/L = typesof(/datum/game_mode) - /datum/game_mode for(var/T in L) @@ -485,6 +487,8 @@ config.no_summon_magic = 1 if("no_summon_events") config.no_summon_events = 1 + if("reactionary_explosions") + config.reactionary_explosions = 1 else diary << "Unknown setting in configuration: '[name]'" diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 5cff548b620..838bcde4e26 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -9,6 +9,7 @@ var/global/datum/controller/game_controller/master_controller = new() var/processing_interval = 1 //The minimum length of time between MC ticks (in deciseconds). The highest this can be without affecting schedules, is the GCD of all subsystem var/wait. Set to 0 to disable all processing. var/iteration = 0 var/cost = 0 + var/SSCostPerSecond = 0 var/last_thing_processed var/list/subsystems = list() @@ -60,7 +61,8 @@ calculate the longest number of ticks the MC can wait between each cycle without for(var/datum/subsystem/S in subsystems) S.Initialize(world.timeofday, zlevel) sleep(-1) - + for(var/datum/subsystem/S in subsystems) + S.AfterInitialize(zlevel) world << "Initializations complete" world.log << "Initializations complete" @@ -89,10 +91,11 @@ calculate the longest number of ticks the MC can wait between each cycle without ++iteration start_time = world.timeofday - + var/SubSystemRan = 0 for(var/datum/subsystem/SS in subsystems) if(SS.can_fire > 0) if(SS.next_fire <= world.time) + SubSystemRan = 1 timer = world.timeofday last_thing_processed = SS.type SS.last_fire = world.time @@ -100,7 +103,9 @@ calculate the longest number of ticks the MC can wait between each cycle without SS.cost = MC_AVERAGE(SS.cost, world.timeofday - timer) if (SS.dynamic_wait) var/oldwait = SS.wait - SS.wait = min(max(round(SS.cost*SS.dwait_delta, 0.1),SS.dwait_lower),SS.dwait_upper) + var/GlobalCostDelta = (SSCostPerSecond-(SS.cost/SS.wait))/(SS.wait/10)-1 + var/NewWait = MC_AVERAGE(oldwait,(SS.cost-1.5+GlobalCostDelta)*SS.dwait_delta) + SS.wait = Clamp(round(NewWait,0.1),SS.dwait_lower,SS.dwait_upper) if (oldwait != SS.wait) calculateGCD() SS.next_fire += SS.wait @@ -109,11 +114,20 @@ calculate the longest number of ticks the MC can wait between each cycle without sleep(-1) cost = MC_AVERAGE(cost, world.timeofday - start_time) - + if (SubSystemRan) + calculateSScost() sleep(processing_interval) else sleep(50) +/datum/controller/game_controller/proc/calculateSScost() + var/newcost = 0 + for(var/datum/subsystem/SS in subsystems) + if (!SS.can_fire) + continue + newcost += SS.cost/(SS.wait/10) + SSCostPerSecond = MC_AVERAGE(SSCostPerSecond,newcost) + #undef MC_AVERAGE /datum/controller/game_controller/proc/roundHasStarted() diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index 5c74da6d84d..969e2fa6d97 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -3,7 +3,6 @@ var/datum/subsystem/air/SSair /datum/subsystem/air name = "Air" priority = 20 - cost = 5 wait = 5 dynamic_wait = 1 dwait_lower = 5 @@ -56,10 +55,12 @@ var/datum/subsystem/air/SSair /datum/subsystem/air/Initialize(timeofday, zlevel) - setup_allturfs(zlevel) setup_atmos_machinery(zlevel) ..() +/datum/subsystem/air/AfterInitialize(zlevel) + setup_allturfs(zlevel) + #define MC_AVERAGE(average, current) (0.8*(average) + 0.2*(current)) /datum/subsystem/air/fire() var/timer = world.timeofday @@ -167,15 +168,14 @@ var/datum/subsystem/air/SSair EG.dismantle() /datum/subsystem/air/proc/setup_allturfs(z_level) + active_turfs.Cut() var/z_start = 1 var/z_finish = world.maxz if(1 <= z_level && z_level <= world.maxz) z_level = round(z_level) z_start = z_level z_finish = z_level - var/list/turfs_to_init = block(locate(1, 1, z_start), locate(world.maxx, world.maxy, z_finish)) - for(var/turf/simulated/T in turfs_to_init) T.CalculateAdjacentTurfs() if(!T.blocks_air) @@ -195,6 +195,8 @@ var/datum/subsystem/air/SSair if(!T.air.check_turf_total(enemy_tile)) T.excited = 1 active_turfs |= T + if(active_turfs.len) + warning("There are [active_turfs.len] active turfs at roundstart, this is a mapping error caused by a difference of the air between the adjacent turfs.") /datum/subsystem/air/proc/setup_atmos_machinery(z_level) for (var/obj/machinery/atmospherics/AM in atmos_machinery) diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index a99ac70899f..352caeb6195 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -5,9 +5,11 @@ var/datum/subsystem/garbage_collector/SSgarbage can_fire = 1 wait = 5 priority = -1 + dynamic_wait = 1 + dwait_delta = 5 var/collection_timeout = 300// deciseconds to wait to let running procs finish before we just say fuck it and force del() the object - var/max_run_time = 2 // how long, in deciseconds, can we run before waiting for the next tick + var/max_run_time = 1 // how long, in deciseconds, can we run before waiting for the next tick var/delslasttick = 0 // number of del()'s we've done this tick var/gcedlasttick = 0 // number of things that gc'ed last tick var/totaldels = 0 diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index c2a0c3df334..cd74bb16b84 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -7,6 +7,7 @@ var/datum/subsystem/lighting/SSlighting wait = 5 priority = 1 dynamic_wait = 1 + dwait_delta = 1 var/list/changed_lights = list() //list of all datum/light_source that need updating var/changed_lights_workload = 0 //stats on the largest number of lights (max changed_lights.len) diff --git a/code/controllers/subsystem/shuttles.dm b/code/controllers/subsystem/shuttles.dm index 7392c98ec88..f2598097565 100644 --- a/code/controllers/subsystem/shuttles.dm +++ b/code/controllers/subsystem/shuttles.dm @@ -109,7 +109,7 @@ var/datum/subsystem/shuttle/SSshuttle user << "The emergency shuttle has been disabled by Centcom." return - call_reason = strip_html_properly(trim(call_reason)) + call_reason = html_encode(trim(call_reason)) if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH) user << "You must provide a reason." diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 4d80d74daae..fa6db81352b 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -417,5 +417,5 @@ var/datum/subsystem/ticker/ticker /datum/subsystem/ticker/proc/send_random_tip() var/list/randomtips = file2list("config/tips.txt") if(randomtips.len) - world << "Tip of the round: [strip_html_properly(pick(randomtips))]" + world << "Tip of the round: [html_encode(pick(randomtips))]" diff --git a/code/controllers/subsystems.dm b/code/controllers/subsystems.dm index 5e10dcbcfd6..777bc2e5a1e 100644 --- a/code/controllers/subsystems.dm +++ b/code/controllers/subsystems.dm @@ -37,6 +37,9 @@ world << "[msg]" world.log << msg +/datum/subsystem/proc/AfterInitialize() + return + //hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc. /datum/subsystem/proc/stat_entry(msg) var/dwait = "" diff --git a/code/datums/spells/lichdom.dm b/code/datums/spells/lichdom.dm new file mode 100644 index 00000000000..a6ace565803 --- /dev/null +++ b/code/datums/spells/lichdom.dm @@ -0,0 +1,108 @@ +/obj/effect/proc_holder/spell/targeted/lichdom + name = "Bind Soul" + desc = "A dark necromantic pact that can forever bind your soul to an item of your choosing. So long as both your body and the item remain intact you can revive from death, though the time between reincarnations grows steadily with use." + school = "necromancy" + charge_max = 10 + clothes_req = 0 + centcom_cancast = 0 + invocation = "NECREM IMORTIUM!" + invocation_type = "shout" + range = -1 + level_max = 0 //cannot be improved + cooldown_min = 10 + include_user = 1 + + var/obj/marked_item + var/mob/living/current_body + + action_icon_state = "skeleton" + +/obj/effect/proc_holder/spell/targeted/lichdom/New() + if(ticker.mode.round_ends_with_antag_death) + ticker.mode.round_ends_with_antag_death = 0 + + ..() +/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets) + for(var/mob/user in targets) + var/list/hand_items = list() + if(iscarbon(user)) + hand_items = list(user.get_active_hand(),user.get_inactive_hand()) + + if(marked_item && !stat_allowed) //sanity, shouldn't happen without badminry + marked_item = null + return + + if(stat_allowed) //Death is not my end! + if(user.stat == CONSCIOUS && iscarbon(user)) + user << "You aren't dead enough to revive!" //Usually a good problem to have + charge_counter = charge_max + return + + if(!marked_item.loc) //Wait nevermind + user << "Your phylactery is gone!" + return + + if(isobserver(user)) + var/mob/dead/observer/O = user + O.reenter_corpse() + + var/mob/living/carbon/human/lich = new /mob/living/carbon/human(get_turf(marked_item)) + + lich.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(lich), slot_shoes) + lich.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(lich), slot_w_uniform) + lich.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(lich), slot_wear_suit) + lich.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(lich), slot_head) + + lich.real_name = user.mind.name + user.mind.transfer_to(lich) + hardset_dna(lich,null,null,lich.real_name,null,/datum/species/skeleton) + lich << "Your bones clatter and shutter as they're pulled back into this world!" + charge_max += 600 + var/mob/old_body = current_body + current_body = lich + lich.Weaken(10) + + if(old_body && old_body.loc) + if(iscarbon(old_body)) + var/mob/living/carbon/C = old_body + for(var/obj/item/W in C) + C.unEquip(W) + var/wheres_wizdo = dir2text(get_dir(get_turf(old_body), get_turf(marked_item))) + if(wheres_wizdo) + old_body.visible_message("Suddenly [old_body.name]'s corpse falls to pieces! You see a strange energy rise from the remains, and speed off towards the [wheres_wizdo]!") + old_body.dust() + + if(!marked_item) //linking item to the spell + message = "" + for(var/obj/item in hand_items) + if(ABSTRACT in item.flags || NODROP in item.flags) + continue + marked_item = item + user << "You begin to focus your very being into the [item.name]..." + break + + if(!marked_item) + user << "You must hold an item you wish to make your phylactery..." + + spawn(50) + if(marked_item.loc != user) //I changed my mind I don't want to put my soul in a cheeseburger! + user << "Your soul snaps back to your body as you drop the [marked_item.name]!" + marked_item = null + return + name = "RISE!" + desc = "Rise from the dead! You will reform at the location of your phylactery and your old body will crumble away." + charge_max = 1800 //3 minute cooldown, if you rise in sight of someone and killed again, you're probably screwed. + charge_counter = 1800 + stat_allowed = 1 + marked_item.name = "Ensouled [marked_item.name]" + marked_item.desc = "A terrible aura surrounds this item, its very existence is offensive to life itself..." + marked_item.color = "#003300" + user << "With a hideous feeling of emptiness you watch in horrified fascination as skin sloughs off bone! Blood boils, nerves disintegrate, eyes boil in their sockets! As your organs crumble to dust in your fleshless chest you come to terms with your choice. You're a lich!" + hardset_dna(user, null, null, null, null, /datum/species/skeleton) + current_body = user.mind.current + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.unEquip(H.wear_suit) + H.unEquip(H.head) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), slot_head) \ No newline at end of file diff --git a/code/datums/spells/summonitem.dm b/code/datums/spells/summonitem.dm index e74ce4a92c6..7b29e448844 100644 --- a/code/datums/spells/summonitem.dm +++ b/code/datums/spells/summonitem.dm @@ -7,7 +7,7 @@ invocation = "GAR YOK" invocation_type = "whisper" range = -1 - level_max = 1 //cannot be improved + level_max = 0 //cannot be improved cooldown_min = 100 include_user = 1 diff --git a/code/datums/wires/camera.dm b/code/datums/wires/camera.dm deleted file mode 100644 index 33f8c1421a5..00000000000 --- a/code/datums/wires/camera.dm +++ /dev/null @@ -1,76 +0,0 @@ -// Wires for cameras. - -/datum/wires/camera - random = 0 - holder_type = /obj/machinery/camera - wire_count = 6 - -/datum/wires/camera/GetInteractWindow() - - . = ..() - var/obj/machinery/camera/C = holder - . += "
\n[(C.view_range == initial(C.view_range) ? "The focus light is on." : "The focus light is off.")]" - . += "
\n[(C.can_use() ? "The power link light is on." : "The power link light is off.")]" - . += "
\n[(C.light_disabled ? "The camera light is off." : "The camera light is on.")]" - . += "
\n[(C.alarm_on ? "The alarm light is on." : "The alarm light is off.")]" - return . - -/datum/wires/camera/CanUse(var/mob/living/L) - var/obj/machinery/camera/C = holder - if(!C.panel_open) - return 0 - return 1 - -var/const/CAMERA_WIRE_FOCUS = 1 -var/const/CAMERA_WIRE_POWER = 2 -var/const/CAMERA_WIRE_LIGHT = 4 -var/const/CAMERA_WIRE_ALARM = 8 -var/const/CAMERA_WIRE_NOTHING1 = 16 -var/const/CAMERA_WIRE_NOTHING2 = 32 - -/datum/wires/camera/UpdateCut(var/index, var/mended) - var/obj/machinery/camera/C = holder - - switch(index) - if(CAMERA_WIRE_FOCUS) - var/range = (mended ? initial(C.view_range) : C.short_range) - C.setViewRange(range) - - if(CAMERA_WIRE_POWER) - if(C.status && !mended || !C.status && mended) - C.deactivate(usr, 1) - - if(CAMERA_WIRE_LIGHT) - C.light_disabled = !mended - - if(CAMERA_WIRE_ALARM) - if(!mended) - C.triggerCameraAlarm() - else - C.cancelCameraAlarm() - return - -/datum/wires/camera/UpdatePulsed(var/index) - var/obj/machinery/camera/C = holder - if(IsIndexCut(index)) - return - switch(index) - if(CAMERA_WIRE_FOCUS) - var/new_range = (C.view_range == initial(C.view_range) ? C.short_range : initial(C.view_range)) - C.setViewRange(new_range) - - if(CAMERA_WIRE_POWER) - C.deactivate(null) // Deactivate the camera - - if(CAMERA_WIRE_LIGHT) - C.light_disabled = !C.light_disabled - - if(CAMERA_WIRE_ALARM) - C.visible_message("\icon[C] *beep*", "\icon[C] *beep*") - return - -/datum/wires/camera/proc/CanDeconstruct() - if(IsIndexCut(CAMERA_WIRE_POWER) && IsIndexCut(CAMERA_WIRE_FOCUS) && IsIndexCut(CAMERA_WIRE_LIGHT) && IsIndexCut(CAMERA_WIRE_NOTHING1) && IsIndexCut(CAMERA_WIRE_NOTHING2)) - return 1 - else - return 0 \ No newline at end of file diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 8afadbc4ce8..cb638aa6f31 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -21,6 +21,10 @@ // replaced by OPENCONTAINER flags and atom/proc/is_open_container() ///Chemistry. var/allow_spin = 1 + + //Value used to increment ex_act() if reactionary_explosions is on + var/explosion_block = 0 + /atom/proc/onCentcom() var/turf/T = get_turf(src) if(!T) diff --git a/code/game/communications.dm b/code/game/communications.dm index 75155dff914..9f7d515a300 100644 --- a/code/game/communications.dm +++ b/code/game/communications.dm @@ -299,4 +299,4 @@ var/list/pointers = list() for(var/d in data) var/val = data[d] if(istext(val)) - data[d] = strip_html_properly(val) + data[d] = html_encode(val) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 4bfeecb2247..eddb0216d76 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -188,7 +188,7 @@ return 0 - if(living_antag_player && living_antag_player.mind && living_antag_player.stat != DEAD && !isnewplayer(living_antag_player) &&!isbrain(living_antag_player)) + if(living_antag_player && living_antag_player.mind && isliving(living_antag_player) && living_antag_player.stat != DEAD && !isnewplayer(living_antag_player) &&!isbrain(living_antag_player)) return 0 //A resource saver: once we find someone who has to die for all antags to be dead, we can just keep checking them, cycling over everyone only when we lose our mark. for(var/mob/Player in living_mob_list) diff --git a/code/game/gamemodes/gang/dominator.dm b/code/game/gamemodes/gang/dominator.dm new file mode 100644 index 00000000000..4fbae44af79 --- /dev/null +++ b/code/game/gamemodes/gang/dominator.dm @@ -0,0 +1,209 @@ +/obj/machinery/dominator + name = "dominator" + desc = "A visibly sinister device. Looks like you can break it if you hit it enough." + icon = 'icons/obj/machines/dominator.dmi' + icon_state = "dominator" + density = 1 + anchored = 1.0 + layer = 3.6 + var/health = 200 + var/gang + var/operating = 0 + var/broken = 0 + +/obj/machinery/dominator/New() + if(!istype(ticker.mode, /datum/game_mode/gang)) + qdel(src) + return + SetLuminosity(2) + +/obj/machinery/dominator/examine(mob/user) + ..() + if(broken) + user << "It looks completely busted." + return + + var/datum/game_mode/gang/mode = ticker.mode + var/time = null + if(isnum(mode.A_timer)) + time = max(mode.A_timer, 0) + if(isnum(mode.B_timer)) + time = max(mode.B_timer, 0) + if(isnum(time)) + if(time > 0) + user << "Hostile Takeover in progress. Estimated [time] seconds remain." + else + user << "Hostile Takeover of [station_name()] successful. Have a great day." + else + user << "System on standby." + user << "System Integrity: [health/2]%" + + +/obj/machinery/dominator/proc/healthcheck(var/damage) + var/iconname = "dominator" + if(gang) + iconname += "-[gang]" + SetLuminosity(3) + + var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread + + health -= damage + + switch(health) + if(101 to INFINITY) + if(prob(damage*2)) + sparks.set_up(5, 1, src) + sparks.start() + if(1 to 100) + sparks.set_up(5, 1, src) + sparks.start() + iconname += "-damaged" + + if(!broken) + if(health <= 0) + set_broken() + else + icon_state = iconname + + if(health <= -50) + new /obj/item/stack/sheet/plasteel(src.loc) + qdel(src) + +/obj/machinery/dominator/proc/set_broken() + if(!gang) + return + var/datum/game_mode/gang/mode = ticker.mode + if(gang == "A") + mode.A_timer = "OFFLINE" + if(gang == "B") + mode.B_timer = "OFFLINE" + if(!isnum(mode.A_timer) && !isnum(mode.B_timer)) + SSshuttle.emergencyNoEscape = 0 + if(SSshuttle.emergency.mode == SHUTTLE_STRANDED) + SSshuttle.emergency.mode = SHUTTLE_DOCKED + SSshuttle.emergency.timer = world.time + priority_announce("Hostile enviroment resolved. You have 3 minutes to board the Emergency Shuttle.", null, 'sound/AI/shuttledock.ogg', "Priority") + else + priority_announce("All hostile activity within station systems have ceased.","Network Alert") + SetLuminosity(0) + icon_state = "dominator-broken" + broken = 1 + +/obj/machinery/dominator/Destroy() + if(!broken) + set_broken() + ..() + +/obj/machinery/dominator/emp_act(severity) + healthcheck(100) + ..() + +/obj/machinery/dominator/ex_act(severity, target) + if(target == src) + qdel(src) + return + switch(severity) + if(1.0) + qdel(src) + if(2.0) + healthcheck(120) + if(3.0) + healthcheck(30) + return + +/obj/machinery/dominator/bullet_act(var/obj/item/projectile/Proj) + if(Proj.damage) + if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) + playsound(src, 'sound/effects/bang.ogg', 50, 1) + visible_message("[src] was hit by [Proj].") + healthcheck(Proj.damage) + ..() + +/obj/machinery/dominator/blob_act() + healthcheck(110) + +/obj/machinery/dominator/attackby(I as obj, user as mob, params) + + return + +/obj/machinery/dominator/attack_hand(mob/user) + if(operating||broken) + examine(user) + return + + var/datum/game_mode/gang/mode = ticker.mode + var/gang_territory + var/timer + + var/tempgang + if(user.mind in (ticker.mode.A_gang|ticker.mode.A_bosses)) + tempgang = "A" + gang_territory = ticker.mode.A_territory.len + timer = mode.A_timer + else if(user.mind in (ticker.mode.B_gang|ticker.mode.B_bosses)) + tempgang = "B" + gang_territory = ticker.mode.B_territory.len + timer = mode.B_timer + + if(!tempgang) + examine(user) + return + + if(isnum(timer)) //In theory, this shouldn't happen. But if it does, they get this meme + user << "Error: Hostile Takeover is already in progress." + return + + var/time = max(180,900 - ((round((gang_territory/start_state.num_territories)*200, 1) - 60) * 15)) + if(alert(user,"With [round((gang_territory/start_state.num_territories)*100, 1)]% station control, a takeover will require [time] seconds.\nThe entire station will likely be alerted once it starts.\nYour gang must be prepared to defend this device throughout the duration.\nAre you ready?","Confirmation","Yes","No") == "Yes") + if ((!in_range(src, user) || !istype(src.loc, /turf))) + return 0 + var/area/srcloc = get_area(src.loc) + gang = tempgang + mode.domination(gang,1,srcloc.name) + src.name = "[gang_name(gang)] Gang [src.name]" + healthcheck(0) + operating = 1 + +/obj/machinery/dominator/attack_alien(mob/living/user) + user.do_attack_animation(src) + playsound(src, 'sound/effects/bang.ogg', 50, 1) + user.visible_message("[user] smashes against [src] with its claws.",\ + "You smash against [src] with your claws.",\ + "You hear metal scraping.") + healthcheck(15) + +/obj/machinery/dominator/attack_animal(mob/living/user as mob) + if(!isanimal(user)) + return + var/mob/living/simple_animal/M = user + M.do_attack_animation(src) + if(M.melee_damage_upper <= 0) + return + healthcheck(M.melee_damage_upper) + +/obj/machinery/dominator/mech_melee_attack(obj/mecha/M) + if(M.damtype == "brute") + playsound(src, 'sound/effects/bang.ogg', 50, 1) + visible_message("[M.name] has hit [src].") + healthcheck(M.force) + return + +/obj/machinery/dominator/attack_hulk(mob/user) + playsound(src, 'sound/effects/bang.ogg', 50, 1) + user.visible_message("[user] smashes [src].",\ + "You punch [src].",\ + "You hear metal being slammed.") + healthcheck(5) + +/obj/machinery/dominator/attackby(obj/item/weapon/I as obj, mob/living/user as mob, params) + if(istype(I, /obj/item/weapon)) + add_fingerprint(user) + user.changeNext_move(CLICK_CD_MELEE) + user.do_attack_animation(src) + if( (I.flags&NOBLUDGEON) || !I.force ) + return + playsound(src, 'sound/weapons/smash.ogg', 50, 1) + visible_message("[user] has hit \the [src] with [I].") + if(I.damtype == BURN || I.damtype == BRUTE) + healthcheck(I.force) + return diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm index 6967dc894c7..97ed4eecbcd 100644 --- a/code/game/gamemodes/gang/gang.dm +++ b/code/game/gamemodes/gang/gang.dm @@ -15,6 +15,10 @@ var/list/A_territory_lost = list() var/list/B_territory_new = list() var/list/B_territory_lost = list() + var/gang_A_style + var/gang_A_headgear + var/gang_B_style + var/gang_B_headgear /datum/game_mode/gang name = "gang war" @@ -26,14 +30,15 @@ recommended_enemies = 2 enemy_minimum_age = 14 var/finished = 0 - var/goal_scalar = 0.5 //Goal = Total territories x goal_scalar - + // Victory timers + var/A_timer = "OFFLINE" + var/B_timer = "OFFLINE" /////////////////////////// //Announces the game type// /////////////////////////// /datum/game_mode/gang/announce() world << "The current game mode is - Gang War!" - world << "A violent turf war has erupted on the station!
Gangsters - Take over the station by claiming more than [round(100*goal_scalar,1)]% of the station!
Crew - The gangs will try to keep you on the station. Successfully evacuate the station to win!
" + world << "A violent turf war has erupted on the station!
Gangsters - Take over the station by activating and defending a Dominator!
Crew - The gangs will try to keep you on the station. Successfully evacuate the station to win!
" /////////////////////////////////////////////////////////////////////////////// @@ -73,6 +78,15 @@ modePlayer += B_bosses ..() +/datum/game_mode/gang/process(seconds) + if(!finished) + if(isnum(A_timer)) + A_timer -= seconds + if(isnum(B_timer)) + B_timer -= seconds + + ticker.mode.check_win() + /datum/game_mode/gang/proc/assign_bosses() var/datum/mind/boss = pick(antag_candidates) A_bosses += boss @@ -91,7 +105,7 @@ /datum/game_mode/proc/forge_gang_objectives(var/datum/mind/boss_mind) var/datum/objective/rival_obj = new rival_obj.owner = boss_mind - rival_obj.explanation_text = "Claim more than 50% the station before the [(boss_mind in A_bosses) ? gang_name("B") : gang_name("A")] Gang does." + rival_obj.explanation_text = "Preform a hostile takeover of the station with a Dominator." boss_mind.objectives += rival_obj @@ -103,6 +117,17 @@ boss_mind.current << "Objective #[obj_count]: [objective.explanation_text]" obj_count++ +/datum/game_mode/gang/proc/domination(var/gang,var/modifier=1,var/dominatorloc) + if(gang=="A") + A_timer = max(180,900 - ((round((ticker.mode.A_territory.len/start_state.num_territories)*200, 1) - 60) * 15)) * modifier + if(gang=="B") + B_timer = max(180,900 - ((round((ticker.mode.B_territory.len/start_state.num_territories)*200, 1) - 60) * 15)) * modifier + if(gang && dominatorloc) + priority_announce("Hostile runtimes detected in all station systems. A network breach by the [gang_name(gang)] Gang has been traced to [dominatorloc].","Network Alert") + if(get_security_level() != "delta") + set_security_level("red") + SSshuttle.emergencyNoEscape = 1 + /////////////////////////////////////////////////////////////////////////// //This equips the bosses with their gear, and makes the clown not clumsy// /////////////////////////////////////////////////////////////////////////// @@ -132,37 +157,107 @@ var/where = mob.equip_in_one_of_slots(gangtool, slots) if (!where) mob << "Your Syndicate benefactors were unfortunately unable to get you a Gangtool." + . += 1 else gangtool.register_device(mob) - mob << "The Gangtool in your [where] will allow you to use your influence to purchase items and prevent the station from evacuating before you can take over. Use it to recall the emergency shuttle from anywhere on the station." + mob << "The Gangtool in your [where] will allow you to purchase items, send messages to your gangsters and to recall the emergency shuttle from anywhere on the station." mob << "You can also promote your gang members to lieutenant by giving them an unregistered gangtool. Lieutenants cannot be deconverted and are able to use recruitment pens and gangtools." - . += 1 var/where2 = mob.equip_in_one_of_slots(T, slots) if (!where2) mob << "Your Syndicate benefactors were unfortunately unable to get you a recruitment pen to start." + . += 1 else mob << "The recruitment pen in your [where2] will help you get your gang started. Use it on unsuspecting crew members to recruit them." - . += 1 var/where3 = mob.equip_in_one_of_slots(SC, slots) if (!where3) mob << "Your Syndicate benefactors were unfortunately unable to get you a territory spraycan to start." + . += 1 else mob << "The territory spraycan in your [where3] can be used to claim areas of the station for your gang. The more territory your gang controls, the more influence you get. Distribute these to your gangsters to grow your influence faster." - . += 1 mob.update_icons() return . +//Used by recallers when purchasing a gang outfit. First time a gang outfit is purchased the buyer decides a gang style which is stored so gang outfits are uniform +/datum/game_mode/proc/gang_outfit(mob/user,var/obj/item/device/gangtool/gangtool,var/gang) + if(!user || !gangtool || !gang) + return 0 + if(!gangtool.can_use(user)) + return 0 + + var/gang_style_list = list("Gang Colors","Leather Jackets","Fine Suits") + var/style + var/headgear + if(gang == "A") + if(!gang_A_style) + gang_A_style = input("Pick an outfit style.", "Pick Style") as null|anything in gang_style_list + if(gang_A_style && (alert(user,"Include headgear?","Option","Yes","No") == "Yes")) + gang_A_headgear = 1 + style = gang_A_style + headgear = gang_A_headgear + + if(gang == "B") + if(!gang_B_style) + gang_B_style = input("Pick an outfit style.", "Pick Style") as null|anything in gang_style_list + if(gang_B_style && (alert(user,"Include headgear?","Option","Yes","No") == "Yes")) + gang_B_headgear = 1 + style = gang_B_style + headgear = gang_B_headgear + + if(!style) + return 0 + + if(gangtool.can_use(user) && (((gang == "A") ? gang_points.A : gang_points.B) >= 1)) + switch(style) + if("Gang Colors") + if(gang == "A") + new /obj/item/clothing/under/color/blue(user.loc) + if(headgear) + new /obj/item/clothing/mask/bandana/blue(user.loc) + if(gang == "B") + new /obj/item/clothing/under/color/red(user.loc) + if(headgear) + new /obj/item/clothing/mask/bandana/red(user.loc) + if("Leather Jackets") + new /obj/item/clothing/suit/jacket/leather(user.loc) + if(headgear) + if(gang == "A") + new /obj/item/clothing/mask/bandana/blue(user.loc) + if(gang == "B") + new /obj/item/clothing/mask/bandana/red(user.loc) + if("Fine Suits") + new /obj/item/clothing/under/suit_jacket/really_black(user.loc) + if(headgear) + new /obj/item/clothing/head/fedora(user.loc) + + return 1 + + return 0 + ///////////////////////////////////////////// //Checks if the either gang have won or not// ///////////////////////////////////////////// /datum/game_mode/gang/check_win() - if(A_territory.len > (start_state.num_territories * goal_scalar)) - finished = "A" //Gang A wins - else if(B_territory.len > (start_state.num_territories * goal_scalar)) - finished = "B" //Gang B wins + var/winner = 0 + + if(isnum(A_timer)) + if(A_timer < 0) + winner += 1 + if(isnum(B_timer)) + if(B_timer < 0) + winner += 2 + + if(winner) + if(winner == 3) //Edge Case: If both dominators activate at the same time + domination("A",0.5) + domination("B",0.5) + priority_announce("Multiple station takeover attempts have made simultaneously. Conflicting hostile runtimes have delayed both attempts.","Network Alert") + else if(winner == 1) + finished = "A" //Gang A wins + else if(winner == 2) + finished = "B" //Gang B wins /////////////////////////////// //Checks if the round is over// @@ -282,7 +377,7 @@ if(!finished) world << "The station was [station_was_nuked ? "destroyed!" : "evacuated before either gang could claim it!"]" else - world << "The [finished=="A" ? gang_name("A") : gang_name("B")] Gang has claimed over [round(100*goal_scalar,1)]% of the station and has assumed control!" + world << "The [finished=="A" ? gang_name("A") : gang_name("B")] Gang successfully preformed a hostile takeover of the station!!" ..() return 1 @@ -338,8 +433,8 @@ ////////////////////////////////////////////////////////// /datum/gang_points - var/A = 30 - var/B = 30 + var/A = 25 + var/B = 25 var/next_point_interval = 1800 var/next_point_time @@ -429,12 +524,9 @@ var/A_control = round((ticker.mode.A_territory.len/start_state.num_territories)*100, 1) var/B_control = round((ticker.mode.B_territory.len/start_state.num_territories)*100, 1) ticker.mode.message_gangtools((ticker.mode.A_tools),"Your gang now has [A_control]% control of the station.",0) - ticker.mode.message_gangtools((ticker.mode.A_tools),"The [gang_name("B")] Gang has [B_control]% control of the station.",0,1) + //ticker.mode.message_gangtools((ticker.mode.A_tools),"The [gang_name("B")] Gang has [B_control]% control of the station.",0,1) ticker.mode.message_gangtools((ticker.mode.B_tools),"Your gang now has [B_control]% control of the station.",0) - ticker.mode.message_gangtools((ticker.mode.B_tools),"The [gang_name("A")] Gang has [A_control]% control of the station.",0,1) - - //Victory check - ticker.mode.check_win() + //ticker.mode.message_gangtools((ticker.mode.B_tools),"The [gang_name("A")] Gang has [A_control]% control of the station.",0,1) //Restart the counter start() diff --git a/code/game/objects/items/devices/recaller.dm b/code/game/gamemodes/gang/recaller.dm similarity index 72% rename from code/game/objects/items/devices/recaller.dm rename to code/game/gamemodes/gang/recaller.dm index de3f046635c..addef28d740 100644 --- a/code/game/objects/items/devices/recaller.dm +++ b/code/game/gamemodes/gang/recaller.dm @@ -2,7 +2,7 @@ /obj/item/device/gangtool name = "suspicious device" desc = "A strange device of sorts. Hard to really make out what it actually does just by looking." - icon_state = "recaller" + icon_state = "gangtool" item_state = "walkietalkie" throwforce = 0 w_class = 1.0 @@ -33,30 +33,28 @@ else dat += "Register Device
" else + var/datum/game_mode/gang/gangmode + if(istype(ticker.mode, /datum/game_mode/gang)) + gangmode = ticker.mode + var/gang_size = ((gang == "A")? (ticker.mode.A_gang.len + ticker.mode.A_bosses.len) : (ticker.mode.B_gang.len + ticker.mode.B_bosses.len)) var/gang_territory = ((gang == "A")? ticker.mode.A_territory.len : ticker.mode.B_territory.len) var/points = ((gang == "A") ? ticker.mode.gang_points.A : ticker.mode.gang_points.B) + var/timer + if(gangmode) + timer = ((gang == "A") ? gangmode.A_timer : gangmode.B_timer) + if(isnum(timer)) + dat += "
Takeover In Progress:
[timer] seconds remain

" dat += "Registration: [(gang == "A")? gang_name("A") : gang_name("B")] Gang [boss ? "Administrator" : "Lieutenant"]
" - dat += "Organization Size: [gang_size]
" - dat += "Station Control: [round((gang_territory/start_state.num_territories)*100, 1)]%
" + dat += "Organization Size: [gang_size] | Station Control: [round((gang_territory/start_state.num_territories)*100, 1)]%
" + dat += "Send Gang-wide Message
" dat += "Recall Emergency Shuttle
" dat += "
" dat += "Influence: [points]
" - dat += "Time until Influence grows: [(points >= 100) ? ("--:--") : (time2text(ticker.mode.gang_points.next_point_time - world.time, "mm:ss"))]
" - dat += "Purchase Items:
" - - dat += "(5 Influence) " - if(points >= 5) - dat += "Send Gang-wide Message
" - else - dat += "Send Gang-wide Message
" - - dat += "(10 Influence) " - if(points >= 10) - dat += "Territory Spraycan
" - else - dat += "Territory Spraycan
" + dat += "Time until Influence grows: [(points >= 999) ? ("--:--") : (time2text(ticker.mode.gang_points.next_point_time - world.time, "mm:ss"))]
" + dat += "
" + dat += "Purchase Weapons:
" dat += "(10 Influence) " if(points >= 10) @@ -64,8 +62,8 @@ else dat += "Switchblade
" - dat += "(25 Influence) " - if(points >= 25) + dat += "(20 Influence) " + if(points >= 20) dat += "10mm Pistol
" else dat += "10mm Pistol
" @@ -76,8 +74,35 @@ else dat += "10mm Ammo
" - dat += "(40 Influence) " - if(points >= 40) + dat += "(50 Influence) " + if(points >= 50) + dat += "Thompson SMG
" + else + dat += "Thompson SMG
" + + dat += "
" + dat += "Purchase Utilities:
" + + dat += "(10 Influence) " + if(points >= 10) + dat += "Territory Spraycan
" + else + dat += "Territory Spraycan
" + + dat += "(1 Influence) " + if(points >= 1) + dat += "Gang Outfit
" + else + dat += "Gang Outfit
" + + dat += "(10 Influence) " + if(points >= 10) + dat += "Bulletproof Vest
" + else + dat += "Bulletproof Vest
" + + dat += "(30 Influence) " + if(points >= 30) dat += "Recruitment Pen
" else dat += "Recruitment Pen
" @@ -91,14 +116,23 @@ dat += "Promote a Gangster
" else dat += "Promote a Gangster
" + if(gangmode) + dat += "(50 Influence) " + if(points >= 50) + dat += "Station Dominator
" + dat += "(Estimated Takeover Time: [round(max(180,900 - ((round((gang_territory/start_state.num_territories)*200, 10) - 60) * 15))/60,1)] minutes)
" + else + dat += "Station Dominator
" dat += "
" dat += "Refresh
" - var/datum/browser/popup = new(user, "gangtool", "Welcome to GangTool v0.4") + var/datum/browser/popup = new(user, "gangtool", "Welcome to GangTool v0.4", 350, 550) popup.set_content(dat) popup.open() + + /obj/item/device/gangtool/Topic(href, href_list) if(!can_use(usr)) return @@ -115,6 +149,10 @@ var/points = ((gang == "A") ? ticker.mode.gang_points.A : ticker.mode.gang_points.B) var/item_type switch(href_list["purchase"]) + if("outfit") + if(points >= 1) + item_type = ticker.mode.gang_outfit(usr,src,gang) + points = 1 if("spraycan") if(points >= 10) item_type = /obj/item/toy/crayon/spraycan/gang @@ -124,31 +162,60 @@ item_type = /obj/item/weapon/switchblade points = 10 if("pistol") - if(points >= 25) + if(points >= 20) item_type = /obj/item/weapon/gun/projectile/automatic/pistol - points = 25 + points = 20 if("ammo") if(points >= 10) item_type = /obj/item/ammo_box/magazine/m10mm points = 10 + if("SMG") + if(points >= 50) + item_type = /obj/item/weapon/gun/projectile/automatic/tommygun + points = 50 + if("vest") + if(points >= 10) + item_type = /obj/item/clothing/suit/armor/bulletproof + points = 10 if("pen") - if(points >= 40) + if(points >= 30) item_type = /obj/item/weapon/pen/gang - points = 40 + points = 30 if("gangtool") if((promotions < 3) && (points >= (promotions*20)+10)) item_type = /obj/item/device/gangtool/lt points = (promotions*20)+10 promotions++ + if("dominator") + if(istype(ticker.mode, /datum/game_mode/gang)) + var/datum/game_mode/gang/mode = ticker.mode + if(isnum((gang == "A") ? mode.A_timer : mode.B_timer)) + return + + var/fail = 0 + var/usrarea = get_area(usr.loc) + var/usrturf = get_turf(usr.loc) + if(istype(usrarea,/area/space) || istype(usrturf,/turf/space) || usr.z != 1) + usr << "You can only use this on the station!" + fail = 1 + for(var/obj/obj in usrturf) + if(obj.density) + usr << "There's not enough room here!" + fail = 1 + break + if(!fail && points >= 50) + item_type = /obj/machinery/dominator + points = 50 if(item_type) if(gang == "A") ticker.mode.gang_points.A -= points else if(gang == "B") ticker.mode.gang_points.B -= points - var/obj/purchased = new item_type(get_turf(usr)) - var/mob/living/carbon/human/H = usr - H.put_in_any_hand_if_possible(purchased) + if(ispath(item_type)) + var/obj/purchased = new item_type(get_turf(usr)) + var/mob/living/carbon/human/H = usr + H.put_in_any_hand_if_possible(purchased) ticker.mode.message_gangtools(((gang=="A")? ticker.mode.A_tools : ticker.mode.B_tools), "A [href_list["purchase"]] was purchased by [usr] for [points] Influence.") log_game("A [href_list["purchase"]] was purchased by [key_name(usr)] for [points] Influence.") @@ -172,18 +239,16 @@ return var/list/members = list() if(gang == "A") - if(ticker.mode.gang_points.A >= 5) - members += ticker.mode.A_bosses | ticker.mode.A_gang - ticker.mode.gang_points.A -= 5 + members += ticker.mode.A_bosses | ticker.mode.A_gang else if(gang == "B") - if(ticker.mode.gang_points.B >= 5) - members += ticker.mode.B_bosses | ticker.mode.B_gang - ticker.mode.gang_points.B -= 5 + members += ticker.mode.B_bosses | ticker.mode.B_gang if(members.len) + var/ping = "[boss ? "Gang Boss" : "Gang Lieutenant"]: [message]" for(var/datum/mind/ganger in members) if(ganger.current.z <= 2) - ganger.current << "BOSS: [message]" - message_admins("[key_name_admin(user)] sent a global message to the [gang_name(gang)] Gang ([gang]): [message].") + ganger.current << "[ping]" + for(var/mob/M in dead_mob_list) + M << "[gang_name(gang)] [ping]" log_game("[key_name(user)] sent a global message to the [gang_name(gang)] Gang ([gang]): [message].") @@ -196,6 +261,7 @@ if(user.mind in (ticker.mode.A_gang | ticker.mode.A_bosses)) ticker.mode.A_tools += src gang = "A" + icon_state = "gangtool-a" if(!(user.mind in ticker.mode.A_bosses)) ticker.mode.remove_gangster(user.mind, 0, 2) ticker.mode.A_bosses += user.mind @@ -206,6 +272,7 @@ else if(user.mind in (ticker.mode.B_gang | ticker.mode.B_bosses)) ticker.mode.B_tools += src gang = "B" + icon_state = "gangtool-b" if(!(user.mind in ticker.mode.B_bosses)) ticker.mode.remove_gangster(user.mind, 0, 2) ticker.mode.B_bosses += user.mind @@ -218,7 +285,7 @@ user << "You have been promoted to Lieutenant!" ticker.mode.forge_gang_objectives(user.mind) ticker.mode.greet_gang(user.mind,0) - user << "The Gangtool you registered will allow you to use your gang's influence to purchase items and prevent the station from evacuating before your gang can take over. Use it to recall the emergency shuttle from anywhere on the station." + user << "The Gangtool you registered will allow you to purchase items, send messages to your gangsters and to recall the emergency shuttle from anywhere on the station." user << "You may also now use recruitment pens to grow your gang membership. Use them on unsuspecting crew members to recruit them." if(!gang) usr << "ACCESS DENIED: Unauthorized user." diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index 8a58076e663..da2e49f4af7 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -182,6 +182,11 @@ log_name = "IS" category = "Utility Spells" +/datum/spellbook_entry/lichdom + name = "Bind Soul" + spell_type = /obj/effect/proc_holder/spell/targeted/lichdom + log_name = "LD" + /datum/spellbook_entry/lightningbolt name = "Lightning Bolt" spell_type = /obj/effect/proc_holder/spell/targeted/lightning diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm index 87eb95b4f42..abb5bc29586 100644 --- a/code/game/machinery/atmo_control.dm +++ b/code/game/machinery/atmo_control.dm @@ -78,6 +78,7 @@ set_frequency(frequency) /obj/machinery/air_sensor/Destroy() + SSair.atmos_machinery -= src if(radio_controller) radio_controller.remove_object(src,frequency) ..() diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm index d8ba823694b..99bd769543a 100644 --- a/code/game/machinery/atmoalter/meter.dm +++ b/code/game/machinery/atmoalter/meter.dm @@ -18,6 +18,11 @@ src.target = locate(/obj/machinery/atmospherics/pipe) in loc return 1 +/obj/machinery/meter/Destroy() + SSair.atmos_machinery -= src + src.target = null + ..() + /obj/machinery/meter/initialize() if (!target) src.target = locate(/obj/machinery/atmospherics/pipe) in loc diff --git a/code/game/machinery/atmoalter/zvent.dm b/code/game/machinery/atmoalter/zvent.dm index 26bd2cff6c1..42e1926ef4e 100644 --- a/code/game/machinery/atmoalter/zvent.dm +++ b/code/game/machinery/atmoalter/zvent.dm @@ -9,6 +9,14 @@ var/on = 0 var/volume_rate = 800 +/obj/machinery/zvent/New() + ..() + SSair.atmos_machinery += src + +/obj/machinery/zvent/Destroy() + SSair.atmos_machinery -= src + ..() + /obj/machinery/zvent/process_atmos() //all this object does, is make its turf share air with the ones above and below it, if they have a vent too. diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index ca4b9fdd034..ae2204f9da3 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -8,12 +8,12 @@ active_power_usage = 10 layer = 5 - var/datum/wires/camera/wires = null // Wires datum + var/health = 50 var/list/network = list("SS13") var/c_tag = null var/c_tag_order = 999 - var/status = 1.0 - anchored = 1.0 + var/status = 1 + anchored = 1 var/start_active = 0 //If it ignores the random chance to start broken on round start var/invuln = null var/obj/item/device/camera_bug/bug = null @@ -30,8 +30,6 @@ var/emped = 0 //Number of consecutive EMP's on this camera /obj/machinery/camera/New() - wires = new(src) - assembly = new(src) assembly.state = 4 assembly.anchored = 1 @@ -59,20 +57,18 @@ if(bug.current == src) bug.current = null bug = null - qdel(wires) cameranet.removeCamera(src) //Will handle removal from the camera network and the chunks, so we don't need to worry about that ..() /obj/machinery/camera/emp_act(severity) if(!isEmpProof()) - if(prob(100/severity)) + if(prob(150/severity)) icon_state = "[initial(icon_state)]emp" var/list/previous_network = network network = list() cameranet.removeCamera(src) stat |= EMPED SetLuminosity(0) - triggerCameraAlarm() emped = emped+1 //Increase the number of consecutive EMP's var/thisemp = emped //Take note of which EMP this proc is for spawn(900) @@ -81,10 +77,12 @@ network = previous_network icon_state = initial(icon_state) stat &= ~EMPED - cancelCameraAlarm() if(can_use()) cameranet.addCamera(src) emped = 0 //Resets the consecutive EMP count + triggerCameraAlarm() + spawn(100) + cancelCameraAlarm() for(var/mob/O in mob_list) if (O.client && O.client.eye == src) O.unset_machine() @@ -117,66 +115,71 @@ if(!istype(user)) return user.do_attack_animation(src) - status = 0 + add_hiddenprint(user) visible_message("\The [user] slashes at [src]!") playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) - icon_state = "[initial(icon_state)]1" - add_hiddenprint(user) - deactivate(user,0) + health = max(0, health - 30) + if(!health && status) + deactivate(user, 0) -/obj/machinery/camera/attackby(W as obj, mob/living/user as mob, params) - var/msg = "You attach [W] into the assembly inner circuits." - var/msg2 = "The camera already has that upgrade!" +/obj/machinery/camera/attackby(obj/W, mob/living/user, params) + var/msg = "You attach [W] into the assembly's inner circuits." + var/msg2 = "[src] already has that upgrade!" // DECONSTRUCTION if(istype(W, /obj/item/weapon/screwdriver)) - //user << "You start to [panel_open ? "close" : "open"] the camera's panel." - //if(toggle_panel(user)) // No delay because no one likes screwdrivers trying to be hip and have a duration cooldown panel_open = !panel_open - user.visible_message("[user] screws the camera's panel [panel_open ? "open" : "closed"]!", - "You screw the camera's panel [panel_open ? "open" : "closed"].") + user << "You screw the camera's panel [panel_open ? "open" : "closed"]." playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + return - else if((istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/multitool)) && panel_open) - wires.Interact(user) + if(panel_open) + if(istype(W, /obj/item/weapon/wirecutters)) //enable/disable the camera + deactivate(user, 1) + health = initial(health) //this is a pretty simplistic way to heal the camera, but there's no reason for this to be complex. - else if(istype(W, /obj/item/weapon/weldingtool) && wires.CanDeconstruct()) - if(weld(W, user)) - user << "You unweld the camera leaving it as just a frame screwed to the wall." - if(!assembly) - assembly = new() - assembly.loc = src.loc - assembly.state = 1 - assembly.dir = src.dir - assembly.update_icon() - assembly = null - qdel(src) - return - else if(istype(W, /obj/item/device/analyzer) && panel_open) //XRay - if(!isXRay()) - upgradeXRay() - qdel(W) - user << "[msg]" - else - user << "[msg2]" + else if(istype(W, /obj/item/device/multitool)) //change focus + setViewRange((view_range == initial(view_range)) ? short_range : initial(view_range)) + user << "You [(view_range == initial(view_range)) ? "restore" : "mess up"] the camera's focus." - else if(istype(W, /obj/item/stack/sheet/mineral/plasma) && panel_open) - if(!isEmpProof()) - upgradeEmpProof() - user << "[msg]" - qdel(W) - else - user << "[msg2]" - else if(istype(W, /obj/item/device/assembly/prox_sensor) && panel_open) - if(!isMotion()) - upgradeMotion() - user << "[msg]" - qdel(W) - else - user << "[msg2]" + else if(istype(W, /obj/item/weapon/weldingtool)) + if(weld(W, user)) + visible_message("[user] unwelds [src], leaving it as just a frame screwed to the wall.", "You unweld [src], leaving it as just a frame screwed to the wall") + if(!assembly) + assembly = new() + assembly.loc = src.loc + assembly.state = 1 + assembly.dir = src.dir + assembly.update_icon() + assembly = null + qdel(src) + return + + else if(istype(W, /obj/item/device/analyzer)) + if(!isXRay()) + upgradeXRay() + qdel(W) + user << "[msg]" + else + user << "[msg2]" + + else if(istype(W, /obj/item/stack/sheet/mineral/plasma)) + if(!isEmpProof()) + upgradeEmpProof() + user << "[msg]" + qdel(W) + else + user << "[msg2]" + else if(istype(W, /obj/item/device/assembly/prox_sensor)) + if(!isMotion()) + upgradeMotion() + user << "[msg]" + qdel(W) + else + user << "[msg2]" // OTHER - else if ((istype(W, /obj/item/weapon/paper) || istype(W, /obj/item/device/pda)) && isliving(user)) + if((istype(W, /obj/item/weapon/paper) || istype(W, /obj/item/device/pda)) && isliving(user)) var/mob/living/U = user var/obj/item/weapon/paper/X = null var/obj/item/device/pda/P = null @@ -204,6 +207,7 @@ else if (O.client && O.client.eye == src) O << "[U] holds \a [itemname] up to one of the cameras ..." O << browse(text("[][]", itemname, info), text("window=[]", itemname)) + else if (istype(W, /obj/item/device/camera_bug)) if (!src.can_use()) user << "Camera non-functional." @@ -216,23 +220,29 @@ user << "Camera bugged." src.bug = W src.bug.bugged_cameras[src.c_tag] = src + else if(istype(W, /obj/item/device/laser_pointer)) var/obj/item/device/laser_pointer/L = W L.laser_act(src, user) + else - ..() + if(W.force > 10) //fairly simplistic, but will do for now. + user.changeNext_move(CLICK_CD_MELEE) + visible_message("[user] hits [src] with [W]!", "You hit [src] with [W]!") + health = max(0, health - W.force) + if(!health && status) + deactivate(user, 1) return -/obj/machinery/camera/proc/deactivate(user as mob, var/choice = 1) - if(choice==1) - status = !( src.status ) - if (!(src.status)) +/obj/machinery/camera/proc/deactivate(mob/user, displaymessage = 1) //this should be called toggle() but doing a find and replace for this would be ass + if(displaymessage) + status = !status + if(!status) if(user) visible_message("[user] deactivates [src]!") add_hiddenprint(user) else visible_message("\The [src] deactivates!") - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) icon_state = "[initial(icon_state)]1" else @@ -241,8 +251,11 @@ add_hiddenprint(user) else visible_message("\The [src] reactivates!") - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) + triggerCameraAlarm() icon_state = initial(icon_state) + spawn(100) + cancelCameraAlarm() + playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) // now disconnect anyone using the camera //Apparently, this will disconnect anyone even if the camera was re-activated. @@ -308,7 +321,6 @@ return null /proc/near_range_camera(var/mob/M) - for(var/obj/machinery/camera/C in range(4, M)) if(C.can_use()) // check if camera disabled return C @@ -317,7 +329,6 @@ return null /obj/machinery/camera/proc/weld(var/obj/item/weapon/weldingtool/WT, var/mob/living/user) - if(busy) return 0 if(!WT.remove_fuel(0, user)) @@ -347,4 +358,4 @@ /obj/machinery/camera/portable/process() //Updates whenever the camera is moved. if(cameranet && get_turf(src) != prev_turf) cameranet.updatePortableCamera(src) - prev_turf = get_turf(src) \ No newline at end of file + prev_turf = get_turf(src) diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 95664e9a49f..759082e598b 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -49,38 +49,13 @@ return list() for(var/mob/living/M in mob_list) - // Easy checks first. - // Don't detect mobs on Centcom. Since the wizard den is on Centcom, we only need this. - var/turf/T = get_turf(M) - if(!T) - continue - if(T.z == ZLEVEL_CENTCOM) - continue - if(T.z >= ZLEVEL_SPACEMAX) - continue - if(M == usr) - continue - if(M.invisibility)//cloaked - continue - if(M.digitalcamo) + if(!M.can_track(usr)) continue // Human check var/human = 0 if(istype(M, /mob/living/carbon/human)) human = 1 - var/mob/living/carbon/human/H = M - //Cameras can't track people wearing an agent card or a ninja hood. - if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) - continue - if(istype(H.head, /obj/item/clothing/head)) - var/obj/item/clothing/head/hat = H.head - if(hat.blockTracking) - continue - - // Now, are they viewable by a camera? (This is last because it's the most intensive check) - if(!near_camera(M)) - continue var/name = M.name if (name in track.names) @@ -109,51 +84,54 @@ ai_actual_track(target) -/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target as mob) +/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target) if(!istype(target)) return var/mob/living/silicon/ai/U = usr - U.cameraFollow = target - //U << text("Now tracking [] on camera.", target.name) - //if (U.machine == null) - // U.machine = U - U << "Now tracking [target.get_visible_name()] on camera." - spawn (0) + U.cameraFollow = target + U.tracking = 1 + + U << "Attempting to track [target.get_visible_name()]..." + sleep(min(30, get_dist(target, U.eyeobj) / 4)) + spawn(15) //give the AI a grace period to stop moving. + U.tracking = 0 + + if(!target || !target.can_track(usr)) + U << "Target is not near any active cameras." + U.cameraFollow = null + return + + U << "Now tracking [target.get_visible_name()] on camera." + + var/cameraticks = 0 + spawn(0) while (U.cameraFollow == target) if (U.cameraFollow == null) return - if (istype(target, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = target - if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) - U << "Follow camera mode terminated." - U.cameraFollow = null - return - if(istype(H.head, /obj/item/clothing/head)) - var/obj/item/clothing/head/hat = H.head - if(hat.blockTracking) - U << "Follow camera mode terminated." - U.cameraFollow = null - return - if(H.digitalcamo) - U << "Follow camera mode terminated." - U.cameraFollow = null - return - if(istype(target.loc,/obj/effect/dummy)) - U << "Follow camera mode ended." - U.cameraFollow = null - return - - if (!near_camera(target)) - U << "Target is not near any active cameras." - sleep(100) - continue + if (!target.can_track(usr)) + U.tracking = 1 + U << "Target is not near any active cameras." + cameraticks++ + if(cameraticks > 9) + U.cameraFollow = null + tracking = 0 + return + else + continue + + else + cameraticks = 0 + U.tracking = 0 if(U.eyeobj) U.eyeobj.setLoc(get_turf(target)) + else view_core() + U.cameraFollow = null return + sleep(10) /proc/near_camera(var/mob/living/M) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index f04424c08a7..00a8bde3ac0 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -44,6 +44,8 @@ for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts) speed_coeff += P.rating heal_level = (efficiency * 15) + 10 + if(heal_level > 100) + heal_level = 100 //The return of data disks?? Just for transferring between genetics machine/cloning machine. //TO-DO: Make the genetics machine accept them. @@ -224,7 +226,7 @@ use_power(7500) //This might need tweaking. return - else if((src.occupant.cloneloss <= (100 - src.heal_level)) && (!src.eject_wait) || src.occupant.health >= 100) + else if((src.occupant.cloneloss <= (100 - src.heal_level)) && (!src.eject_wait)) src.connected_message("Cloning Process Complete.") src.locked = 0 src.go_out() diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 23f042caebf..848a98d53c6 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -101,10 +101,10 @@ var/name_part1 var/name_part2 - name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ") + name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ", "Ban ") name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ") - name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn") + name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn", "Bloopers") src.enemy_name = replacetext((name_part1 + name_part2), "the ", "") src.name = (name_action + name_part1 + name_part2) @@ -145,6 +145,7 @@ src.blocked = 1 var/attackamt = rand(2,6) src.temp = "You attack for [attackamt] damage!" + playsound(src.loc, 'sound/arcade/Hit.ogg', 50, 1, extrarange = -3, falloff = 10) src.updateUsrDialog() if(turtle > 0) turtle-- @@ -158,6 +159,7 @@ var/pointamt = rand(1,3) var/healamt = rand(6,8) src.temp = "You use [pointamt] magic to heal for [healamt] damage!" + playsound(src.loc, 'sound/arcade/Heal.ogg', 50, 1, extrarange = -3, falloff = 10) src.updateUsrDialog() turtle++ @@ -172,6 +174,7 @@ src.blocked = 1 var/chargeamt = rand(4,7) src.temp = "You regain [chargeamt] points" + playsound(src.loc, 'sound/arcade/Mana.ogg', 50, 1, extrarange = -3, falloff = 10) src.player_mp += chargeamt if(turtle > 0) turtle-- @@ -206,6 +209,7 @@ if(!gameover) src.gameover = 1 src.temp = "[src.enemy_name] has fallen! Rejoice!" + playsound(src.loc, 'sound/arcade/Win.ogg', 50, 1, extrarange = -3, falloff = 10) if(emagged) feedback_inc("arcade_win_emagged") @@ -222,11 +226,13 @@ else if (emagged && (turtle >= 4)) var/boomamt = rand(5,10) src.temp = "[src.enemy_name] throws a bomb, exploding you for [boomamt] damage!" + playsound(src.loc, 'sound/arcade/Boom.ogg', 50, 1, extrarange = -3, falloff = 10) src.player_hp -= boomamt else if ((src.enemy_mp <= 5) && (prob(70))) var/stealamt = rand(2,3) src.temp = "[src.enemy_name] steals [stealamt] of your power!" + playsound(src.loc, 'sound/arcade/Steal.ogg', 50, 1, extrarange = -3, falloff = 10) src.player_mp -= stealamt src.updateUsrDialog() @@ -234,6 +240,7 @@ src.gameover = 1 sleep(10) src.temp = "You have been drained! GAME OVER" + playsound(src.loc, 'sound/arcade/Lose.ogg', 50, 1, extrarange = -3, falloff = 10) if(emagged) feedback_inc("arcade_loss_mana_emagged") usr.gib() @@ -242,17 +249,20 @@ else if ((src.enemy_hp <= 10) && (src.enemy_mp > 4)) src.temp = "[src.enemy_name] heals for 4 health!" + playsound(src.loc, 'sound/arcade/Heal.ogg', 50, 1, extrarange = -3, falloff = 10) src.enemy_hp += 4 src.enemy_mp -= 4 else var/attackamt = rand(3,6) src.temp = "[src.enemy_name] attacks for [attackamt] damage!" + playsound(src.loc, 'sound/arcade/Hit.ogg', 50, 1, extrarange = -3, falloff = 10) src.player_hp -= attackamt if ((src.player_mp <= 0) || (src.player_hp <= 0)) src.gameover = 1 src.temp = "You have been crushed! GAME OVER" + playsound(src.loc, 'sound/arcade/Lose.ogg', 50, 1, extrarange = -3, falloff = 10) if(emagged) feedback_inc("arcade_loss_hp_emagged") usr.gib() diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index c7b8dc92fe8..ae1a9fb771d 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -46,6 +46,8 @@ var/hasShocked = 0 //Prevents multiple shocks from happening var/autoclose = 1 + explosion_block = 1 + /obj/machinery/door/airlock/command icon = 'icons/obj/doors/Doorcom.dmi' doortype = /obj/structure/door_assembly/door_assembly_com @@ -268,6 +270,7 @@ name = "high tech security airlock" icon = 'icons/obj/doors/hightechsecurity.dmi' doortype = /obj/structure/door_assembly/door_assembly_highsecurity + explosion_block = 2 /obj/machinery/door/airlock/shuttle name = "shuttle airlock" diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index e558ccbac61..c1836108462 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -6,6 +6,7 @@ var/id = 1 var/auto_close = 0 // Time in seconds to automatically close when opened, 0 if it doesn't. sub_door = 1 + explosion_block = 3 heat_proof = 1 /obj/machinery/door/poddoor/preopen @@ -87,318 +88,27 @@ operating = 0 +//"BLAST" doors are obviously stronger than regular doors when it comes to BLASTS. +/obj/machinery/door/poddoor/ex_act(severity, target) + switch(severity) + if(1.0) + if(prob(80)) + qdel(src) + else + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() + if(2.0) + if(prob(20)) + qdel(src) + else + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() + if(3.0) + if(prob(80)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() -/* -/obj/machinery/door/poddoor/two_tile_hor/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - src.SetOpacity(0) - f1.SetOpacity(0) - f2.SetOpacity(0) - - sleep(10) - src.density = 0 - f1.density = 0 - f2.density = 0 - - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/two_tile_hor/close() - if (src.operating) - return - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - - src.density = 1 - f1.density = 1 - f2.density = 1 - - sleep(10) - src.SetOpacity(initial(opacity)) - f1.SetOpacity(initial(opacity)) - f2.SetOpacity(initial(opacity)) - - update_nearby_tiles() - - src.operating = 0 - return - -/obj/machinery/door/poddoor/four_tile_hor/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - sleep(10) - src.density = 0 - src.sd_SetOpacity(0) - - f1.density = 0 - f1.sd_SetOpacity(0) - f2.density = 0 - f2.sd_SetOpacity(0) - f3.density = 0 - f3.sd_SetOpacity(0) - f4.density = 0 - f4.sd_SetOpacity(0) - - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/four_tile_hor/close() - if (src.operating) - return - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - src.density = 1 - - f1.density = 1 - f1.sd_SetOpacity(1) - f2.density = 1 - f2.sd_SetOpacity(1) - f3.density = 1 - f3.sd_SetOpacity(1) - f4.density = 1 - f4.sd_SetOpacity(1) - - if (src.visible) - src.sd_SetOpacity(1) - update_nearby_tiles() - - sleep(10) - src.operating = 0 - return - -/obj/machinery/door/poddoor/two_tile_ver/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - sleep(10) - src.density = 0 - src.sd_SetOpacity(0) - - f1.density = 0 - f1.sd_SetOpacity(0) - f2.density = 0 - f2.sd_SetOpacity(0) - - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/two_tile_ver/close() - if (src.operating) - return - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - src.density = 1 - - f1.density = 1 - f1.sd_SetOpacity(1) - f2.density = 1 - f2.sd_SetOpacity(1) - - if (src.visible) - src.sd_SetOpacity(1) - update_nearby_tiles() - - sleep(10) - src.operating = 0 - return - -/obj/machinery/door/poddoor/four_tile_ver/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - sleep(10) - src.density = 0 - src.sd_SetOpacity(0) - - f1.density = 0 - f1.sd_SetOpacity(0) - f2.density = 0 - f2.sd_SetOpacity(0) - f3.density = 0 - f3.sd_SetOpacity(0) - f4.density = 0 - f4.sd_SetOpacity(0) - - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/four_tile_ver/close() - if (src.operating) - return - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - src.density = 1 - - f1.density = 1 - f1.sd_SetOpacity(1) - f2.density = 1 - f2.sd_SetOpacity(1) - f3.density = 1 - f3.sd_SetOpacity(1) - f4.density = 1 - f4.sd_SetOpacity(1) - - if (src.visible) - src.sd_SetOpacity(1) - update_nearby_tiles() - - sleep(10) - src.operating = 0 - return - - - - -/obj/machinery/door/poddoor/two_tile_hor - var/obj/machinery/door/poddoor/filler_object/f1 - var/obj/machinery/door/poddoor/filler_object/f2 - icon = 'icons/obj/doors/1x2blast_hor.dmi' - - New() - ..() - f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) - f2 = new/obj/machinery/door/poddoor/filler_object (get_step(src,EAST)) - f1.density = density - f2.density = density - f1.sd_SetOpacity(opacity) - f2.sd_SetOpacity(opacity) - - Destroy() - qdel(f1) - qdel(f2) - ..() - -/obj/machinery/door/poddoor/two_tile_ver - var/obj/machinery/door/poddoor/filler_object/f1 - var/obj/machinery/door/poddoor/filler_object/f2 - icon = 'icons/obj/doors/1x2blast_vert.dmi' - - New() - ..() - f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) - f2 = new/obj/machinery/door/poddoor/filler_object (get_step(src,NORTH)) - f1.density = density - f2.density = density - f1.sd_SetOpacity(opacity) - f2.sd_SetOpacity(opacity) - - Destroy() - qdel(f1) - qdel(f2) - ..() - -/obj/machinery/door/poddoor/four_tile_hor - var/obj/machinery/door/poddoor/filler_object/f1 - var/obj/machinery/door/poddoor/filler_object/f2 - var/obj/machinery/door/poddoor/filler_object/f3 - var/obj/machinery/door/poddoor/filler_object/f4 - icon = 'icons/obj/doors/1x4blast_hor.dmi' - - New() - ..() - f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) - f2 = new/obj/machinery/door/poddoor/filler_object (get_step(f1,EAST)) - f3 = new/obj/machinery/door/poddoor/filler_object (get_step(f2,EAST)) - f4 = new/obj/machinery/door/poddoor/filler_object (get_step(f3,EAST)) - f1.density = density - f2.density = density - f3.density = density - f4.density = density - f1.sd_SetOpacity(opacity) - f2.sd_SetOpacity(opacity) - f4.sd_SetOpacity(opacity) - f3.sd_SetOpacity(opacity) - - Destroy() - qdel(f1) - qdel(f2) - qdel(f3) - qdel(f4) - ..() - -/obj/machinery/door/poddoor/four_tile_ver - var/obj/machinery/door/poddoor/filler_object/f1 - var/obj/machinery/door/poddoor/filler_object/f2 - var/obj/machinery/door/poddoor/filler_object/f3 - var/obj/machinery/door/poddoor/filler_object/f4 - icon = 'icons/obj/doors/1x4blast_vert.dmi' - - New() - ..() - f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) - f2 = new/obj/machinery/door/poddoor/filler_object (get_step(f1,NORTH)) - f3 = new/obj/machinery/door/poddoor/filler_object (get_step(f2,NORTH)) - f4 = new/obj/machinery/door/poddoor/filler_object (get_step(f3,NORTH)) - f1.density = density - f2.density = density - f3.density = density - f4.density = density - f1.sd_SetOpacity(opacity) - f2.sd_SetOpacity(opacity) - f4.sd_SetOpacity(opacity) - f3.sd_SetOpacity(opacity) - - Destroy() - qdel(f1) - qdel(f2) - qdel(f3) - qdel(f4) - ..() - -/obj/machinery/door/poddoor/filler_object - name = "" - icon_state = "" - -*/ \ No newline at end of file diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm index df94284c2c5..f8c634f9724 100644 --- a/code/game/machinery/doors/unpowered.dm +++ b/code/game/machinery/doors/unpowered.dm @@ -21,4 +21,5 @@ name = "door" icon_state = "door1" opacity = 1 - density = 1 \ No newline at end of file + density = 1 + explosion_block = 1 \ No newline at end of file diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 63620b72676..7e1fd4d977c 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -90,6 +90,18 @@ for(var/turf/T in trange(max_range, epicenter)) var/dist = cheap_pythag(T.x - x0,T.y - y0) + + if(config.reactionary_explosions) + var/turf/Trajectory = T + while(Trajectory != epicenter) + Trajectory = get_step_towards(Trajectory, epicenter) + if(Trajectory.density && Trajectory.explosion_block) + dist += Trajectory.explosion_block + + for(var/obj/machinery/door/D in Trajectory) + if(D.density && D.explosion_block) + dist += D.explosion_block + var/flame_dist = 0 var/throw_dist = dist @@ -138,3 +150,76 @@ /proc/secondaryexplosion(turf/epicenter, range) for(var/turf/tile in trange(range, epicenter)) tile.ex_act(2) + + +/client/proc/check_bomb_impacts() + set name = "Check Bomb Impact" + set category = "Debug" + + var/newmode = alert("Use reactionary explosions?","Check Bomb Impact", "Yes", "No") + var/turf/epicenter = get_turf(mob) + if(!epicenter) + return + + var/dev = 0 + var/heavy = 0 + var/light = 0 + var/list/choices = list("Small Bomb","Medium Bomb","Big Bomb","Custom Bomb") + var/choice = input("Bomb Size?") in choices + switch(choice) + if(null) + return 0 + if("Small Bomb") + dev = 1 + heavy = 2 + light = 3 + if("Medium Bomb") + dev = 2 + heavy = 3 + light = 4 + if("Big Bomb") + dev = 3 + heavy = 5 + light = 7 + if("Custom Bomb") + dev = input("Devestation range (Tiles):") as num + heavy = input("Heavy impact range (Tiles):") as num + light = input("Light impact range (Tiles):") as num + + var/max_range = max(dev, heavy, light) + var/x0 = epicenter.x + var/y0 = epicenter.y + var/list/wipe_colours = list() + for(var/turf/T in trange(max_range, epicenter)) + wipe_colours += T + var/dist = cheap_pythag(T.x - x0, T.y - y0) + + if(newmode == "Yes") + var/turf/TT = T + while(TT != epicenter) + TT = get_step_towards(TT,epicenter) + if(TT.density && TT.explosion_block) + dist += TT.explosion_block + + for(var/obj/machinery/door/D in TT) + if(D.density && D.explosion_block) + dist += D.explosion_block + + if(dist < dev) + T.color = "red" + T.maptext = "Dev" + else if (dist < heavy) + T.color = "yellow" + T.maptext = "Heavy" + else if (dist < light) + T.color = "blue" + T.maptext = "Light" + else + continue + + sleep(100) + for(var/turf/T in wipe_colours) + T.color = null + T.maptext = "" + + diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm index aeb17f0df26..83dcbf39f7c 100644 --- a/code/game/objects/items/blueprints.dm +++ b/code/game/objects/items/blueprints.dm @@ -58,7 +58,7 @@ . = ..() var/area/A = get_area() if(get_area_type() == AREA_STATION) - . += "

According to \the [src], you are now in \"[strip_html_properly(A.name)]\".

" + . += "

According to \the [src], you are now in \"[html_encode(A.name)]\".

" var/datum/browser/popup = new(user, "blueprints", "[src]", 700, 500) popup.set_content(.) popup.open() @@ -83,7 +83,7 @@ . = ..() var/area/A = get_area() if(get_area_type() == AREA_STATION) - . += "

According to \the [src], you are now in \"[strip_html_properly(A.name)]\".

" + . += "

According to \the [src], you are now in \"[html_encode(A.name)]\".

" . += "

You may move an amendment to the drawing.

" var/datum/browser/popup = new(user, "blueprints", "[src]", 700, 500) popup.set_content(.) diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 731a7324b81..a512741096f 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -97,10 +97,7 @@ /obj/item/toy/crayon/spraycan/New() ..() - if(gang) - name = "Modified Paint Applicator" - else - name = "NanoTrasen-brand Rapid Paint Applicator" + name = "spray can" update_icon() /obj/item/toy/crayon/spraycan/examine(mob/user) @@ -116,7 +113,7 @@ if("Toggle Cap") user << "You [capped ? "Remove" : "Replace"] the cap of the [src]" capped = capped ? 0 : 1 - icon_state = "spraycan[gang ? "_gang" : ""][capped ? "_cap" : ""]" + icon_state = "spraycan[capped ? "_cap" : ""]" update_icon() if("Change Drawing") ..() @@ -155,8 +152,7 @@ overlays += I /obj/item/toy/crayon/spraycan/gang - desc = "A suspicious-looking spraycan modified to use special paint used by gangsters to mark territory." - icon_state = "spraycan_gang_cap" + desc = "A modified container containing suspicious paint." gang = 1 uses = 20 instant = -1 diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 18376a20ea0..16f19760d7d 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -1032,7 +1032,7 @@ var/global/list/obj/item/device/pda/PDAs = list() note = replacetext(note, "
  • ", "\[*\]") note = replacetext(note, "", "\[/list\]") - note = strip_html_properly(note) + note = html_encode(note) notescanned = 1 user << "Paper scanned. Saved to PDA's notekeeper." //concept of scanning paper copyright brainoblivion 2009 @@ -1186,7 +1186,7 @@ var/global/list/obj/item/device/pda/PDAs = list() //ntrc handler proc /obj/item/device/pda/proc/msg_chat(channel as text, sender as text, message as text) - var/msg = "[strip_html_properly(sender)]| [strip_html_properly(message)]
    " + var/msg = "[html_encode(sender)]| [html_encode(message)]
    " if(!channel) for(var/C in ntrclog) ntrclog[C] = msg + ntrclog[C] diff --git a/code/game/objects/items/devices/PDA/chatroom.dm b/code/game/objects/items/devices/PDA/chatroom.dm index 1cc8d642cd3..a46b4def36f 100644 --- a/code/game/objects/items/devices/PDA/chatroom.dm +++ b/code/game/objects/items/devices/PDA/chatroom.dm @@ -66,7 +66,7 @@ var/list/chatchannels = list(default_ntrc_chatroom.name = default_ntrc_chatroom) /datum/chatroom/proc/send_message(client,nick,message) //standard message if(!message) return 0 - logs.Insert(1,"[strip_html_properly(nick)]> [strip_html_properly(message)]") + logs.Insert(1,"[html_encode(nick)]> [html_encode(message)]") log_chat("[usr]/([usr.ckey]) as [nick] sent to [name]: [message]") events.fireEvent("msg_chat",name,nick,message) return 1 diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index 862fc2a89b8..bca8126ad81 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -30,23 +30,24 @@ ..() SSobj.processing += src - /obj/item/device/multitool/ai_detect/Destroy() SSobj.processing -= src ..() /obj/item/device/multitool/ai_detect/process() - if(track_delay > world.time) return var/found_eye = 0 var/turf/our_turf = get_turf(src) - if(cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z)) + for(var/mob/living/silicon/ai/AI in ai_list) + if(AI.cameraFollow == src) + found_eye = 1 + break + if(!found_eye && cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z)) var/datum/camerachunk/chunk = cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z) - if(chunk) if(chunk.seenby.len) for(var/mob/camera/aiEye/A in chunk.seenby) @@ -62,4 +63,3 @@ track_delay = world.time + 10 // 1 second return - diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 2a8ef3cae0b..fd5cb821462 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -100,7 +100,7 @@ /obj/item/device/taperecorder/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans) if(mytape && recording) mytape.timestamp += mytape.used_capacity - mytape.storedinfo += "\[[time2text(mytape.used_capacity * 10,"mm:ss")]\] [strip_html_properly(message)]" + mytape.storedinfo += "\[[time2text(mytape.used_capacity * 10,"mm:ss")]\] [html_encode(message)]" /obj/item/device/taperecorder/verb/record() set name = "Start Recording" diff --git a/code/game/objects/items/holotape.dm b/code/game/objects/items/holotape.dm index bd10a107cad..68070972d6e 100644 --- a/code/game/objects/items/holotape.dm +++ b/code/game/objects/items/holotape.dm @@ -153,6 +153,8 @@ charging = 0 /obj/item/holotape/Bumped(var/mob/M) + if(!ismob(M)) + return if(iscarbon(M)) var/mob/living/carbon/C = M if(C.m_intent == "walk") @@ -227,11 +229,11 @@ /obj/item/holotape/proc/breaktape() var/dir[2] - var/icon_dir = src.icon_state - if(icon_dir == "[src.icon_base]_h") + var/icon_dir = icon_state + if(icon_dir == "[icon_base]_h") dir[1] = EAST dir[2] = WEST - if(icon_dir == "[src.icon_base]_v") + if(icon_dir == "[icon_base]_v") dir[1] = NORTH dir[2] = SOUTH diff --git a/code/game/objects/items/stacks/sheets/sheets.dm b/code/game/objects/items/stacks/sheets/sheets.dm index 34522d2ec59..35d3ae089ce 100644 --- a/code/game/objects/items/stacks/sheets/sheets.dm +++ b/code/game/objects/items/stacks/sheets/sheets.dm @@ -8,18 +8,4 @@ throw_range = 3 attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed") var/perunit = MINERAL_MATERIAL_AMOUNT - var/sheettype = null //this is used for girders in the creation of walls/false walls - - -// Since the sheetsnatcher was consolidated into weapon/storage/bag we now use -// item/attackby() properly, making this unnecessary - -/*/obj/item/stack/sheet/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/storage/bag/sheetsnatcher)) - var/obj/item/weapon/storage/bag/sheetsnatcher/S = W - if(!S.mode) - S.add(src,user) - else - for (var/obj/item/stack/sheet/stack in locate(src.x,src.y,src.z)) - S.add(stack,user) - ..()*/ \ No newline at end of file + var/sheettype = null //this is used for girders in the creation of walls/false walls \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index 92ebff9c716..7519804b005 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -335,3 +335,17 @@ ..() +/* + * Chemistry bag + */ + +/obj/item/weapon/storage/bag/chemistry + name = "chemistry bag" + icon = 'icons/obj/chemical.dmi' + icon_state = "bag" + desc = "A bag for storing pills, patches, and bottles." + storage_slots = 50 + max_combined_w_class = 200 + w_class = 1 + preposition = "in" + can_hold = list(/obj/item/weapon/reagent_containers/pill, /obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/reagent_containers/glass/bottle) diff --git a/code/game/objects/items/weapons/storage/book.dm b/code/game/objects/items/weapons/storage/book.dm index 9a71db5ab8d..5d5eb001840 100644 --- a/code/game/objects/items/weapons/storage/book.dm +++ b/code/game/objects/items/weapons/storage/book.dm @@ -68,11 +68,9 @@ var/global/list/bibleitemstates = list("bible", "koran", "scrapbook", "bible", " /obj/item/weapon/storage/book/bible/proc/setupbiblespecifics(var/obj/item/weapon/storage/book/bible/B, var/mob/living/carbon/human/H) switch(B.icon_state) if("honk1","honk2") - new /obj/item/weapon/grown/bananapeel(B) - new /obj/item/weapon/grown/bananapeel(B) - - if(B.icon_state == "honk1") - H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), slot_wear_mask) + new /obj/item/weapon/bikehorn(B) + H.dna.add_mutation(CLOWNMUT) + H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), slot_wear_mask) if("bible") for(var/area/chapel/main/A in world) @@ -211,4 +209,4 @@ var/global/list/bibleitemstates = list("bible", "koran", "scrapbook", "bible", " /obj/item/weapon/storage/book/bible/attackby(obj/item/weapon/W as obj, mob/user as mob, params) playsound(src.loc, "rustle", 50, 1, -5) - ..() \ No newline at end of file + ..() diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index bae96ce7ef0..dde6cba1c31 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -1,6 +1,5 @@ /obj languages = HUMAN - //var/datum/module/mod //not used var/crit_fail = 0 var/unacidable = 0 //universal "unacidabliness" var, here so you can use it in any obj. animate_movement = 2 diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 85f3f7582bb..9de891501fa 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -68,7 +68,7 @@ return (!density) /obj/structure/closet/proc/can_open() - if(src.welded || src.locked) + if(welded || locked) return 0 return 1 @@ -81,32 +81,32 @@ /obj/structure/closet/proc/dump_contents() for(var/obj/O in src) - O.loc = src.loc + O.loc = loc for(var/mob/M in src) - M.loc = src.loc + M.loc = loc if(M.client) M.client.eye = M.client.mob M.client.perspective = MOB_PERSPECTIVE /obj/structure/closet/proc/take_contents() - for(var/atom/movable/AM in src.loc) + for(var/atom/movable/AM in loc) if(insert(AM) == -1) // limit reached break /obj/structure/closet/proc/open() - if(src.opened) + if(opened) return 0 - if(!src.can_open()) + if(!can_open()) return 0 - src.dump_contents() + dump_contents() - src.opened = 1 + opened = 1 if(istype(src, /obj/structure/closet/body_bag)) - playsound(src.loc, 'sound/items/zip.ogg', 15, 1, -3) + playsound(loc, 'sound/items/zip.ogg', 15, 1, -3) else - playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) + playsound(loc, 'sound/machines/click.ogg', 15, 1, -3) density = 0 update_icon() return 1 @@ -139,25 +139,25 @@ return 1 /obj/structure/closet/proc/close() - if(!src.opened) + if(!opened) return 0 - if(!src.can_close()) + if(!can_close()) return 0 take_contents() - src.opened = 0 + opened = 0 if(istype(src, /obj/structure/closet/body_bag)) - playsound(src.loc, 'sound/items/zip.ogg', 15, 1, -3) + playsound(loc, 'sound/items/zip.ogg', 15, 1, -3) else - playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) + playsound(loc, 'sound/machines/click.ogg', 15, 1, -3) density = 1 update_icon() return 1 /obj/structure/closet/proc/toggle() - if(src.opened) - return src.close() - return src.open() + if(opened) + return close() + return open() /obj/structure/closet/ex_act(severity, target) contents_explosion(severity, target) @@ -192,9 +192,9 @@ return if(opened) if(istype(W, /obj/item/weapon/grab)) - if(src.large) + if(large) var/obj/item/weapon/grab/G = W - src.MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet + MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet user.drop_item() else user << "The locker is too small to stuff [W] into!" @@ -210,7 +210,7 @@ if( !opened || !istype(src, /obj/structure/closet) || !user || !WT || !WT.isOn() || !user.loc ) return playsound(loc, 'sound/items/Welder2.ogg', 50, 1) - new /obj/item/stack/sheet/metal(src.loc) + new /obj/item/stack/sheet/metal(loc) visible_message("[user] has cut \the [src] apart with \the [WT].", "You hear welding.") qdel(src) return @@ -239,10 +239,10 @@ user << "The locker appears to be broken." return if(!place(user, W) && !isnull(W)) - src.attack_hand(user) + attack_hand(user) /obj/structure/closet/proc/place(var/mob/user, var/obj/item/I) - if(!src.opened && secure) + if(!opened && secure) togglelock(user) return 1 return 0 @@ -258,21 +258,21 @@ return 0 if(!istype(user.loc, /turf)) // are you in a container/closet/pod/etc? Will also check for null loc return 0 - if(needs_opened && !src.opened) + if(needs_opened && !opened) return 0 if(istype(O, /obj/structure/closet)) return 0 if(move_them) - step_towards(O, src.loc) + step_towards(O, loc) if(show_message && user != O) user.show_viewers("[user] stuffs [O] into [src]!") - src.add_fingerprint(user) + add_fingerprint(user) return 1 /obj/structure/closet/relaymove(mob/user as mob) - if(user.stat || !isturf(src.loc)) + if(user.stat || !isturf(loc)) return - if(!src.open()) + if(!open()) user << "It won't budge!" if(world.time > lastbang+5) lastbang = world.time @@ -281,19 +281,20 @@ /obj/structure/closet/attack_paw(mob/user as mob) - return src.attack_hand(user) + return attack_hand(user) /obj/structure/closet/attack_hand(mob/user as mob) - src.add_fingerprint(user) + add_fingerprint(user) if(user.lying && get_dist(src, user) > 0) return - if(!src.toggle()) - return src.attackby(null, user) + if(!toggle()) + user << "You cannot close the locker!" + return // tk grab then use on self /obj/structure/closet/attack_self_tk(mob/user as mob) - return src.attack_hand(user) + return attack_hand(user) /obj/structure/closet/verb/verb_toggleopen() set src in oview(1) @@ -304,7 +305,7 @@ return if(iscarbon(usr) || issilicon(usr)) - src.attack_hand(usr) + attack_hand(usr) else usr << "This mob type can't use this verb." @@ -322,7 +323,7 @@ if(istype(user.loc, /obj/structure/closet/critter) && !welded) breakout_time = 0.75 //45 seconds if it's an unwelded critter crate - if( opened || (!welded && !locked && !istype(src.loc, /obj/mecha)) ) + if( opened || (!welded && !locked && !istype(loc, /obj/mecha)) ) return //Door's open, not locked or welded or inside a mech, no point in resisting. //okay, so the closet is either welded or locked... resist!!! @@ -332,7 +333,7 @@ for(var/mob/O in viewers(src)) O << "[src] begins to shake violently!" if(do_after(user,(breakout_time*60*10))) //minutes * 60seconds * 10deciseconds - if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded && !istype(src.loc, /obj/mecha)) ) + if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded && !istype(loc, /obj/mecha)) ) return //we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting @@ -340,11 +341,11 @@ locked = 0 //applies to critter crates and secure lockers only broken = 1 //applies to secure lockers only user.visible_message("[user] successfully broke out of [src]!", "You successfully break out of [src]!") - if(istype( src.loc, /obj/structure/bigDelivery)) - var/obj/structure/bigDelivery/D = src.loc + if(istype( loc, /obj/structure/bigDelivery)) + var/obj/structure/bigDelivery/D = loc qdel(D) - else if(istype( src.loc, /obj/mecha)) - src.loc = get_turf(src.loc) + else if(istype( loc, /obj/mecha)) + loc = get_turf(loc) open() else user << "You fail to break out of [src]!" @@ -354,7 +355,7 @@ if(!user.canUseTopic(user) || broken) user << "You can't do that right now!" return - if(src.opened || !secure || !in_range(src, user)) + if(opened || !secure || !in_range(src, user)) return else togglelock(user) @@ -364,20 +365,20 @@ O.emp_act(severity) if(secure && !broken) if(prob(50/severity)) - src.locked = !src.locked - src.update_icon() + locked = !locked + update_icon() if(prob(20/severity) && !opened) if(!locked) open() else - src.req_access = list() - src.req_access += pick(get_all_accesses()) + req_access = list() + req_access += pick(get_all_accesses()) ..() /obj/structure/closet/proc/togglelock(mob/user as mob) if(secure) - if(src.allowed(user)) - src.locked = !src.locked + if(allowed(user)) + locked = !locked add_fingerprint(user) for(var/mob/O in viewers(user, 3)) if((O.client && !( O.eye_blind ))) diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm index a4510966df7..37433c2423c 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -311,6 +311,8 @@ new /obj/item/weapon/storage/backpack/chemistry(src) new /obj/item/weapon/storage/backpack/satchel_chem(src) new /obj/item/weapon/storage/backpack/satchel_chem(src) + new /obj/item/weapon/storage/bag/chemistry(src) + new /obj/item/weapon/storage/bag/chemistry(src) return diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 6eb5f7b9317..ffe58681ab0 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -106,7 +106,20 @@ name = "magic mirror" desc = "Turn and face the strange... face." icon_state = "magic_mirror" + var/list/races_blacklist = list("skeleton") + var/list/choosable_races = list() +/obj/structure/mirror/magic/New() + if(!choosable_races.len) + for(var/datum/species/S in typesof(/datum/species) - /datum/species) + if(!(S.id in races_blacklist)) + choosable_races += S + ..() + +/obj/structure/mirror/magic/badmin/New() + for(var/datum/species/S in typesof(/datum/species) - /datum/species) + choosable_races += S + ..() /obj/structure/mirror/magic/attack_hand(mob/user as mob) if(!ishuman(user)) @@ -130,7 +143,7 @@ if("race") var/newrace - var/racechoice = input(H, "What are we again?", "Race change") as null|anything in species_list + var/racechoice = input(H, "What are we again?", "Race change") as null|anything in choosable_races newrace = species_list[racechoice] if(!newrace || !H.dna) diff --git a/code/game/objects/structures/table_frames.dm b/code/game/objects/structures/table_frames.dm index 4e44968971b..0b1f15d41b3 100644 --- a/code/game/objects/structures/table_frames.dm +++ b/code/game/objects/structures/table_frames.dm @@ -32,28 +32,37 @@ return if(istype(I, /obj/item/stack/sheet/plasteel)) var/obj/item/stack/sheet/plasteel/P = I + if(P.get_amount() < 1) + user << "You need one plasteel sheet to do this!" + return user << "You start adding [P] to [src]..." if(do_after(user, 50)) + P.use(1) new /obj/structure/table/reinforced(src.loc) qdel(src) - P.use(1) - return + return if(istype(I, /obj/item/stack/sheet/metal)) var/obj/item/stack/sheet/metal/M = I + if(M.get_amount() < 1) + user << "You need one metal sheet to do this!" + return user << "You start adding [M] to [src]..." if(do_after(user, 20)) + M.use(1) new /obj/structure/table(src.loc) qdel(src) - M.use(1) - return + return if(istype(I, /obj/item/stack/sheet/glass)) var/obj/item/stack/sheet/glass/G = I + if(G.get_amount() < 1) + user << "You need one glass sheet to do this!" + return user << "You start adding [G] to [src]..." if(do_after(user, 20)) + G.use(1) new /obj/structure/table/glass(src.loc) qdel(src) - G.use(1) - return + return /* * Wooden Frames @@ -71,17 +80,23 @@ ..() if(istype(I, /obj/item/stack/sheet/mineral/wood)) var/obj/item/stack/sheet/mineral/wood/W = I + if(W.get_amount() < 1) + user << "You need one wood sheet to do this!" + return user << "You start adding [W] to [src]..." if(do_after(user, 20)) + W.use(1) new /obj/structure/table/wood(src.loc) qdel(src) - W.use(1) - return + return if(istype(I, /obj/item/stack/tile/carpet)) var/obj/item/stack/tile/carpet/C = I + if(C.get_amount() < 1) + user << "You need one carpet sheet to do this!" + return user << "You start adding [C] to [src]..." if(do_after(user, 20)) + C.use(1) new /obj/structure/table/wood/poker(src.loc) qdel(src) - C.use(1) - return \ No newline at end of file + return \ No newline at end of file diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index b3a52450234..8262201bf28 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -29,7 +29,7 @@ /obj/structure/windoor_assembly/New(dir=NORTH) ..() - src.ini_dir = src.dir + ini_dir = dir air_update_turf(1) /obj/structure/windoor_assembly/Destroy() @@ -77,7 +77,7 @@ var/obj/item/weapon/weldingtool/WT = W if (WT.remove_fuel(0,user)) user.visible_message("[user] disassembles the windoor assembly.", "You start to disassemble the windoor assembly...") - playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1) + playsound(loc, 'sound/items/Welder2.ogg', 50, 1) if(do_after(user, 40)) if(!src || !WT.isOn()) return @@ -93,41 +93,41 @@ //Wrenching an unsecure assembly anchors it in place. Step 4 complete if(istype(W, /obj/item/weapon/wrench) && !anchored) - for(var/obj/machinery/door/window/WD in src.loc) - if(WD.dir == src.dir) + for(var/obj/machinery/door/window/WD in loc) + if(WD.dir == dir) user << "There is already a windoor in that location!" return - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + playsound(loc, 'sound/items/Ratchet.ogg', 100, 1) user.visible_message("[user] secures the windoor assembly to the floor.", "You start to secure the windoor assembly to the floor...") if(do_after(user, 40)) - if(!src || src.anchored) + if(!src || anchored) return - for(var/obj/machinery/door/window/WD in src.loc) - if(WD.dir == src.dir) + for(var/obj/machinery/door/window/WD in loc) + if(WD.dir == dir) user << "There is already a windoor in that location!" return user << "You secure the windoor assembly." - src.anchored = 1 - if(src.secure) - src.name = "secure anchored windoor assembly" + anchored = 1 + if(secure) + name = "secure anchored windoor assembly" else - src.name = "anchored windoor assembly" + name = "anchored windoor assembly" //Unwrenching an unsecure assembly un-anchors it. Step 4 undone else if(istype(W, /obj/item/weapon/wrench) && anchored) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + playsound(loc, 'sound/items/Ratchet.ogg', 100, 1) user.visible_message("[user] unsecures the windoor assembly to the floor.", "You start to unsecure the windoor assembly to the floor...") if(do_after(user, 40)) - if(!src || !src.anchored) + if(!src || !anchored) return user << "You unsecure the windoor assembly." - src.anchored = 0 - if(src.secure) - src.name = "secure windoor assembly" + anchored = 0 + if(secure) + name = "secure windoor assembly" else - src.name = "windoor assembly" + name = "windoor assembly" //Adding plasteel makes the assembly a secure windoor assembly. Step 2 (optional) complete. else if(istype(W, /obj/item/stack/sheet/plasteel) && !secure) @@ -143,27 +143,29 @@ P.use(2) user << "You reinforce the windoor." - src.secure = 1 - if(src.anchored) - src.name = "secure anchored windoor assembly" + secure = 1 + if(anchored) + name = "secure anchored windoor assembly" else - src.name = "secure windoor assembly" + name = "secure windoor assembly" //Adding cable to the assembly. Step 5 complete. else if(istype(W, /obj/item/stack/cable_coil) && anchored) user.visible_message("[user] wires the windoor assembly.", "You start to wire the windoor assembly...") if(do_after(user, 40)) - if(!src || !src.anchored || src.state != "01") + if(!src || !anchored || state != "01") return var/obj/item/stack/cable_coil/CC = W - CC.use(1) + if(!CC.use(1)) + user << "You need more cable to do this!" + return user << "You wire the windoor." - src.state = "02" - if(src.secure) - src.name = "secure wired windoor assembly" + state = "02" + if(secure) + name = "secure wired windoor assembly" else - src.name = "wired windoor assembly" + name = "wired windoor assembly" else ..() @@ -171,61 +173,61 @@ //Removing wire from the assembly. Step 5 undone. if(istype(W, /obj/item/weapon/wirecutters)) - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) + playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1) user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly...") if(do_after(user, 40)) - if(!src || src.state != "02") + if(!src || state != "02") return user << "You cut the windoor wires." new/obj/item/stack/cable_coil(get_turf(user), 1) - src.state = "01" - if(src.secure) - src.name = "secure anchored windoor assembly" + state = "01" + if(secure) + name = "secure anchored windoor assembly" else - src.name = "anchored windoor assembly" + name = "anchored windoor assembly" //Adding airlock electronics for access. Step 6 complete. else if(istype(W, /obj/item/weapon/airlock_electronics)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) + playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1) user.visible_message("[user] installs the electronics into the airlock assembly.", "You start to install electronics into the airlock assembly...") user.drop_item() W.loc = src if(do_after(user, 40)) - if(!src || src.electronics) - W.loc = src.loc + if(!src || electronics) + W.loc = loc return user << "You install the airlock electronics." - src.name = "near finished windoor assembly" - src.electronics = W + name = "near finished windoor assembly" + electronics = W else - W.loc = src.loc + W.loc = loc //Screwdriver to remove airlock electronics. Step 6 undone. else if(istype(W, /obj/item/weapon/screwdriver)) if(!electronics) return - playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) + playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1) user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to uninstall electronics from the airlock assembly...") if(do_after(user, 40)) if(!src || !electronics) return user << "You remove the airlock electronics." - src.name = "wired windoor assembly" + name = "wired windoor assembly" var/obj/item/weapon/airlock_electronics/ae ae = electronics electronics = null - ae.loc = src.loc + ae.loc = loc else if(istype(W, /obj/item/weapon/pen)) - var/t = stripped_input(user, "Enter the name for the door.", src.name, src.created_name,MAX_NAME_LEN) + var/t = stripped_input(user, "Enter the name for the door.", name, created_name,MAX_NAME_LEN) if(!t) return - if(!in_range(src, usr) && src.loc != usr) + if(!in_range(src, usr) && loc != usr) return created_name = t return @@ -234,37 +236,37 @@ //Crowbar to complete the assembly, Step 7 complete. else if(istype(W, /obj/item/weapon/crowbar)) - if(!src.electronics) + if(!electronics) usr << "The assembly is missing electronics!" return usr << browse(null, "window=windoor_access") - playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) + playsound(loc, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] pries the windoor into the frame.", "You start prying the windoor into the frame...") if(do_after(user, 40)) - if(src.loc && src.electronics) + if(loc && electronics) density = 1 //Shouldn't matter but just incase user << "You finish the windoor." if(secure) - var/obj/machinery/door/window/brigdoor/windoor = new /obj/machinery/door/window/brigdoor(src.loc) - if(src.facing == "l") + var/obj/machinery/door/window/brigdoor/windoor = new /obj/machinery/door/window/brigdoor(loc) + if(facing == "l") windoor.icon_state = "leftsecureopen" windoor.base_state = "leftsecure" else windoor.icon_state = "rightsecureopen" windoor.base_state = "rightsecure" - windoor.dir = src.dir + windoor.dir = dir windoor.density = 0 - if(src.electronics.use_one_access) - windoor.req_one_access = src.electronics.conf_access + if(electronics.use_one_access) + windoor.req_one_access = electronics.conf_access else - windoor.req_access = src.electronics.conf_access - windoor.electronics = src.electronics - src.electronics.loc = windoor + windoor.req_access = electronics.conf_access + windoor.electronics = electronics + electronics.loc = windoor if(created_name) windoor.name = created_name qdel(src) @@ -272,19 +274,19 @@ else - var/obj/machinery/door/window/windoor = new /obj/machinery/door/window(src.loc) - if(src.facing == "l") + var/obj/machinery/door/window/windoor = new /obj/machinery/door/window(loc) + if(facing == "l") windoor.icon_state = "leftopen" windoor.base_state = "left" else windoor.icon_state = "rightopen" windoor.base_state = "right" - windoor.dir = src.dir + windoor.dir = dir windoor.density = 0 - windoor.req_access = src.electronics.conf_access - windoor.electronics = src.electronics - src.electronics.loc = windoor + windoor.req_access = electronics.conf_access + windoor.electronics = electronics + electronics.loc = windoor if(created_name) windoor.name = created_name qdel(src) @@ -305,18 +307,18 @@ set src in oview(1) if(usr.stat || !usr.canmove || usr.restrained()) return - if (src.anchored) + if (anchored) usr << "It is fastened to the floor; therefore, you can't rotate it!" return 0 - //if(src.state != "01") + //if(state != "01") //update_nearby_tiles(need_rebuild=1) //Compel updates before - src.dir = turn(src.dir, 270) + dir = turn(dir, 270) - //if(src.state != "01") + //if(state != "01") //update_nearby_tiles(need_rebuild=1) - src.ini_dir = src.dir + ini_dir = dir update_icon() return @@ -328,11 +330,11 @@ if(usr.stat || !usr.canmove || usr.restrained()) return - if(src.facing == "l") + if(facing == "l") usr << "The windoor will now slide to the right." - src.facing = "r" + facing = "r" else - src.facing = "l" + facing = "l" usr << "The windoor will now slide to the left." update_icon() diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 6e565879c9f..25f2ec88ecb 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -105,6 +105,28 @@ ChangeTurf(/turf/simulated/floor/plating) return + +/turf/simulated/floor/engine/ex_act(severity,target) + switch(severity) + if(1.0) + if(prob(80)) + ReplaceWithLattice() + else if(prob(50)) + qdel(src) + else + make_plating(1) + if(2.0) + if(prob(50)) + make_plating(1) + + +/turf/simulated/floor/engine/cult + name = "engraved floor" + icon_state = "cult" + +/turf/simulated/floor/engine/cult/narsie_act() + return + /turf/simulated/floor/engine/n20/New() ..() var/datum/gas_mixture/adding = new diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index af5a84bdc3c..2829c18e6c9 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -6,6 +6,7 @@ opacity = 1 density = 1 blocks_air = 1 + explosion_block = 1 thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m plasteel wall diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm index c61a20cb100..fb73c1f61c6 100644 --- a/code/game/turfs/simulated/walls_mineral.dm +++ b/code/game/turfs/simulated/walls_mineral.dm @@ -17,6 +17,7 @@ mineral = "gold" //var/electro = 1 //var/shocked = null + explosion_block = 0 //gold is a soft metal you dingus. /turf/simulated/wall/mineral/silver name = "silver wall" @@ -34,6 +35,7 @@ walltype = "diamond" mineral = "diamond" slicing_duration = 200 //diamond wall takes twice as much time to slice + explosion_block = 3 /turf/simulated/wall/mineral/diamond/thermitemelt(mob/user as mob) return @@ -51,6 +53,7 @@ icon_state = "sandstone0" walltype = "sandstone" mineral = "sandstone" + explosion_block = 0 /turf/simulated/wall/mineral/uranium name = "uranium wall" @@ -143,3 +146,4 @@ walltype = "wood" mineral = "wood" hardness = 70 + explosion_block = 0 \ No newline at end of file diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index aec87adc748..00f6f38825f 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -10,6 +10,7 @@ var/d_state = 0 hardness = 10 sheet_type = /obj/item/stack/sheet/plasteel + explosion_block = 2 /turf/simulated/wall/r_wall/break_wall() builtin_sheet.loc = src diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index c87a61c076c..1c073505ab8 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -10,6 +10,7 @@ var/list/admin_verbs_default = list( /client/proc/deadchat, /*toggles deadchat on/off*/ /client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/ /client/proc/toggleprayers, /*toggles prayers on/off*/ + /client/verb/toggleprayersounds, /*Toggles prayer sounds (HALLELUJAH!)*/ /client/proc/toggle_hear_radio, /*toggles whether we hear the radio*/ /client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/ /client/proc/secrets, @@ -121,6 +122,7 @@ var/list/admin_verbs_debug = list( /client/proc/test_movable_UI, /client/proc/test_snap_UI, /client/proc/debugNatureMapGenerator, + /client/proc/check_bomb_impacts, /proc/machine_upgrade ) var/list/admin_verbs_possess = list( @@ -548,7 +550,7 @@ var/list/admin_verbs_hideable = list( var/list/Lines = file2list("config/admins.txt") for(var/line in Lines) var/list/splitline = text2list(line, " = ") - if(splitline[1] == ckey) + if(lowertext(splitline[1]) == ckey) if(splitline.len >= 2) rank = ckeyEx(splitline[2]) break diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 334190fbd20..14d8693c3e5 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -307,7 +307,7 @@ if(ratio) config.midround_antag_life_check = ratio/100 - message_admins("[key_name_admin(usr)] edited the midround antagonist living crew ratio to [ratio * 100]% alive.") + message_admins("[key_name_admin(usr)] edited the midround antagonist living crew ratio to [ratio]% alive.") check_antagonists() else if(href_list["toggle_noncontinuous_behavior"]) @@ -1605,6 +1605,7 @@ message_admins("[key_name(H)] got their cookie, spawned by [key_name(src.owner)]") feedback_inc("admin_cookies_spawned",1) H << "Your prayers have been answered!! You received the best cookie!" + H << 'sound/effects/pray_chaplain.ogg' else if(href_list["BlueSpaceArtillery"]) var/mob/living/M = locate(href_list["BlueSpaceArtillery"]) diff --git a/code/modules/admin/verbs/buildmode.dm b/code/modules/admin/verbs/buildmode.dm index 767f30e1380..d06bd7e61c8 100644 --- a/code/modules/admin/verbs/buildmode.dm +++ b/code/modules/admin/verbs/buildmode.dm @@ -1,3 +1,10 @@ +#define BASIC_BUILDMODE 1 +#define ADV_BUILDMODE 2 +#define VAR_BUILDMODE 3 +#define THROW_BUILDMODE 4 +#define AREA_BUILDMODE 5 +#define NUM_BUILDMODES 5 + /proc/togglebuildmode(mob/M as mob in player_list) set name = "Toggle Build Mode" set category = "Special Verbs" @@ -35,7 +42,7 @@ M.client.screen += D H.cl = M.client -/obj/effect/bmode//Cleaning up the tree a bit +/obj/effect/bmode //Cleaning up the tree a bit density = 1 anchored = 1 layer = 20 @@ -68,7 +75,7 @@ /obj/effect/bmode/buildhelp/Click() switch(master.cl.buildmode) - if(1) + if(BASIC_BUILDMODE) usr << "\blue ***********************************************************" usr << "\blue Left Mouse Button = Construct / Upgrade" usr << "\blue Right Mouse Button = Deconstruct / Delete / Downgrade" @@ -78,7 +85,7 @@ usr << "\blue Use the button in the upper left corner to" usr << "\blue change the direction of built objects." usr << "\blue ***********************************************************" - if(2) + if(ADV_BUILDMODE) usr << "\blue ***********************************************************" usr << "\blue Right Mouse Button on buildmode button = Set object type" usr << "\blue Left Mouse Button on turf/obj = Place objects" @@ -87,17 +94,23 @@ usr << "\blue Use the button in the upper left corner to" usr << "\blue change the direction of built objects." usr << "\blue ***********************************************************" - if(3) + if(VAR_BUILDMODE) usr << "\blue ***********************************************************" usr << "\blue Right Mouse Button on buildmode button = Select var(type) & value" usr << "\blue Left Mouse Button on turf/obj/mob = Set var(type) & value" usr << "\blue Right Mouse Button on turf/obj/mob = Reset var's value" usr << "\blue ***********************************************************" - if(4) + if(THROW_BUILDMODE) usr << "\blue ***********************************************************" usr << "\blue Left Mouse Button on turf/obj/mob = Select" usr << "\blue Right Mouse Button on turf/obj/mob = Throw" usr << "\blue ***********************************************************" + if(AREA_BUILDMODE) + usr << "\blue ***********************************************************" + usr << "\blue Left Mouse Button on turf/obj/mob = Select corner" + usr << "\blue Right Mouse Button on buildmode button = Select generator" + usr << "\blue ***********************************************************" + return 1 /obj/effect/bmode/buildquit @@ -117,6 +130,13 @@ var/obj/effect/bmode/buildmode/buildmode = null var/obj/effect/bmode/buildquit/buildquit = null var/atom/movable/throw_atom = null + var/turf/cornerA = null + var/turf/cornerB = null + var/generator_path = null + +/obj/effect/bmode/buildholder/proc/Reset()//Reset temporary variables + cornerA = null + cornerB = null /obj/effect/bmode/buildmode icon_state = "buildmode1" @@ -129,25 +149,15 @@ var/list/pa = params2list(params) if(pa.Find("left")) - switch(master.cl.buildmode) - if(1) - master.cl.buildmode = 2 - src.icon_state = "buildmode2" - if(2) - master.cl.buildmode = 3 - src.icon_state = "buildmode3" - if(3) - master.cl.buildmode = 4 - src.icon_state = "buildmode4" - if(4) - master.cl.buildmode = 1 - src.icon_state = "buildmode1" + master.cl.buildmode = (master.cl.buildmode % NUM_BUILDMODES) +1 + master.Reset() + src.icon_state = "buildmode[master.cl.buildmode]" else if(pa.Find("right")) switch(master.cl.buildmode) - if(1) + if(BASIC_BUILDMODE) return 1 - if(2) + if(ADV_BUILDMODE) objholder = text2path(input(usr,"Enter typepath:" ,"Typepath","/obj/structure/closet")) if(!ispath(objholder)) objholder = /obj/structure/closet @@ -155,7 +165,7 @@ else if(ispath(objholder,/mob) && !check_rights(R_DEBUG,0)) objholder = /obj/structure/closet - if(3) + if(VAR_BUILDMODE) var/list/locked = list("vars", "key", "ckey", "client", "firemut", "ishulk", "telekinesis", "xray", "virus", "viruses", "cuffed", "ka", "last_eaten", "urine") master.buildmode.varholder = input(usr,"Enter variable name:" ,"Name", "name") @@ -174,6 +184,16 @@ master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value") as obj in world if("turf-reference") master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value") as turf in world + if(AREA_BUILDMODE) + var/list/gen_paths = typesof(/datum/mapGenerator) - /datum/mapGenerator + + var/type = input(usr,"Select Generator Type","Type") as null|anything in gen_paths + if(!type) return + + master.generator_path = type + master.cornerA = null + master.cornerB = null + return 1 @@ -186,8 +206,11 @@ if(!holder) return var/list/pa = params2list(params) + if(istype(object,/obj/effect/bmode)) + return + switch(buildmode) - if(1) + if(BASIC_BUILDMODE) if(istype(object,/turf) && pa.Find("left") && !pa.Find("alt") && !pa.Find("ctrl") ) var/turf/T = object if(istype(object,/turf/space)) @@ -233,7 +256,7 @@ var/obj/structure/window/reinforced/WIN = new/obj/structure/window/reinforced(get_turf(object)) WIN.dir = NORTHWEST log_admin("Build Mode: [key_name(usr)] built a window at ([object.x],[object.y],[object.z])") - if(2) + if(ADV_BUILDMODE) if(pa.Find("left")) if(ispath(holder.buildmode.objholder,/turf)) var/turf/T = get_turf(object) @@ -248,7 +271,7 @@ log_admin("Build Mode: [key_name(usr)] deleted [object] at ([object.x],[object.y],[object.z])") qdel(object) - if(3) + if(VAR_BUILDMODE) if(pa.Find("left")) //I cant believe this shit actually compiles. if(object.vars.Find(holder.buildmode.varholder)) log_admin("Build Mode: [key_name(usr)] modified [object.name]'s [holder.buildmode.varholder] to [holder.buildmode.valueholder]") @@ -262,7 +285,7 @@ else usr << "[initial(object.name)] does not have a var called '[holder.buildmode.varholder]'" - if(4) + if(THROW_BUILDMODE) if(pa.Find("left")) if(isturf(object)) return @@ -271,4 +294,35 @@ if(holder.throw_atom) holder.throw_atom.throw_at(object, 10, 1) log_admin("Build Mode: [key_name(usr)] threw [holder.throw_atom] at [object] ([object.x],[object.y],[object.z])") - + if(AREA_BUILDMODE) + if(!holder.cornerA) + holder.cornerA = get_turf(object) + return + if(holder.cornerA && !holder.cornerB) + holder.cornerB = get_turf(object) + + if(pa.Find("left")) //rectangular + if(holder.cornerA && holder.cornerB) + if(!holder.generator_path) + usr << "Select generator type first." + var/datum/mapGenerator/G = new holder.generator_path + G.defineRegion(holder.cornerA,holder.cornerB,1) + G.generate() + holder.cornerA = null + holder.cornerB = null + return + /* Something wrong with this, will check later + if(pa.Find("right")) // circular + if(holder.cornerA && holder.cornerB) + if(!holder.generator_path) + usr << "Select generator type first." + var/datum/mapGenerator/G = new holder.generator_path + G.defineCircularRegion(holder.cornerA,holder.cornerB,1) + G.generate() + holder.cornerA = null + holder.cornerB = null + return + */ + //Something wrong - Reset + holder.cornerA = null + holder.cornerB = null \ No newline at end of file diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index f14df6a3fc9..3125067f32b 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -142,15 +142,33 @@ var/list/VVckey_edit = list("key", "ckey") if(confirm != "Continue") return - var/list/names = sortList(L) + var/assoc = 0 + if(L.len > 0) + var/a = L[1] + if(istext(a) && L[a] != null) + assoc = 1 //This is pretty weak test but i can't think of anything else + usr << "List appears to be associative." - var/variable = input("Which var?","Var") as null|anything in names + "(ADD VAR)" + var/list/names = null + if(!assoc) + names = sortList(L) + + var/variable + var/assoc_key + if(assoc) + variable = input("Which var?","Var") as null|anything in L + "(ADD VAR)" + else + variable = input("Which var?","Var") as null|anything in names + "(ADD VAR)" if(variable == "(ADD VAR)") mod_list_add(L, O, original_name, objectvar) return - if(!variable) + if(assoc) + assoc_key = variable + variable = L[assoc_key] + + if(!assoc && !variable || assoc && !assoc_key) return var/default @@ -240,7 +258,12 @@ var/list/VVckey_edit = list("key", "ckey") if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") class = "marked datum" - var/original_var = L[L.Find(variable)] + var/original_var + if(assoc) + original_var = L[assoc_key] + else + original_var = L[L.Find(variable)] + var/new_var switch(class) //Spits a runtime error if you try to modify an entry in the contents list. Dunno how to fix it, yet. @@ -249,7 +272,10 @@ var/list/VVckey_edit = list("key", "ckey") if("restore to default") new_var = initial(variable) - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("edit referenced object") modify_variables(variable) @@ -263,35 +289,59 @@ var/list/VVckey_edit = list("key", "ckey") if("text") new_var = input("Enter new text:","Text") as text - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("num") new_var = input("Enter new number:","Num") as num - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("type") new_var = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf) - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("reference") new_var = input("Select reference:","Reference") as mob|obj|turf|area in world - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("mob reference") new_var = input("Select reference:","Reference") as mob in world - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("file") new_var = input("Pick file:","File") as file - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("icon") new_var = input("Pick icon:","Icon") as icon - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("marked datum") new_var = holder.marked_datum - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var world.log << "### ListVarEdit by [src]: [O.type] [objectvar]: [original_var]=[new_var]" log_admin("[key_name(src)] modified [original_name]'s [objectvar]: [original_var]=[new_var]") @@ -539,4 +589,4 @@ var/list/VVckey_edit = list("key", "ckey") world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.vars[variable]]")]" log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.vars[variable]]") - message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.vars[variable]]") \ No newline at end of file + message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.vars[variable]]") diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index 85fb049bd4d..5671bd85046 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -17,11 +17,21 @@ return var/image/cross = image('icons/obj/storage.dmi',"bible") - msg = "\icon[cross] PRAY: [key_name(src, 1)] (?) (PP) (VV) (SM) (JMP) (TP) (SC): [msg]" - + if(usr.job == "Chaplain") + cross = image('icons/obj/storage.dmi',"kingyellow") + msg = "\icon[cross] CHAPLAIN PRAYER: [key_name(src, 1)] (?) (PP) (VV) (SM) (JMP) (TP) (SC): [msg]" + else if(iscultist(usr)) + cross = image('icons/obj/storage.dmi',"tome") + msg = "\icon[cross] CULTIST PRAYER: [key_name(src, 1)] (?) (PP) (VV) (SM) (JMP) (TP) (SC): [msg]" + else + cross = image('icons/obj/storage.dmi',"bible") + msg = "\icon[cross] PRAYER: [key_name(src, 1)] (?) (PP) (VV) (SM) (JMP) (TP) (SC): [msg]" for(var/client/C in admins) if(C.prefs.chat_toggles & CHAT_PRAYER) C << msg + if(C.prefs.toggles & SOUND_PRAYERS) + if(usr.job == "Chaplain") + C << 'sound/effects/pray.ogg' usr << "Your prayers have been received by the gods." feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index 5d5aefac0be..1769315acab 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -21,6 +21,7 @@ attach(A2,user) name = "[A.name]-[A2.name] assembly" update_icon() + feedback_add_details("assembly_made","[name]") /obj/item/device/assembly_holder/proc/attach(var/obj/item/device/assembly/A, var/mob/user) if(!A.remove_item_from_storage(src)) diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index 3b542c43cb1..472e0912568 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -91,6 +91,18 @@ src << "You will [(prefs.chat_toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat." feedback_add_details("admin_verb","TP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/client/verb/toggleprayersounds() + set name = "Hear/Silence Prayer Sounds" + set category = "Preferences" + set desc = "Toggles hearing pray sounds." + prefs.toggles ^= SOUND_PRAYERS + prefs.save_preferences() + if(prefs.toggles & SOUND_PRAYERS) + src << "You will now hear prayer sounds." + else + src << "You will no longer prayer sounds." + feedback_add_details("admin_verb", "PSounds") + /client/verb/togglePRs() set name = "Show/Hide Pull Request Announcements" set category = "Preferences" diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index 2aecf9f789b..dd22a1e9f5c 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -19,6 +19,11 @@ desc = "Strange-looking yellow hat-wear that most certainly belongs to a powerful magic user." icon_state = "yellowwizard" +/obj/item/clothing/head/wizard/black + name = "black wizard hat" + desc = "Strange-looking black hat-wear that most certainly belongs to a real skeleton. Spooky." + icon_state = "blackwizard" + /obj/item/clothing/head/wizard/fake name = "wizard hat" desc = "It has WIZZARD written across it in sequins. Comes with a cool beard." @@ -72,6 +77,12 @@ icon_state = "yellowwizard" item_state = "yellowwizrobe" +/obj/item/clothing/suit/wizrobe/black + name = "black wizard robe" + desc = "An unnerving black gem-lined robe that reeks of death and decay." + icon_state = "blackwizard" + item_state = "blackwizrobe" + /obj/item/clothing/suit/wizrobe/marisa name = "witch robe" desc = "Magic is all about the spell power, ZE!" diff --git a/code/modules/crafting/table.dm b/code/modules/crafting/table.dm index 75847c323f4..7f6e111599a 100644 --- a/code/modules/crafting/table.dm +++ b/code/modules/crafting/table.dm @@ -78,6 +78,7 @@ /obj/structure/table/proc/construct_item(mob/user, datum/table_recipe/R) check_table() + var/send_feedback = 1 if(check_contents(R) && check_tools(user, R)) if(do_after(user, R.time)) if(!check_contents(R) || !check_tools(user, R)) @@ -86,6 +87,8 @@ if(istype(I, /obj/item/weapon/reagent_containers/food/snacks)) var/obj/item/weapon/reagent_containers/food/snacks/S = I S.create_reagents(S.volume) + feedback_add_details("food_made","[S.name]") + send_feedback = 0 var/list/parts = del_reqs(R, I) for(var/A in parts) if(istype(A, /obj/item)) @@ -98,6 +101,8 @@ I.reagents = new /datum/reagents() I.reagents.reagent_list.Add(A) I.CheckParts() + if(send_feedback) + feedback_add_details("object_crafted","[I.name]") return 1 return 0 diff --git a/code/modules/events/camerafailure.dm b/code/modules/events/camerafailure.dm new file mode 100644 index 00000000000..458b50e9a83 --- /dev/null +++ b/code/modules/events/camerafailure.dm @@ -0,0 +1,20 @@ +/datum/round_event_control/camera_failure + name = "Camera Failure" + typepath = /datum/round_event/camera_failure + weight = 100 + max_occurrences = 20 + alertadmins = 0 + +/datum/round_event/camera_failure + startWhen = 1 + endWhen = 2 + announceWhen = 0 + +/datum/round_event/camera_failure/tick() + var/iterations = 1 + var/obj/machinery/camera/C = pick(cameranet.cameras) + while(prob(round(100/iterations))) + while(!("SS13" in C.network)) + C = pick(cameranet.cameras) + C.deactivate(null, 0) + iterations *= 2.5 diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm index 3dad124aabe..078f7dab63b 100644 --- a/code/modules/events/dust.dm +++ b/code/modules/events/dust.dm @@ -1,12 +1,11 @@ /datum/round_event_control/meteor_wave/dust name = "Minor Space Dust" typepath = /datum/round_event/meteor_wave/dust - weight = 300 + weight = 200 max_occurrences = 1000 earliest_start = 0 alertadmins = 0 - /datum/round_event/meteor_wave/dust startWhen = 1 endWhen = 2 @@ -19,4 +18,4 @@ spawn_meteors(1, meteorsC) /datum/round_event/meteor_wave/dust/tick() - return \ No newline at end of file + return diff --git a/code/modules/events/event.dm b/code/modules/events/event.dm index e9661d5dc7c..07dbff7d269 100644 --- a/code/modules/events/event.dm +++ b/code/modules/events/event.dm @@ -28,6 +28,7 @@ return PROCESS_KILL var/datum/round_event/E = new typepath() E.control = src + feedback_add_details("event_ran","[E]") occurrences++ testing("[time2text(world.time, "hh:mm:ss")] [E.type]") diff --git a/code/modules/food&drinks/kitchen machinery/gibber.dm b/code/modules/food&drinks/kitchen machinery/gibber.dm index 7cf5e1d7e37..e5111bfb000 100644 --- a/code/modules/food&drinks/kitchen machinery/gibber.dm +++ b/code/modules/food&drinks/kitchen machinery/gibber.dm @@ -156,8 +156,11 @@ return use_power(1000) visible_message("You hear a loud squelchy grinding sound.") + playsound(src.loc, 'sound/machines/juicer.ogg', 50, 1) src.operating = 1 update_icon() + var/offset = prob(50) ? -2 : 2 + animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 200) //start shaking var/sourcename = src.occupant.real_name var/sourcejob if(ishuman(occupant)) @@ -207,6 +210,7 @@ if (!gibturf.density && src in viewers(gibturf)) new gibtype(gibturf,i) + pixel_x = initial(pixel_x) //return to its spot after shaking src.operating = 0 update_icon() diff --git a/code/modules/food&drinks/kitchen machinery/microwave.dm b/code/modules/food&drinks/kitchen machinery/microwave.dm index c35ffc078f6..b04ac183825 100644 --- a/code/modules/food&drinks/kitchen machinery/microwave.dm +++ b/code/modules/food&drinks/kitchen machinery/microwave.dm @@ -251,6 +251,7 @@ if(F.cooked_type) var/obj/item/weapon/reagent_containers/food/snacks/S = new F.cooked_type (get_turf(src)) F.initialize_cooked_food(S, efficiency) + feedback_add_details("food_made","[F.name]") else new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(src) if(dirty < 100) diff --git a/code/modules/food&drinks/kitchen machinery/monkeyrecycler.dm b/code/modules/food&drinks/kitchen machinery/monkeyrecycler.dm index 2e4d02b1bca..bb88e5ec867 100644 --- a/code/modules/food&drinks/kitchen machinery/monkeyrecycler.dm +++ b/code/modules/food&drinks/kitchen machinery/monkeyrecycler.dm @@ -64,8 +64,12 @@ qdel(target) user << "You stuff the monkey in the machine." playsound(src.loc, 'sound/machines/juicer.ogg', 50, 1) + var/offset = prob(50) ? -2 : 2 + animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 200) //start shaking use_power(500) src.grinded++ + sleep(50) + pixel_x = initial(pixel_x) //return to its spot after shaking user << "The machine now has [grinded] monkey\s worth of material stored." else diff --git a/code/modules/food&drinks/kitchen machinery/processor.dm b/code/modules/food&drinks/kitchen machinery/processor.dm index 5cbe9784689..78038266d98 100644 --- a/code/modules/food&drinks/kitchen machinery/processor.dm +++ b/code/modules/food&drinks/kitchen machinery/processor.dm @@ -191,6 +191,8 @@ log_admin("DEBUG: [O] in processor havent suitable recipe. How do you put it in?") //-rastaf0 // DEAR GOD THIS BURNS MY EYES HAVE YOU EVER LOOKED IN AN ENGLISH DICTONARY BEFORE IN YOUR LIFE AAAAAAAAAAAAAAAAAAAAA - Iamgoofball continue total_time += P.time + var/offset = prob(50) ? -2 : 2 + animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = (total_time / rating_speed)*5) //start shaking sleep(total_time / rating_speed) for(var/O in src.contents) var/datum/food_processor_process/P = select_recipe(O) @@ -198,6 +200,7 @@ log_admin("DEBUG: [O] in processor havent suitable recipe. How do you put it in?") //-rastaf0 continue P.process_food(src.loc, O, src) + pixel_x = initial(pixel_x) //return to its spot after shaking src.processing = 0 src.visible_message("\the [src] finishes processing.") diff --git a/code/modules/hydroponics/biogenerator.dm b/code/modules/hydroponics/biogenerator.dm index 4ba2414beb7..ba32bb2c6ff 100644 --- a/code/modules/hydroponics/biogenerator.dm +++ b/code/modules/hydroponics/biogenerator.dm @@ -159,6 +159,7 @@ dat += "Book bag: Make ([200/efficiency])
    " dat += "Plant bag: Make ([200/efficiency])
    " dat += "Mining satchel: Make ([200/efficiency])
    " + dat += "Chemistry bag: Make ([200/efficiency])
    " dat += "Botanical gloves: Make ([250/efficiency])
    " dat += "Utility belt: Make ([300/efficiency])
    " dat += "Security belt: Make ([300/efficiency])
    " @@ -270,6 +271,9 @@ if("mnbag") if (check_cost(200/efficiency)) return 0 else new/obj/item/weapon/storage/bag/ore(src.loc) + if("chbag") + if (check_cost(200/efficiency)) return 0 + else new/obj/item/weapon/storage/bag/chemistry(src.loc) if("gloves") if (check_cost(250/efficiency)) return 0 else new/obj/item/clothing/gloves/botanic_leather(src.loc) diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 82f7e40bbee..608414b38c2 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -802,7 +802,7 @@ var/t_amount = 0 var/list/result = list() var/output_loc = parent.Adjacent(user) ? user.loc : parent.loc //needed for TK - + var/product_name while(t_amount < getYield()) var/obj/item/weapon/reagent_containers/food/snacks/grown/t_prod = new product(output_loc, potency) result.Add(t_prod) // User gets a consumable @@ -815,7 +815,9 @@ t_prod.potency = potency t_prod.plant_type = plant_type t_amount++ - + product_name = t_prod.name + if(getYield() >= 1) + feedback_add_details("food_harvested","[product_name]|[getYield()]") parent.update_tray() return result diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index e9067b526dc..ddfdd96ad9a 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -439,6 +439,7 @@ var/global/list/rockTurfEdgeCache user << "You finish cutting into the rock." P.update_icon() gets_drilled(user) + feedback_add_details("pick_used_mining","[P.name]") else return attack_hand(user) return @@ -448,6 +449,7 @@ var/global/list/rockTurfEdgeCache var/i for (i=0;i 0)) stat(null, "Time left: [max(malf.AI_win_timeleft/malf.apcs, 0)]") + if(istype(ticker.mode, /datum/game_mode/gang)) + var/datum/game_mode/gang/mode = ticker.mode + if(isnum(mode.A_timer)) + stat(null, "[gang_name("A")] Gang Takeover: [max(mode.A_timer, 0)]") + if(isnum(mode.B_timer)) + stat(null, "[gang_name("B")] Gang Takeover: [max(mode.B_timer, 0)]") + /mob/dead/observer/verb/reenter_corpse() set category = "Ghost" set name = "Re-enter Corpse" diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index ab85a8f3d19..32086909dbf 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -130,6 +130,8 @@ emp_act var/obj/item/organ/limb/affecting = get_organ(ran_zone(user.zone_sel.selecting)) var/hit_area = parse_zone(affecting.name) var/target_area = parse_zone(target_limb.name) + feedback_add_details("item_used_for_combat","[I.name]|[I.force]") + feedback_add_details("zone_targeted","[def_zone]") if(dna) // allows your species to affect the attacked_by code return dna.species.spec_attacked_by(I,user,def_zone,affecting,hit_area,src.a_intent,target_limb,target_area,src) @@ -154,7 +156,6 @@ emp_act var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords) apply_damage(I.force, I.damtype, affecting, armor , I) - var/bloody = 0 if(((I.damtype == BRUTE) && I.force && prob(25 + (I.force * 2)))) if(affecting.status == ORGAN_ORGANIC) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index ecc7c49649e..8d08b29ecb2 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -136,3 +136,13 @@ return bypass // if it returns 0, it will run the usual on_mob_life for that reagent. otherwise, it will stop after running handle_chemicals for the species. else return 0 + +/mob/living/carbon/human/can_track(mob/living/user) + if(wear_id && istype(wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) + return 0 + if(istype(head, /obj/item/clothing/head)) + var/obj/item/clothing/head/hat = head + if(hat.blockTracking) + return 0 + + return ..() diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index f55238a821b..b9321879663 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -31,7 +31,7 @@ /mob/living/carbon/human/experience_pressure_difference() playsound(src, 'sound/effects/space_wind.ogg', 50, 1) - if(shoes.flags&NOSLIP) + if(shoes && shoes.flags&NOSLIP) return 0 . = ..() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 4f953dff6e9..7d29d7a3bdc 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -73,12 +73,14 @@ if (getBrainLoss() >= 60 && stat != DEAD) if (prob(3)) - switch(pick(1,2,3)) + switch(pick(1,2,3,4)) if(1) - say(pick("IM A PONY NEEEEEEIIIIIIIIIGH", "without oxigen blob don't evoluate?", "CAPTAINS A COMDOM", "[pick("", "that faggot traitor")] [pick("joerge", "george", "gorge", "gdoruge")] [pick("mellens", "melons", "mwrlins")] is grifing me HAL;P!!!", "can u give me [pick("telikesis","halk","eppilapse")]?", "THe saiyans screwed", "Bi is THE BEST OF BOTH WORLDS>", "I WANNA PET TEH monkeyS", "stop grifing me!!!!", "SOTP IT#")) + say(pick("IM A PONY NEEEEEEIIIIIIIIIGH", "without oxigen blob don't evoluate?", "CAPTAINS A COMDOM", "[pick("", "that faggot traitor")] [pick("joerge", "george", "gorge", "gdoruge")] [pick("mellens", "melons", "mwrlins")] is grifing me HAL;P!!!", "can u give me [pick("telikesis","halk","eppilapse","kamelien","eksrey","glowey skin")]?", "THe saiyans screwed", "Bi is THE BEST OF BOTH WORLDS>", "I WANNA PET TEH monkeyS", "stop grifing me!!!!", "SOTP IT#", "shiggey diggey!!", "A PIRATE APPEAR")) if(2) - say(pick("FUS RO DAH","fucking 4rries!", "stat me", ">my face", "roll it easy!", "waaaaaagh!!!", "red wonz go fasta", "FOR TEH EMPRAH", "lol2cat", "dem dwarfs man, dem dwarfs", "SPESS MAHREENS", "hwee did eet fhor khayosss", "lifelike texture ;_;", "luv can bloooom", "PACKETS!!!")) + say(pick("FUS RO DAH","fucking 4rries!", "stat me", ">my face", "roll it easy!", "waaaaaagh!!!", "red wonz go fasta", "FOR TEH EMPRAH", "lol2cat", "dem dwarfs man, dem dwarfs", "SPESS MAHREENS", "hwee did eet fhor khayosss", "lifelike texture ;_;", "luv can bloooom", "PACKETS!!!", "port ba[pick("y", "i", "e")] med!!!!", "REVIRT GON CHEM!!!!!!!!", "youed call her a toeugh bithc", "closd for merbegging", "pray can u [pick("spawn", "MAke me", "creat")] [pick("zenomorfs", "ayleins", "treaitors", "sheadow linkgs", "ubdoocters")]???")) if(3) + say(pick("GEY AWAY FROM ME U GREIFING PRICK!!!!", "ur a fuckeing autist!", ";HELP SHITECIRTY MURDERIN MEE!!!", "hwat dose tha [pick("g", "squid", "r")] mean?????", "CAL; TEH SHUTTLE!!!!!", "wearnig siNGUARLTY IS .... FIne xDDDDDDDDD", "AI laW 22 Open door", "this SI mY stATIon......", "who the HELL do u thenk u r?!!!!", "geT THE FUCK OUTTTT", "H U G B O X", ";;CRAGING THIS STTAYTION WITH NIO SURVIVROS", "[pick("bager", "syebl")] is down11!!!!!!!!!!!!!!!!!")) + if(4) emote("drool") diff --git a/code/modules/mob/living/carbon/human/whisper.dm b/code/modules/mob/living/carbon/human/whisper.dm index 23bb31ead56..fd4573900c7 100644 --- a/code/modules/mob/living/carbon/human/whisper.dm +++ b/code/modules/mob/living/carbon/human/whisper.dm @@ -10,7 +10,7 @@ return - message = trim(strip_html_properly(message)) + message = trim(html_encode(message)) if(!can_speak(message)) return diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 0f1fe82505d..855ecf423c4 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -816,3 +816,41 @@ Sorry Giacom. Please don't be mad :( /mob/living/proc/get_standard_pixel_y_offset(lying = 0) return initial(pixel_y) + +/mob/living/Stat() + ..() + if(statpanel("Status")) + if(ticker) + if(ticker.mode) + if(istype(ticker.mode, /datum/game_mode/gang)) + var/datum/game_mode/gang/mode = ticker.mode + if(isnum(mode.A_timer)) + stat(null, "[gang_name("A")] Gang Takeover: [max(mode.A_timer, 0)]") + if(isnum(mode.B_timer)) + stat(null, "[gang_name("B")] Gang Takeover: [max(mode.B_timer, 0)]") + +/mob/living/cancel_camera() + ..() + cameraFollow = null + +/mob/living/proc/can_track(mob/living/user) + //basic fast checks go first. When overriding this proc, I recommend calling ..() at the end. + var/turf/T = get_turf(src) + if(!T) + return 0 + if(T.z == ZLEVEL_CENTCOM) //dont detect mobs on centcomm + return 0 + if(T.z >= ZLEVEL_SPACEMAX) + return 0 + if(src == user) + return 0 + if(invisibility || alpha == 0)//cloaked + return 0 + if(digitalcamo) + return 0 + + // Now, are they viewable by a camera? (This is last because it's the most intensive check) + if(!near_camera(src)) + return 0 + + return 1 diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 9317991ac81..65479146645 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -35,6 +35,7 @@ var/list/ai_list = list() var/obj/item/device/pda/ai/aiPDA = null var/obj/item/device/multitool/aiMulti = null var/obj/machinery/bot/Bot + var/tracking = 0 //this is 1 if the AI is currently tracking somebody, but the track has not yet been completed. //MALFUNCTION var/datum/module_picker/malf_picker @@ -62,6 +63,13 @@ var/list/ai_list = list() var/waypoint_mode = 0 //Waypoint mode is for selecting a turf via clicking. var/apc_override = 0 //hack for letting the AI use its APC even when visionless + var/mob/camera/aiEye/eyeobj = new() + var/sprint = 10 + var/cooldown = 0 + var/acceleration = 1 + + var/obj/machinery/camera/portable/builtInCamera + /mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0) rename_self("ai", 1) name = real_name @@ -118,6 +126,13 @@ var/list/ai_list = list() job = "AI" ai_list += src shuttle_caller_list += src + + eyeobj.ai = src + eyeobj.name = "[src.name] (AI Eye)" // Give it a name + eyeobj.loc = src.loc + + builtInCamera = new /obj/machinery/camera/portable(src) + builtInCamera.network = list("SS13") ..() return @@ -125,6 +140,7 @@ var/list/ai_list = list() ai_list -= src shuttle_caller_list -= src SSshuttle.autoEvac() + qdel(eyeobj) // No AI, no Eye ..() @@ -457,7 +473,8 @@ var/list/ai_list = list() /mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C) - src.cameraFollow = null + if(!tracking) + cameraFollow = null if (!C || stat == 2) //C.can_use()) return 0 @@ -589,7 +606,7 @@ var/list/ai_list = list() set category = "AI Commands" set name = "Jump To Network" unset_machine() - src.cameraFollow = null + cameraFollow = null var/cameralist[0] if(usr.stat == 2) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 33ba6d1056f..dd38dac92d1 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -36,30 +36,8 @@ return ai.client return null - -// AI MOVEMENT - -// The AI's "eye". Described on the top of the page. - -/mob/living/silicon/ai - var/mob/camera/aiEye/eyeobj = new() - var/sprint = 10 - var/cooldown = 0 - var/acceleration = 1 - - -// Intiliaze the eye by assigning it's "ai" variable to us. Then set it's loc to us. -/mob/living/silicon/ai/New() - ..() - eyeobj.ai = src - eyeobj.name = "[src.name] (AI Eye)" // Give it a name - spawn(5) - eyeobj.loc = src.loc - -/mob/living/silicon/ai/Destroy() - eyeobj.ai = null - qdel(eyeobj) // No AI, no Eye - eyeobj = null +/mob/camera/aiEye/Destroy() + ai = null ..() /atom/proc/move_camera_by_click() @@ -92,7 +70,8 @@ else user.sprint = initial - user.cameraFollow = null + if(!user.tracking) + user.cameraFollow = null //user.unset_machine() //Uncomment this if it causes problems. //user.lightNearbyCamera() @@ -115,10 +94,7 @@ src.eyeobj.ai = src src.eyeobj.name = "[src.name] (AI Eye)" // Give it a name - if(client && client.eye) - client.eye = src - for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks) - c.remove(eyeobj) + eyeobj.setLoc(loc) /mob/living/silicon/ai/verb/toggle_acceleration() set category = "AI Commands" @@ -126,6 +102,3 @@ acceleration = !acceleration usr << "Camera acceleration has been toggled [acceleration ? "on" : "off"]." - - - diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index a324cdbbfe7..0e629e59283 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -163,9 +163,9 @@ // ok, we're alive, camera is good and in our network... - src.set_machine(src) - src:current = C - src.reset_view(C) + set_machine(src) + current = C + reset_view(C) return 1 diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 77e0040131f..c016f818fbd 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -556,13 +556,8 @@ if(user != src)//To prevent syndieborgs from emagging themselves if(!opened)//Cover is closed if(locked) - if(prob(90)) - user << "You emag the cover lock." - locked = 0 - else - user << "You fail to emag the cover lock!" - if(prob(25)) - src << "Hack attempt detected." + user << "You emag the cover lock." + locked = 0 else user << "The cover is already unlocked!" return @@ -573,42 +568,37 @@ return else sleep(6) - if(prob(50)) - SetEmagged(1) - SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown - lawupdate = 0 - connected_ai = null - user << "You emag [src]'s interface." - message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.") - log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.") - clear_supplied_laws() - clear_inherent_laws() - laws = new /datum/ai_laws/syndicate_override - var/time = time2text(world.realtime,"hh:mm:ss") - lawchanges.Add("[time] : [user.name]([user.key]) emagged [name]([key])") - set_zeroth_law("Only [user.real_name] and people they designate as being such are Syndicate Agents.") - src << "ALERT: Foreign software detected." - sleep(5) - src << "Initiating diagnostics..." - sleep(20) - src << "SynBorg v1.7 loaded." - sleep(5) - src << "LAW SYNCHRONISATION ERROR" - sleep(5) - src << "Would you like to send a report to NanoTraSoft? Y/N" - sleep(10) - src << "> N" - sleep(20) - src << "ERRORERRORERROR" - src << "Obey these laws:" - laws.show_laws(src) - src << "ALERT: [user.real_name] is your new master. Obey your new laws and their commands." - SetLockdown(0) - update_icons() - else - user << "You fail to [ locked ? "unlock" : "lock"] [src]'s interface!" - if(prob(25)) - src << "ALERT: Hack attempt detected." + SetEmagged(1) + SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown + lawupdate = 0 + connected_ai = null + user << "You emag [src]'s interface." + message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.") + log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.") + clear_supplied_laws() + clear_inherent_laws() + laws = new /datum/ai_laws/syndicate_override + var/time = time2text(world.realtime,"hh:mm:ss") + lawchanges.Add("[time] : [user.name]([user.key]) emagged [name]([key])") + set_zeroth_law("Only [user.real_name] and people they designate as being such are Syndicate Agents.") + src << "ALERT: Foreign software detected." + sleep(5) + src << "Initiating diagnostics..." + sleep(20) + src << "SynBorg v1.7 loaded." + sleep(5) + src << "LAW SYNCHRONISATION ERROR" + sleep(5) + src << "Would you like to send a report to NanoTraSoft? Y/N" + sleep(10) + src << "> N" + sleep(20) + src << "ERRORERRORERROR" + src << "Obey these laws:" + laws.show_laws(src) + src << "ALERT: [user.real_name] is your new master. Obey your new laws and their commands." + SetLockdown(0) + update_icons() /mob/living/silicon/robot/verb/unlock_own_cover() set category = "Robot Commands" diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index 066d484506d..ab816782d26 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -155,6 +155,8 @@ var/T = src.loc + if(!stat) + return 0 if(busy != SPINNING_WEB) busy = SPINNING_WEB src.visible_message("\the [src] begins to secrete a sticky substance.") @@ -171,6 +173,8 @@ set category = "Spider" set desc = "Wrap up prey to feast upon and objects for safe keeping." + if(!stat) + return 0 if(!cocoon_target) var/list/choices = list() for(var/mob/living/L in view(1,src)) @@ -228,6 +232,8 @@ set desc = "Lay a clutch of eggs, but you must wrap a creature for feeding first." var/obj/effect/spider/eggcluster/E = locate() in get_turf(src) + if(!stat) + return 0 if(E) src << "There is already a cluster of eggs here!" else if(!fed) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm index 9e0296844b0..b4616ae9fb7 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm @@ -41,6 +41,10 @@ return ..() +/mob/living/simple_animal/hostile/asteroid/death(gibbed) + feedback_add_details("mobs_killed_mining","[src.name]") + ..(gibbed) + /mob/living/simple_animal/hostile/asteroid/basilisk name = "basilisk" desc = "A territorial beast, covered in a thick shell that absorbs energy. Its stare causes victims to freeze from the inside." @@ -110,6 +114,7 @@ D.layer = 4.1 ..(gibbed) + /mob/living/simple_animal/hostile/asteroid/goldgrub name = "goldgrub" desc = "A worm that grows fat from eating everything in its sight. Seems to enjoy precious metals and other shiny things, hence the name." diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index e116423eff3..7aea2933083 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -623,9 +623,6 @@ var/list/slot_equipment_priority = list( \ set category = "OOC" reset_view(null) unset_machine() - if(istype(src, /mob/living)) - if(src:cameraFollow) - src:cameraFollow = null /mob/Topic(href, href_list) if(href_list["mach_close"]) @@ -720,6 +717,7 @@ var/list/slot_equipment_priority = list( \ if(master_controller) stat("MasterController:","[round(master_controller.cost,0.001)]ds (Interval:[master_controller.processing_interval] | Iteration:[master_controller.iteration])") + stat("Subsystem cost per second:","[round(master_controller.SSCostPerSecond,0.001)]ds") for(var/datum/subsystem/SS in master_controller.subsystems) if(SS.can_fire) SS.stat_entry() diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 08b04e3afff..3c1906ee7dc 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -182,7 +182,7 @@ return 0 /proc/stars(n, pr) - n = strip_html_properly(n) + n = html_encode(n) if (pr == null) pr = 25 if (pr <= 0) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 96c8a2ba049..67a15e73030 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -453,7 +453,9 @@ By design, d1 is the smallest direction and d2 is the highest // Definitions //////////////////////////////// - +var/global/list/datum/stack_recipe/cable_coil_recipes = list ( \ + new/datum/stack_recipe("cable restraints", /obj/item/weapon/restraints/handcuffs/cable, 15), \ + ) /obj/item/stack/cable_coil name = "cable coil" @@ -501,6 +503,7 @@ By design, d1 is the smallest direction and d2 is the highest pixel_x = rand(-2,2) pixel_y = rand(-2,2) update_icon() + recipes = cable_coil_recipes /////////////////////////////////// // General procedures @@ -533,38 +536,12 @@ By design, d1 is the smallest direction and d2 is the highest icon_state = "coil_[item_color]" name = "cable coil" -/obj/item/stack/cable_coil/verb/make_restraint() - set name = "Make Cable Restraints" - set category = "Object" - var/mob/M = usr - - if(ishuman(M) && !M.restrained() && !M.stat && M.canmove) - if(!istype(usr.loc,/turf)) - return - if(src.amount <= 14) - usr << "You need at least 15 lengths to make restraints!" - return - var/obj/item/weapon/restraints/handcuffs/cable/B = new /obj/item/weapon/restraints/handcuffs/cable(usr.loc) - B.icon_state = "cuff_[item_color]" - usr << "You wind some cable together to make some restraints." - src.use(15) - else - usr << "You cannot do that!" - ..() // Items usable on a cable coil : -// - Wirecutters : cut them duh ! // - Cable coil : merge cables /obj/item/stack/cable_coil/attackby(obj/item/weapon/W, mob/user, params) ..() - if( istype(W, /obj/item/weapon/wirecutters) && src.amount > 1) - src.amount-- - new /obj/item/stack/cable_coil(user.loc, 1,item_color) - user << "You cut a piece off the cable coil." - src.update_icon() - return - - else if(istype(W, /obj/item/stack/cable_coil/cyborg)) + if(istype(W, /obj/item/stack/cable_coil/cyborg)) var/obj/item/stack/cable_coil/cyborg/C = W var/to_transfer = min(src.amount, round((C.source.max_energy - C.source.energy) / C.cost)) C.add(to_transfer) @@ -588,22 +565,6 @@ By design, d1 is the smallest direction and d2 is the highest src.use(amt) return -//remove cables from the stack -/* This is probably reduntant -/obj/item/stack/cable_coil/use(var/used) - if(src.amount < used) - return 0 - else if (src.amount == used) - if(ismob(loc)) //handle mob icon update - var/mob/M = loc - M.unEquip(src) - qdel(src) - return 1 - else - amount -= used - update_icon() - return 1 -*/ /obj/item/stack/cable_coil/use(var/used) . = ..() update_icon() diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 849c404c9fd..d90d7280cd2 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -43,6 +43,8 @@ return 0 if(charge < amount) return 0 charge = (charge - amount) + if(!istype(loc, /obj/machinery/power/apc)) + feedback_add_details("cell_used","[src.name]") return 1 // recharge the cell diff --git a/code/modules/procedural mapping/mapGeneratorModules/helpers.dm b/code/modules/procedural mapping/mapGeneratorModules/helpers.dm new file mode 100644 index 00000000000..bad449a9e8f --- /dev/null +++ b/code/modules/procedural mapping/mapGeneratorModules/helpers.dm @@ -0,0 +1,44 @@ +//Helper Modules + + +// Helper to repressurize the area in case it was run in space +/datum/mapGeneratorModule/bottomLayer/repressurize + spawnableAtoms = list() + spawnableTurfs = list() + +/datum/mapGeneratorModule/bottomLayer/repressurize/generate() + if(!mother) + return + var/list/map = mother.map + for(var/turf/simulated/T in map) + SSair.remove_from_active(T) + for(var/turf/simulated/T in map) + if(T.air) + T.air.oxygen = T.oxygen + T.air.nitrogen = T.nitrogen + T.air.carbon_dioxide = T.carbon_dioxide + T.air.toxins = T.toxins + T.air.temperature = T.temperature + SSair.add_to_active(T) + +//Only places atoms/turfs on area borders +/datum/mapGeneratorModule/border + clusterCheckFlags = CLUSTER_CHECK_NONE + +/datum/mapGeneratorModule/border/generate() + if(!mother) + return + var/list/map = mother.map + for(var/turf/T in map) + if(is_border(T)) + place(T) + +/datum/mapGeneratorModule/border/proc/is_border(var/turf/T) + for(var/direction in list(SOUTH,EAST,WEST,NORTH)) + if (get_step(T,direction) in mother.map) + continue + return 1 + return 0 + +/datum/mapGenerator/repressurize + modules = list(/datum/mapGeneratorModule/bottomLayer/repressurize) \ No newline at end of file diff --git a/code/modules/procedural mapping/mapGenerators/asteroid.dm b/code/modules/procedural mapping/mapGenerators/asteroid.dm new file mode 100644 index 00000000000..4dc002aa56a --- /dev/null +++ b/code/modules/procedural mapping/mapGenerators/asteroid.dm @@ -0,0 +1,45 @@ +//Asteroid turfs +/datum/mapGeneratorModule/bottomLayer/asteroidTurfs + spawnableTurfs = list(/turf/simulated/floor/plating/asteroid = 100) + +/datum/mapGeneratorModule/bottomLayer/asteroidWalls + spawnableTurfs = list(/turf/simulated/mineral = 100) + +//Border walls +/datum/mapGeneratorModule/border/asteroidWalls + spawnableAtoms = list() + spawnableTurfs = list(/turf/simulated/mineral = 100) + +//Random walls +/datum/mapGeneratorModule/splatterLayer/asteroidWalls + clusterCheckFlags = CLUSTER_CHECK_NONE + spawnableAtoms = list() + spawnableTurfs = list(/turf/simulated/mineral = 30) + +//Monsters +/datum/mapGeneratorModule/splatterLayer/asteroidMonsters + spawnableTurfs = list() + spawnableAtoms = list(/mob/living/simple_animal/hostile/asteroid/basilisk = 10, \ + /mob/living/simple_animal/hostile/asteroid/hivelord = 10, \ + /mob/living/simple_animal/hostile/asteroid/goliath = 10) + + +// GENERATORS + +/datum/mapGenerator/asteroid/hollow + modules = list(/datum/mapGeneratorModule/bottomLayer/asteroidTurfs, \ + /datum/mapGeneratorModule/border/asteroidWalls) + +/datum/mapGenerator/asteroid/hollow/random + modules = list(/datum/mapGeneratorModule/bottomLayer/asteroidTurfs, \ + /datum/mapGeneratorModule/border/asteroidWalls, \ + /datum/mapGeneratorModule/splatterLayer/asteroidWalls) + +/datum/mapGenerator/asteroid/hollow/random/monsters + modules = list(/datum/mapGeneratorModule/bottomLayer/asteroidTurfs, \ + /datum/mapGeneratorModule/border/asteroidWalls, \ + /datum/mapGeneratorModule/splatterLayer/asteroidWalls, \ + /datum/mapGeneratorModule/splatterLayer/asteroidMonsters) + +/datum/mapGenerator/asteroid/filled + modules = list(/datum/mapGeneratorModule/bottomLayer/asteroidWalls) \ No newline at end of file diff --git a/code/modules/procedural mapping/mapGenerators/shuttle.dm b/code/modules/procedural mapping/mapGenerators/shuttle.dm new file mode 100644 index 00000000000..7197b127d48 --- /dev/null +++ b/code/modules/procedural mapping/mapGenerators/shuttle.dm @@ -0,0 +1,15 @@ +/datum/mapGeneratorModule/bottomLayer/shuttleFloor + spawnableTurfs = list(/turf/simulated/floor/plasteel/shuttle = 100) + +/datum/mapGeneratorModule/border/shuttleWalls + spawnableAtoms = list() + spawnableTurfs = list(/turf/simulated/wall/shuttle = 100) +// Generators + +/datum/mapGenerator/shuttle/full + modules = list(/datum/mapGeneratorModule/bottomLayer/shuttleFloor, \ + /datum/mapGeneratorModule/border/shuttleWalls,\ + /datum/mapGeneratorModule/bottomLayer/repressurize) + +/datum/mapGenerator/shuttle/floor + modules = list(/datum/mapGeneratorModule/bottomLayer/shuttleFloor) diff --git a/code/modules/procedural mapping/mapGenerators/syndicate.dm b/code/modules/procedural mapping/mapGenerators/syndicate.dm new file mode 100644 index 00000000000..e48fe718d00 --- /dev/null +++ b/code/modules/procedural mapping/mapGenerators/syndicate.dm @@ -0,0 +1,52 @@ +// Modules + +/turf/simulated/floor/plasteel/shuttle/red/syndicate + name = "floor" //Not Brig Floor + +/datum/mapGeneratorModule/bottomLayer/syndieFloor + spawnableTurfs = list(/turf/simulated/floor/plasteel/shuttle/red/syndicate = 100) + +/datum/mapGeneratorModule/border/syndieWalls + spawnableAtoms = list() + spawnableTurfs = list(/turf/simulated/wall/r_wall = 100) + + +/datum/mapGeneratorModule/syndieFurniture + clusterCheckFlags = CLUSTER_CHECK_ALL + spawnableTurfs = list() + spawnableAtoms = list(/obj/structure/table = 20,/obj/structure/stool/bed/chair = 15,/obj/structure/stool = 10, \ + /obj/structure/computerframe = 15, /obj/item/weapon/storage/toolbox/syndicate = 15 ,\ + /obj/structure/closet/syndicate = 25, /obj/machinery/suit_storage_unit/syndicate = 15) + +/datum/mapGeneratorModule/splatterLayer/syndieMobs + spawnableAtoms = list(/mob/living/simple_animal/hostile/syndicate = 30, \ + /mob/living/simple_animal/hostile/syndicate/melee = 20, \ + /mob/living/simple_animal/hostile/syndicate/ranged = 20, \ + /mob/living/simple_animal/hostile/viscerator = 30) + spawnableTurfs = list() + +// Generators + +/datum/mapGenerator/syndicate/empty //walls and floor only + modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \ + /datum/mapGeneratorModule/border/syndieWalls,\ + /datum/mapGeneratorModule/bottomLayer/repressurize) + +/datum/mapGenerator/syndicate/mobsonly + modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \ + /datum/mapGeneratorModule/border/syndieWalls,\ + /datum/mapGeneratorModule/splatterLayer/syndieMobs, \ + /datum/mapGeneratorModule/bottomLayer/repressurize) + +/datum/mapGenerator/syndicate/furniture + modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \ + /datum/mapGeneratorModule/border/syndieWalls,\ + /datum/mapGeneratorModule/syndieFurniture, \ + /datum/mapGeneratorModule/bottomLayer/repressurize) + +/datum/mapGenerator/syndicate/full + modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \ + /datum/mapGeneratorModule/border/syndieWalls,\ + /datum/mapGeneratorModule/syndieFurniture, \ + /datum/mapGeneratorModule/splatterLayer/syndieMobs, \ + /datum/mapGeneratorModule/bottomLayer/repressurize) \ No newline at end of file diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 4cc38cb4fc2..9b1666fd2f0 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -132,6 +132,7 @@ process_fire(target,user,1,params) + /obj/item/weapon/gun/proc/can_trigger_gun(mob/living/carbon/user) if (!user.IsAdvancedToolUser()) user << "You don't have the dexterity to do this!" @@ -218,7 +219,7 @@ user.update_inv_l_hand(0) else user.update_inv_r_hand(0) - + feedback_add_details("gun_fired","[src.name]") /obj/item/weapon/gun/attack(mob/M as mob, mob/user) if(user.a_intent == "harm") //Flogging diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index fdec6f437b9..8a6ffca294b 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -230,10 +230,11 @@ return /obj/item/weapon/gun/projectile/automatic/tommygun - name = "tommy gun" + name = "thompson SMG" desc = "A genuine 'Chicago Typewriter'." icon_state = "tommygun" item_state = "shotgun" + w_class = 5 slot_flags = 0 origin_tech = "combat=5;materials=1;syndicate=2" mag_type = /obj/item/ammo_box/magazine/tommygunm45 diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index 92235739bdb..3dab9a3442a 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -192,7 +192,8 @@ dispensable_reagents = list() var/list/special_reagents = list(list("hydrogen", "oxygen", "silicon", "phosphorus", "sulfur", "carbon", "nitrogen", "water"), list("lithium", "sugar", "sacid", "copper", "mercury", "sodium","iodine","bromine"), - list("ethanol", "chlorine", "potassium", "aluminium", "radium", "fluorine", "iron", "welding_fuel","silver","stable_plasma")) + list("ethanol", "chlorine", "potassium", "aluminium", "radium", "fluorine", "iron", "welding_fuel","silver","stable_plasma"), + list("oil", "ash", "acetone", "saltpetre", "ammonia", "diethylamine")) /obj/machinery/chem_dispenser/constructable/New() ..() @@ -1244,9 +1245,12 @@ if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)) return playsound(src.loc, 'sound/machines/juicer.ogg', 20, 1) + var/offset = prob(50) ? -2 : 2 + animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 250) //start shaking operating = 1 updateUsrDialog() spawn(50) + pixel_x = initial(pixel_x) //return to its spot after shaking operating = 0 updateUsrDialog() @@ -1279,9 +1283,12 @@ if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)) return playsound(src.loc, 'sound/machines/blender.ogg', 50, 1) + var/offset = prob(50) ? -2 : 2 + animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 250) //start shaking operating = 1 updateUsrDialog() spawn(60) + pixel_x = initial(pixel_x) //return to its spot after shaking operating = 0 updateUsrDialog() diff --git a/code/modules/research/message_server.dm b/code/modules/research/message_server.dm index b4b25eb9e42..2df53886ab3 100644 --- a/code/modules/research/message_server.dm +++ b/code/modules/research/message_server.dm @@ -177,6 +177,7 @@ var/global/list/obj/machinery/message_server/message_servers = list() /datum/feedback_variable/proc/add_details(var/text) if (istext(text)) + text = replacetext(text, " ", "_") if (!details) details = text else diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index d076c813158..1bc794782c6 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -276,6 +276,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(linked_lathe) //Also sends salvaged materials to a linked protolathe, if any. linked_lathe.m_amount += min((linked_lathe.max_material_storage - linked_lathe.TotalMaterials()), (linked_destroy.loaded_item.m_amt*(linked_destroy.decon_mod/10))) linked_lathe.g_amount += min((linked_lathe.max_material_storage - linked_lathe.TotalMaterials()), (linked_destroy.loaded_item.g_amt*(linked_destroy.decon_mod/10))) + feedback_add_details("item_deconstructed","[linked_destroy.loaded_item.name]") linked_destroy.loaded_item = null else screen = 1.0 @@ -406,6 +407,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, var/R = being_built.reliability spawn(32*amount/coeff) if(g2g) //And if we only fail the material requirements, we still spend time and power + var/already_logged = 0 for(var/i = 0, iYou drape [I] over [M]'s [parse_zone(procedure.location)] to prepare for \an [procedure.name].") add_logs(user, M, "operated", addition="Operation type: [procedure.name]") + feedback_add_details("surgery_initiated","[procedure.name]") return 1 else user << "You need to expose [M]'s [procedure.location] first!" diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index 042832894d7..76365b0790c 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -73,6 +73,7 @@ /datum/surgery_step/proc/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) user.visible_message("[user] succeeds!", "You succeed.") + feedback_add_details("surgery_step_success","[src.type]") return 1 /datum/surgery_step/saw/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) @@ -80,10 +81,12 @@ var/mob/living/carbon/human/H = target H.apply_damage(75,"brute","[target_zone]") user.visible_message("[user] saws [target]'s [parse_zone(target_zone)] open!", "You saw [target]'s [parse_zone(target_zone)] open.") + feedback_add_details("surgery_step_success","[src.type]") return 1 /datum/surgery_step/proc/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) user.visible_message("[user] screws up!", "You screw up!") + feedback_add_details("surgery_step_failed","[src.type]") return 0 /datum/surgery_step/close/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) diff --git a/code/orphaned procs/priority_announce.dm b/code/orphaned procs/priority_announce.dm index e085fa783ca..3630b9d58df 100644 --- a/code/orphaned procs/priority_announce.dm +++ b/code/orphaned procs/priority_announce.dm @@ -6,7 +6,8 @@ if(type == "Priority") announcement += "

    Priority Announcement

    " - + if (title && length(title) > 0) + announcement += "

    [html_encode(title)]

    " else if(type == "Captain") announcement += "

    Captain Announces

    " news_network.SubmitArticle(text, "Captain's Announcement", "Station Announcements", null) diff --git a/config/game_options.txt b/config/game_options.txt index cc2a9c13d1d..ed44c926e10 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -276,3 +276,7 @@ MIDROUND_ANTAG_LIFE_CHECK 0.7 #NO_SUMMON_MAGIC #NO_SUMMON_EVENTS +//Comment for "normal" explosions, which ignore obstacles +//Uncomment for explosions that react to doors and walls +REACTIONARY_EXPLOSIONS + diff --git a/html/changelog.html b/html/changelog.html index fdf8f21ed83..69c3bf7818a 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,46 @@ -->
    +

    12 June 2015

    +

    Ikarrus updated:

    +
      +
    • Gang Updates
    • +
    • New objective: To win, Gangs must now buy a Dominator machine (50 influence) and defend it for a varying time frame.
      * The location of the dominator is broadcasted to the entire station the moment it is activated
      * The more territories the gang controls, the less time it will take
      * Gangs no longer win by capturing territories
    • +
    • A choice of gang outfits are now purchasable for 1 influence each
    • +
    • Thompson SMGs aka "tommy guns" are now purchasable for 50 influence
    • +
    • Bulletproof armor vests are now purchasable for 10 influence
    • +
    • Gang messages are now free to send
    • +
    • Prices of pistols and pens reduced to 20 and 30, respectively
    • +
    • Gang spraycans have been made a lot less obvious. They look nearly identical to regular ones, now.
    • +
    • Gangs will no longer be notified how much territory the enemy controls
    • +
    +

    Incoming5643 updated:

    +
      +
    • Growing tired of reports of slain members, the Wizard Federation has cautiously sactioned the dark path of lichdom. Beware of the powerful lich who hides his phylactery well, for he is immortal!
    • +
    • The trick to defeating liches is to destroy either their body or their phylactery item before they can ressurect to it. The more a lich is slain the longer it will take him to make use of his phylactery and the more likely the crew is to catch him during a vunerable moment.
    • +
    • Due to the addition of proper liching, skeletons as a choosable race from magic mirrors has been discontinued. My apologies to the powergamers. A special admin version of the mirror that allows for skeletons has also been added to the code.
    • +
    +

    Miauw updated:

    +
      +
    • AIs have received several minor nerfs in order to increase antagonist counterplay:
    • +
    • AI tracking is no longer instant, it takes an amount of time that increases with distance from the AI eye, up to 4 seconds. The AI detector item will light up when an AI begins tracking.
    • +
    • A random camera failure event has been added, which will break one or two random cameras.
    • +
    • You can no longer keep tracking people that are outside of your camera vision.
    • +
    • Camera wires have been removed. Screwdriver a camera to open the panel, then use wirecutters to disable it or a multitool to change the focus.
    • +
    • You can now hit cameras with items to break them. To repair a camera, simply open the panel and use wirecutters on it.
    • +
    • Camera alerts now only happen after a camera is reactivated.
    • +
    +

    RemieRichards updated:

    +
      +
    • New optional explosion effect ported from /vg/'s DeityLink, Explosions that are affected by Walls and Doors
    • +
    + +

    11 June 2015

    +

    Cheridan updated:

    +
      +
    • Removes the powerdrain for individiual active modules on cyborgs.
    • +
    +

    09 June 2015

    Aranclanos updated:

      diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 07bf534836e..e7f6df25d6e 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -2702,3 +2702,52 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - tweak: 'Biogenerator: Matter Bins increase storage.' bananacreampie: - rscadd: Added several new options to the ghostform sprites +2015-06-11: + Cheridan: + - rscdel: Removes the powerdrain for individiual active modules on cyborgs. +2015-06-12: + Ikarrus: + - experiment: Gang Updates + - rscadd: 'New objective: To win, Gangs must now buy a Dominator machine (50 influence) + and defend it for a varying time frame.
      * The location of the dominator is + broadcasted to the entire station the moment it is activated
      * The more territories + the gang controls, the less time it will take
      * Gangs no longer win by capturing + territories' + - rscadd: A choice of gang outfits are now purchasable for 1 influence each + - rscadd: Thompson SMGs aka "tommy guns" are now purchasable for 50 influence + - rscadd: Bulletproof armor vests are now purchasable for 10 influence + - tweak: Gang messages are now free to send + - tweak: Prices of pistols and pens reduced to 20 and 30, respectively + - tweak: Gang spraycans have been made a lot less obvious. They look nearly identical + to regular ones, now. + - rscdel: Gangs will no longer be notified how much territory the enemy controls + Incoming5643: + - rscadd: Growing tired of reports of slain members, the Wizard Federation has cautiously + sactioned the dark path of lichdom. Beware of the powerful lich who hides his + phylactery well, for he is immortal! + - rscadd: The trick to defeating liches is to destroy either their body or their + phylactery item before they can ressurect to it. The more a lich is slain the + longer it will take him to make use of his phylactery and the more likely the + crew is to catch him during a vunerable moment. + - rscremove: Due to the addition of proper liching, skeletons as a choosable race + from magic mirrors has been discontinued. My apologies to the powergamers. A + special admin version of the mirror that allows for skeletons has also been + added to the code. + Miauw: + - tweak: 'AIs have received several minor nerfs in order to increase antagonist + counterplay:' + - tweak: AI tracking is no longer instant, it takes an amount of time that increases + with distance from the AI eye, up to 4 seconds. The AI detector item will light + up when an AI begins tracking. + - tweak: A random camera failure event has been added, which will break one or two + random cameras. + - tweak: You can no longer keep tracking people that are outside of your camera + vision. + - tweak: Camera wires have been removed. Screwdriver a camera to open the panel, + then use wirecutters to disable it or a multitool to change the focus. + - tweak: You can now hit cameras with items to break them. To repair a camera, simply + open the panel and use wirecutters on it. + - tweak: Camera alerts now only happen after a camera is reactivated. + RemieRichards: + - rscadd: New optional explosion effect ported from /vg/'s DeityLink, Explosions + that are affected by Walls and Doors diff --git a/html/changelogs/CHERIDAN-PR-9820.yml b/html/changelogs/CHERIDAN-PR-9820.yml deleted file mode 100644 index c2aaaf0e2ba..00000000000 --- a/html/changelogs/CHERIDAN-PR-9820.yml +++ /dev/null @@ -1,36 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# spellcheck (typo fixes) -# experiment -# tgs (TG-ported fixes?) -################################# - -# Your name. -author: Cheridan - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit. -# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog. -changes: - - rscdel: "Removes the powerdrain for individiual active modules on cyborgs." diff --git a/icons/misc/buildmode.dmi b/icons/misc/buildmode.dmi index a885e76d549..089427111f2 100644 Binary files a/icons/misc/buildmode.dmi and b/icons/misc/buildmode.dmi differ diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi index bc98f542874..4ced7caebed 100644 Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 522826b5530..934435bd835 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index dd1f96dcbfe..6572955ff2b 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi index 9c5ddae42c1..42e1b95b2c0 100644 Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index f4d22e41ee2..59ac6436d18 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index b56aa44170d..deca94b24fa 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/crayons.dmi b/icons/obj/crayons.dmi index a3966103053..7d3489285c3 100644 Binary files a/icons/obj/crayons.dmi and b/icons/obj/crayons.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 473e51f6964..5a3e80c66f7 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/machines/dominator.dmi b/icons/obj/machines/dominator.dmi new file mode 100644 index 00000000000..7671dedff86 Binary files /dev/null and b/icons/obj/machines/dominator.dmi differ diff --git a/sound/arcade/Boom.ogg b/sound/arcade/Boom.ogg new file mode 100644 index 00000000000..8adfb2bc430 Binary files /dev/null and b/sound/arcade/Boom.ogg differ diff --git a/sound/arcade/Heal.ogg b/sound/arcade/Heal.ogg new file mode 100644 index 00000000000..26f47195c65 Binary files /dev/null and b/sound/arcade/Heal.ogg differ diff --git a/sound/arcade/Hit.ogg b/sound/arcade/Hit.ogg new file mode 100644 index 00000000000..0bf18679a65 Binary files /dev/null and b/sound/arcade/Hit.ogg differ diff --git a/sound/arcade/Lose.ogg b/sound/arcade/Lose.ogg new file mode 100644 index 00000000000..dd2145737cd Binary files /dev/null and b/sound/arcade/Lose.ogg differ diff --git a/sound/arcade/Mana.ogg b/sound/arcade/Mana.ogg new file mode 100644 index 00000000000..7f26ae53fe7 Binary files /dev/null and b/sound/arcade/Mana.ogg differ diff --git a/sound/arcade/Steal.ogg b/sound/arcade/Steal.ogg new file mode 100644 index 00000000000..9c7b3be2a5a Binary files /dev/null and b/sound/arcade/Steal.ogg differ diff --git a/sound/arcade/Win.ogg b/sound/arcade/Win.ogg new file mode 100644 index 00000000000..27fb9725f20 Binary files /dev/null and b/sound/arcade/Win.ogg differ diff --git a/sound/effects/pray.ogg b/sound/effects/pray.ogg new file mode 100644 index 00000000000..beadd3916f1 Binary files /dev/null and b/sound/effects/pray.ogg differ diff --git a/sound/effects/pray_chaplain.ogg b/sound/effects/pray_chaplain.ogg new file mode 100644 index 00000000000..1b543275311 Binary files /dev/null and b/sound/effects/pray_chaplain.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 42c59cb7caa..e448e1b78bd 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -227,6 +227,7 @@ #include "code\datums\spells\genetic.dm" #include "code\datums\spells\inflict_handler.dm" #include "code\datums\spells\knock.dm" +#include "code\datums\spells\lichdom.dm" #include "code\datums\spells\lightning.dm" #include "code\datums\spells\mime.dm" #include "code\datums\spells\mind_transfer.dm" @@ -240,7 +241,6 @@ #include "code\datums\wires\alarm.dm" #include "code\datums\wires\apc.dm" #include "code\datums\wires\autolathe.dm" -#include "code\datums\wires\camera.dm" #include "code\datums\wires\explosive.dm" #include "code\datums\wires\mulebot.dm" #include "code\datums\wires\particle_accelerator.dm" @@ -326,7 +326,9 @@ #include "code\game\gamemodes\cult\runes.dm" #include "code\game\gamemodes\cult\talisman.dm" #include "code\game\gamemodes\extended\extended.dm" +#include "code\game\gamemodes\gang\dominator.dm" #include "code\game\gamemodes\gang\gang.dm" +#include "code\game\gamemodes\gang\recaller.dm" #include "code\game\gamemodes\malfunction\Malf_Modules.dm" #include "code\game\gamemodes\malfunction\malfunction.dm" #include "code\game\gamemodes\meteor\meteor.dm" @@ -579,7 +581,6 @@ #include "code\game\objects\items\devices\pipe_painter.dm" #include "code\game\objects\items\devices\pizza_bomb.dm" #include "code\game\objects\items\devices\powersink.dm" -#include "code\game\objects\items\devices\recaller.dm" #include "code\game\objects\items\devices\scanners.dm" #include "code\game\objects\items\devices\sensor_device.dm" #include "code\game\objects\items\devices\taperecorder.dm" @@ -931,6 +932,7 @@ #include "code\modules\events\anomaly_vortex.dm" #include "code\modules\events\blob.dm" #include "code\modules\events\brand_intelligence.dm" +#include "code\modules\events\camerafailure.dm" #include "code\modules\events\carp_migration.dm" #include "code\modules\events\communications_blackout.dm" #include "code\modules\events\disease_outbreak.dm" @@ -1332,8 +1334,12 @@ #include "code\modules\procedural mapping\mapGenerator.dm" #include "code\modules\procedural mapping\mapGeneratorModule.dm" #include "code\modules\procedural mapping\mapGeneratorReadme.dm" +#include "code\modules\procedural mapping\mapGeneratorModules\helpers.dm" #include "code\modules\procedural mapping\mapGeneratorModules\nature.dm" +#include "code\modules\procedural mapping\mapGenerators\asteroid.dm" #include "code\modules\procedural mapping\mapGenerators\nature.dm" +#include "code\modules\procedural mapping\mapGenerators\shuttle.dm" +#include "code\modules\procedural mapping\mapGenerators\syndicate.dm" #include "code\modules\projectiles\ammunition.dm" #include "code\modules\projectiles\firing.dm" #include "code\modules\projectiles\gun.dm" diff --git a/tools/dmifonts/DmiFonts.exe b/tools/dmifonts/DmiFonts.exe new file mode 100644 index 00000000000..ce1d694147a Binary files /dev/null and b/tools/dmifonts/DmiFonts.exe differ diff --git a/tools/dmifonts/DmiFonts.int b/tools/dmifonts/DmiFonts.int new file mode 100644 index 00000000000..b82874fded5 --- /dev/null +++ b/tools/dmifonts/DmiFonts.int @@ -0,0 +1,6 @@ +// BEGIN_INTERNALS +/* +MAP_ICON_TYPE: 0 +AUTO_FILE_DIR: OFF +*/ +// END_INTERNALS diff --git a/tools/dmifonts/DmiFonts.lk b/tools/dmifonts/DmiFonts.lk new file mode 100644 index 00000000000..e69de29bb2d