diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm index a2e0660a8bc..c4747776f39 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm @@ -257,6 +257,13 @@ "G" = ( /turf/closed/wall/mineral/titanium, /area/ruin/powered/golem_ship) +"H" = ( +/obj/machinery/door/airlock/shuttle, +/obj/structure/fans/tiny, +/turf/open/floor/mineral/titanium/purple{ + baseturf = /turf/open/floor/plating/lava/smooth + }, +/area/ruin/powered/golem_ship) (1,1,1) = {" a @@ -686,8 +693,8 @@ b i i b -j -j +H +H b i i diff --git a/_maps/map_files/BirdStation/BirdStation.dmm b/_maps/map_files/BirdStation/BirdStation.dmm index 034c1ede772..ba0be3682f0 100644 --- a/_maps/map_files/BirdStation/BirdStation.dmm +++ b/_maps/map_files/BirdStation/BirdStation.dmm @@ -1599,7 +1599,7 @@ "aeh" = ( /turf/open/floor/engine{ name = "high pressure o2 floor"; - initial_gas_mix = "o2=500000" + initial_gas_mix = "o2=500000;TEMP=293.15" }, /area/engine/engineering) "aei" = ( @@ -1608,7 +1608,7 @@ }, /turf/open/floor/engine{ name = "high pressure o2 floor"; - initial_gas_mix = "o2=500000" + initial_gas_mix = "o2=500000;TEMP=293.15" }, /area/engine/engineering) "aej" = ( @@ -1705,14 +1705,14 @@ }, /turf/open/floor/engine{ name = "high pressure o2 floor"; - initial_gas_mix = "o2=500000" + initial_gas_mix = "o2=500000;TEMP=293.15" }, /area/engine/engineering) "aet" = ( /obj/machinery/portable_atmospherics/canister/oxygen, /turf/open/floor/engine{ name = "high pressure o2 floor"; - initial_gas_mix = "o2=500000" + initial_gas_mix = "o2=500000;TEMP=293.15" }, /area/engine/engineering) "aeu" = ( @@ -1727,7 +1727,7 @@ }, /turf/open/floor/engine{ name = "high pressure o2 floor"; - initial_gas_mix = "o2=500000" + initial_gas_mix = "o2=500000;TEMP=293.15" }, /area/engine/engineering) "aev" = ( @@ -1799,7 +1799,7 @@ /obj/machinery/light/small, /turf/open/floor/engine{ name = "high pressure o2 floor"; - initial_gas_mix = "o2=500000" + initial_gas_mix = "o2=500000;TEMP=293.15" }, /area/engine/engineering) "aeE" = ( @@ -2570,7 +2570,7 @@ "agD" = ( /turf/open/floor/engine{ name = "high pressure plasma floor"; - initial_gas_mix = "plasma=240000" + initial_gas_mix = "plasma=240000;TEMP=293.15" }, /area/engine/engineering) "agE" = ( @@ -2579,7 +2579,7 @@ }, /turf/open/floor/engine{ name = "high pressure plasma floor"; - initial_gas_mix = "plasma=240000" + initial_gas_mix = "plasma=240000;TEMP=293.15" }, /area/engine/engineering) "agF" = ( @@ -2739,14 +2739,14 @@ }, /turf/open/floor/engine{ name = "high pressure plasma floor"; - initial_gas_mix = "plasma=240000" + initial_gas_mix = "plasma=240000;TEMP=293.15" }, /area/engine/engineering) "agX" = ( /obj/machinery/portable_atmospherics/canister/toxins, /turf/open/floor/engine{ name = "high pressure plasma floor"; - initial_gas_mix = "plasma=240000" + initial_gas_mix = "plasma=240000;TEMP=293.15" }, /area/engine/engineering) "agY" = ( @@ -2761,7 +2761,7 @@ }, /turf/open/floor/engine{ name = "high pressure plasma floor"; - initial_gas_mix = "plasma=240000" + initial_gas_mix = "plasma=240000;TEMP=293.15" }, /area/engine/engineering) "agZ" = ( @@ -2808,8 +2808,8 @@ "ahf" = ( /obj/structure/cable, /obj/machinery/power/generator{ - cold_dir = 8; - hot_dir = 4 + cold_dir = 4; + hot_dir = 8 }, /turf/open/floor/plasteel, /area/engine/engineering) @@ -2972,7 +2972,7 @@ /obj/machinery/light/small, /turf/open/floor/engine{ name = "high pressure plasma floor"; - initial_gas_mix = "plasma=240000" + initial_gas_mix = "plasma=240000;TEMP=293.15" }, /area/engine/engineering) "ahB" = ( @@ -3271,7 +3271,7 @@ "ain" = ( /turf/open/floor/engine{ name = "high pressure co2 floor"; - initial_gas_mix = "co2=200000" + initial_gas_mix = "co2=200000;TEMP=293.15" }, /area/engine/engineering) "aio" = ( @@ -3280,7 +3280,7 @@ }, /turf/open/floor/engine{ name = "high pressure co2 floor"; - initial_gas_mix = "co2=200000" + initial_gas_mix = "co2=200000;TEMP=293.15" }, /area/engine/engineering) "aip" = ( @@ -3395,14 +3395,14 @@ }, /turf/open/floor/engine{ name = "high pressure co2 floor"; - initial_gas_mix = "co2=200000" + initial_gas_mix = "co2=200000;TEMP=293.15" }, /area/engine/engineering) "aiD" = ( /obj/machinery/portable_atmospherics/canister/carbon_dioxide, /turf/open/floor/engine{ name = "high pressure co2 floor"; - initial_gas_mix = "co2=200000" + initial_gas_mix = "co2=200000;TEMP=293.15" }, /area/engine/engineering) "aiE" = ( @@ -3417,7 +3417,7 @@ }, /turf/open/floor/engine{ name = "high pressure co2 floor"; - initial_gas_mix = "co2=200000" + initial_gas_mix = "co2=200000;TEMP=293.15" }, /area/engine/engineering) "aiF" = ( @@ -3537,7 +3537,7 @@ /obj/machinery/light/small, /turf/open/floor/engine{ name = "high pressure co2 floor"; - initial_gas_mix = "co2=200000" + initial_gas_mix = "co2=200000;TEMP=293.15" }, /area/engine/engineering) "aiW" = ( @@ -3644,7 +3644,7 @@ "aji" = ( /turf/open/floor/engine{ name = "high pressure n2 floor"; - initial_gas_mix = "n2=400000" + initial_gas_mix = "n2=400000;TEMP=293.15" }, /area/engine/engineering) "ajj" = ( @@ -3659,7 +3659,7 @@ }, /turf/open/floor/engine{ name = "high pressure n2 floor"; - initial_gas_mix = "n2=400000" + initial_gas_mix = "n2=400000;TEMP=293.15" }, /area/engine/engineering) "ajk" = ( @@ -3767,14 +3767,14 @@ }, /turf/open/floor/engine{ name = "high pressure n2 floor"; - initial_gas_mix = "n2=400000" + initial_gas_mix = "n2=400000;TEMP=293.15" }, /area/engine/engineering) "ajx" = ( /obj/machinery/portable_atmospherics/canister/nitrogen, /turf/open/floor/engine{ name = "high pressure n2 floor"; - initial_gas_mix = "n2=400000" + initial_gas_mix = "n2=400000;TEMP=293.15" }, /area/engine/engineering) "ajy" = ( @@ -3783,7 +3783,7 @@ }, /turf/open/floor/engine{ name = "high pressure n2 floor"; - initial_gas_mix = "n2=400000" + initial_gas_mix = "n2=400000;TEMP=293.15" }, /area/engine/engineering) "ajz" = ( @@ -3844,7 +3844,7 @@ /obj/machinery/light/small, /turf/open/floor/engine{ name = "high pressure n2 floor"; - initial_gas_mix = "n2=400000" + initial_gas_mix = "n2=400000;TEMP=293.15" }, /area/engine/engineering) "ajI" = ( @@ -4089,7 +4089,7 @@ "akd" = ( /turf/open/floor/engine{ name = "high pressure air floor"; - initial_gas_mix = "o2=10000;n2=40015" + initial_gas_mix = "o2=10000;n2=40015;TEMP=293.15" }, /area/engine/engineering) "ake" = ( @@ -4133,14 +4133,14 @@ }, /turf/open/floor/engine{ name = "high pressure air floor"; - initial_gas_mix = "o2=10000;n2=40015" + initial_gas_mix = "o2=10000;n2=40015;TEMP=293.15" }, /area/engine/engineering) "akm" = ( /obj/machinery/portable_atmospherics/canister/air, /turf/open/floor/engine{ name = "high pressure air floor"; - initial_gas_mix = "o2=10000;n2=40015" + initial_gas_mix = "o2=10000;n2=40015;TEMP=293.15" }, /area/engine/engineering) "akn" = ( @@ -4155,7 +4155,7 @@ }, /turf/open/floor/engine{ name = "high pressure air floor"; - initial_gas_mix = "o2=10000;n2=40015" + initial_gas_mix = "o2=10000;n2=40015;TEMP=293.15" }, /area/engine/engineering) "ako" = ( diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 0b7a3184c44..4d1482c1d76 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -53303,7 +53303,7 @@ /area/bridge) "bOg" = ( /obj/structure/rack, -/obj/machinery/telecomms/bus, +/obj/item/weapon/circuitboard/machine/telecomms/bus, /obj/item/weapon/circuitboard/machine/telecomms/broadcaster, /obj/machinery/atmospherics/components/unary/vent_pump{ dir = 1; diff --git a/_maps/map_files/TgStation/tgstation.2.1.3.dmm b/_maps/map_files/TgStation/tgstation.2.1.3.dmm index 6f9c860ea8c..753df9896f2 100644 --- a/_maps/map_files/TgStation/tgstation.2.1.3.dmm +++ b/_maps/map_files/TgStation/tgstation.2.1.3.dmm @@ -58527,7 +58527,7 @@ name = "Emergency Shuttle Airlock"; req_access_txt = "2" }, -/turf/closed/wall/mineral/titanium/nodiagonal, +/turf/open/floor/mineral/plastitanium/brig, /area/shuttle/escape) "cxh" = ( /obj/structure/chair{ diff --git a/_maps/map_files/generic/lavaland.dmm b/_maps/map_files/generic/lavaland.dmm index c864950a0c5..5d5b80a9a7b 100644 --- a/_maps/map_files/generic/lavaland.dmm +++ b/_maps/map_files/generic/lavaland.dmm @@ -535,10 +535,10 @@ height = 5; id = "laborcamp_away"; name = "labor camp"; - turf_type = /turf/open/floor/plating/lava/smooth; + turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface; width = 9 }, -/turf/open/floor/plating/lava/smooth/lava_land_surface, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors/explored) "bm" = ( /obj/machinery/door/airlock/glass_security{ @@ -5844,7 +5844,7 @@ af bA bA bA -bA +dq bA bA bA @@ -5853,7 +5853,7 @@ bA dq bA bA -bA +dq bA bA bA @@ -6102,15 +6102,15 @@ af bA bA bA -bA -bA -bA -bA -bA -bA -bA -bA -bA +dq +dq +dq +dq +dq +dq +dq +dq +dq bA af af @@ -6359,15 +6359,15 @@ bA bA bA bA -bA -bA -bA -bA -bA -bA -bA -bA -bA +dq +dq +dq +dq +dq +dq +dq +dq +dq bA bA ab @@ -6616,15 +6616,15 @@ bA bA bA bA -bA -bA -bA -bA -bA -bA -bA -bA -bA +dq +dq +dq +dq +dq +dq +dq +dq +dq bA bA bA @@ -6873,15 +6873,15 @@ af bA bA bA -bA -bA -bA -bA -bA -bA -bA -bA -bA +dq +dq +dq +dq +dq +dq +dq +dq +dq bA af af @@ -7129,17 +7129,17 @@ af af bA bA -bA -bA -bA -bA -bA -bA -bA +dq +dq +dq +dq +dq +dq +dq bl -bA -bA -bA +dq +dq +dq af af af @@ -7391,7 +7391,7 @@ an an aO an -fI +an an bm an diff --git a/_maps/map_files/generic/z2.dmm b/_maps/map_files/generic/z2.dmm index d426013a909..66251a4f0c6 100644 --- a/_maps/map_files/generic/z2.dmm +++ b/_maps/map_files/generic/z2.dmm @@ -5810,7 +5810,7 @@ /area/holodeck/rec_center/winterwonderland) "se" = ( /turf/open/floor/holofloor/snow/cold, -/area/holodeck/rec_center/medical) +/area/holodeck/rec_center/winterwonderland) "sf" = ( /obj/structure/flora/bush, /turf/open/floor/holofloor/snow/cold, diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 43933ce6127..1d7a3b8df61 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -63,6 +63,8 @@ #define issilicon(A) (istype(A, /mob/living/silicon)) +#define iscyborg(A) (istype(A, /mob/living/silicon/robot)) + #define isliving(A) (istype(A, /mob/living)) #define isobserver(A) (istype(A, /mob/dead/observer)) diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm index a0877b8d756..27280edfd79 100644 --- a/code/__DEFINES/machines.dm +++ b/code/__DEFINES/machines.dm @@ -21,4 +21,5 @@ #define AUTOLATHE 4 //Uses glass/metal only. #define CRAFTLATHE 8 //Uses fuck if I know. For use eventually. #define MECHFAB 16 //Remember, objects utilising this flag should have construction_time and construction_cost vars. +#define BIOGENERATOR 32 //Uses biomass //Note: More then one of these can be added to a design but imprinter and lathe designs are incompatable. \ No newline at end of file diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index e8bc1480d48..fdd549e71e2 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -263,6 +263,7 @@ #define MAT_PLASMA "$plasma" #define MAT_BANANIUM "$bananium" #define MAT_TITANIUM "$titanium" +#define MAT_BIOMASS "$biomass" //check_target_facings() return defines diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index f478a81e5ff..eb441a96b94 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -397,14 +397,14 @@ return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y) -/proc/pollCandidates(var/Question, var/jobbanType, var/datum/game_mode/gametypeCheck, var/be_special_flag = 0, var/poll_time = 300) +/proc/pollCandidates(var/Question, var/jobbanType, var/datum/game_mode/gametypeCheck, var/be_special_flag = 0, var/poll_time = 300, var/ignore_category = null) var/list/mob/dead/observer/candidates = list() var/time_passed = world.time if (!Question) Question = "Would you like to be a special role?" for(var/mob/dead/observer/G in player_list) - if(!G.key || !G.client) + if(!G.key || !G.client || (ignore_category && poll_ignore[ignore_category] && G.ckey in poll_ignore[ignore_category])) continue if(be_special_flag) if(!(G.client.prefs) || !(be_special_flag in G.client.prefs.be_special)) @@ -417,7 +417,7 @@ continue spawn(0) G << 'sound/misc/notice2.ogg' //Alerting them to their consideration - switch(askuser(G,Question,"Please answer in [poll_time/10] seconds!","Yes","No", StealFocus=0, Timeout=poll_time)) + switch(ignore_category ? askuser(G,Question,"Please answer in [poll_time/10] seconds!","Yes","No","Never for this round", StealFocus=0, Timeout=poll_time) : askuser(G,Question,"Please answer in [poll_time/10] seconds!","Yes","No", StealFocus=0, Timeout=poll_time)) if(1) G << "Choice registered: Yes." if((world.time-time_passed)>poll_time) @@ -427,6 +427,12 @@ candidates += G if(2) G << "Choice registered: No." + if(3) + var/list/L = poll_ignore[ignore_category] + if(!L) + poll_ignore[ignore_category] = list() + poll_ignore[ignore_category] += G.ckey + G << "Choice registered: Never for this round." sleep(poll_time) //Check all our candidates, to make sure they didn't log off during the wait period. diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm index fd4b3222026..7f76e50e434 100644 --- a/code/__HELPERS/icon_smoothing.dm +++ b/code/__HELPERS/icon_smoothing.dm @@ -156,20 +156,22 @@ underlays.Cut() if(fixed_underlay) if(fixed_underlay["space"]) - underlays += image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=src.layer) + underlays += image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=TURF_LAYER) else - underlays += image(fixed_underlay["icon"], fixed_underlay["icon_state"], layer=src.layer) + underlays += image(fixed_underlay["icon"], fixed_underlay["icon_state"], layer=TURF_LAYER) else var/turf/T = get_step(src, turn(adjacencies, 180)) - if(T && T.density) + if(T && (T.density || T.smooth)) T = get_step(src, turn(adjacencies, 135)) - if(T && T.density) + if(T && (T.density || T.smooth)) T = get_step(src, turn(adjacencies, 225)) - if(istype(T, /turf/open/space)) - underlays += image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=src.layer) + if(istype(T, /turf/open/space) && !istype(T, /turf/open/space/transit)) + underlays += image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=TURF_LAYER) else if(T && !T.density && !T.smooth) underlays += T + else if(baseturf && !initial(baseturf.density) && !initial(baseturf.smooth)) + underlays += image(initial(baseturf.icon), initial(baseturf.icon_state), layer=TURF_LAYER) else underlays += DEFAULT_UNDERLAY_IMAGE diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index db09c2a3dca..0f4bf8fa162 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -692,11 +692,7 @@ The _flatIcons list is a cache for generated icon files. var/image/copy // Add the atom's icon itself, without pixel_x/y offsets. if(!noIcon) - var/icon/copyicon = icon(curicon, curstate, dir=curdir) - if(IsBlankIcon(copyicon)) - curdir = SOUTH - copy = image(icon=curicon, icon_state=curstate, layer=A.layer) - copy.dir = curdir + copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=curdir) copy.color = A.color copy.alpha = A.alpha copy.blend_mode = curblend @@ -919,12 +915,6 @@ var/global/list/friendly_animal_types = list() final_average = BlendRGB(final_average, colour, 1) return final_average -/proc/IsBlankIcon(icon/I) - for(var/y_pixel = 1 to I.Height()) - for(var/x_pixel = 1 to I.Width()) - if(I.GetPixel(x_pixel, y_pixel)) - return 0 - return 1 //Interface for using DrawBox() to draw 1 pixel on a coordinate. //Returns the same icon specifed in the argument, but with the pixel drawn @@ -1016,4 +1006,4 @@ var/global/list/humanoid_icon_cache = list() //Images have dir without being an atom, so they get their own definition. //Lame. /image/proc/setDir(newdir) - dir = newdir + dir = newdir diff --git a/code/_globalvars/lists/poll_ignore.dm b/code/_globalvars/lists/poll_ignore.dm new file mode 100644 index 00000000000..6a765f6bfd3 --- /dev/null +++ b/code/_globalvars/lists/poll_ignore.dm @@ -0,0 +1,6 @@ +//Each lists stores ckeys for "Never for this round" option category + +#define POLL_IGNORE_PAI "pai" +#define POLL_IGNORE_SENTIENCE_POTION "sentience_potion" + +var/list/poll_ignore = list() \ No newline at end of file diff --git a/code/controllers/subsystem/pai.dm b/code/controllers/subsystem/pai.dm index 1978c1b167d..f3dcb49e6c3 100644 --- a/code/controllers/subsystem/pai.dm +++ b/code/controllers/subsystem/pai.dm @@ -5,10 +5,7 @@ var/datum/subsystem/pai/SSpai init_order = 20 flags = SS_NO_FIRE|SS_NO_INIT - var/askDelay = 600 - var/const/NEVER_FOR_THIS_ROUND = -1 var/list/candidates = list() - var/list/asked = list() /datum/subsystem/pai/New() NEW_SS_GLOBAL(SSpai) @@ -181,34 +178,10 @@ var/datum/subsystem/pai/SSpai user << browse(dat, "window=findPai") /datum/subsystem/pai/proc/requestRecruits() - for(var/mob/dead/observer/O in player_list) - if(jobban_isbanned(O, ROLE_PAI)) - continue - if(asked[O.ckey]) - if(world.time < asked[O.ckey] + askDelay || asked[O.ckey] == NEVER_FOR_THIS_ROUND) - continue - else - asked.Remove(O.ckey) - if(O.client) - var/hasSubmitted = 0 - for(var/datum/paiCandidate/c in SSpai.candidates) - if(c.key == O.key) - hasSubmitted = 1 - if(!hasSubmitted && (ROLE_PAI in O.client.prefs.be_special)) - question(O.client) - -/datum/subsystem/pai/proc/question(client/C) - set waitfor = 0 - if(!C) - return - asked[C.ckey] = world.time - var/response = tgalert(C, "Someone is requesting a pAI personality. Would you like to play as a personal AI?", "pAI Request", "Yes", "No", "Never for this round", StealFocus=0, Timeout=askDelay) - if(!C) - return //handle logouts that happen whilst the alert is waiting for a response. - if(response == "Yes") - recruitWindow(C.mob) - else if (response == "Never for this round") - asked[C.ckey] = NEVER_FOR_THIS_ROUND + var/list/candidates = pollCandidates("Someone is requesting a pAI personality. Would you like to play as a personal AI?", ROLE_PAI, null, ROLE_PAI,300, ignore_category = POLL_IGNORE_PAI) + for(var/V in candidates) + recruitWindow(V) + return /datum/paiCandidate var/name diff --git a/code/datums/action.dm b/code/datums/action.dm index 395de2dfc87..31779f99b8f 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -303,6 +303,7 @@ ..() /datum/action/item_action/toggle_research_scanner/ApplyIcon(obj/screen/movable/action_button/current_button) + current_button.cut_overlays() if(button_icon && button_icon_state) var/image/img = image(button_icon, current_button, "scan_mode") current_button.add_overlay(img) diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 1968d08e493..bee26a1a538 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -6,6 +6,7 @@ var/list/supplied = list() var/list/ion = list() var/mob/living/silicon/owner + var/list/devillaws = null /datum/ai_laws/default/asimov name = "Three Laws of Robotics" @@ -189,71 +190,82 @@ add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") WARNING("Invalid custom AI laws, check silicon_laws.txt") +/datum/ai_laws/proc/set_law_sixsixsix(laws) + devillaws = laws + /datum/ai_laws/proc/set_zeroth_law(law, law_borg = null) - src.zeroth = law + zeroth = law if(law_borg) //Making it possible for slaved borgs to see a different law 0 than their AI. --NEO - src.zeroth_borg = law_borg + zeroth_borg = law_borg /datum/ai_laws/proc/add_inherent_law(law) - if (!(law in src.inherent)) - src.inherent += law + if (!(law in inherent)) + inherent += law /datum/ai_laws/proc/add_ion_law(law) - src.ion += law + ion += law /datum/ai_laws/proc/clear_inherent_laws() - qdel(src.inherent) - src.inherent = list() + qdel(inherent) + inherent = list() /datum/ai_laws/proc/add_supplied_law(number, law) - while (src.supplied.len < number + 1) - src.supplied += "" + while (supplied.len < number + 1) + supplied += "" - src.supplied[number + 1] = law + supplied[number + 1] = law /datum/ai_laws/proc/clear_supplied_laws() - src.supplied = list() + supplied = list() /datum/ai_laws/proc/clear_ion_laws() - src.ion = list() + ion = list() /datum/ai_laws/proc/show_laws(who) - if (src.zeroth) - who << "0. [src.zeroth]" + if (devillaws && devillaws.len) //Yes, devil laws go in FRONT of zeroth laws, as the devil must still obey it's ban/obligation. + for(var/i in devillaws) + who << "666. [i]" - for (var/index = 1, index <= src.ion.len, index++) - var/law = src.ion[index] + if (zeroth) + who << "0. [zeroth]" + + for (var/index = 1, index <= ion.len, index++) + var/law = ion[index] var/num = ionnum() who << "[num]. [law]" var/number = 1 - for (var/index = 1, index <= src.inherent.len, index++) - var/law = src.inherent[index] + for (var/index = 1, index <= inherent.len, index++) + var/law = inherent[index] if (length(law) > 0) who << "[number]. [law]" number++ - for (var/index = 1, index <= src.supplied.len, index++) - var/law = src.supplied[index] + for (var/index = 1, index <= supplied.len, index++) + var/law = supplied[index] if (length(law) > 0) who << "[number]. [law]" number++ /datum/ai_laws/proc/clear_zeroth_law(force) //only removes zeroth from antag ai if force is 1 if(force) - src.zeroth = null - src.zeroth_borg = null + zeroth = null + zeroth_borg = null return else if(owner && owner.mind.special_role) return else - src.zeroth = null - src.zeroth_borg = null + zeroth = null + zeroth_borg = null return +/datum/ai_laws/proc/clear_law_sixsixsix(force) + if(force || !(owner && owner.mind.devilinfo)) + devillaws = null + /datum/ai_laws/proc/associate(mob/living/silicon/M) if(!owner) owner = M @@ -261,6 +273,10 @@ /datum/ai_laws/proc/get_law_list(include_zeroth = 0, show_numbers = 1) var/list/data = list() + if (include_zeroth && devillaws && devillaws.len) + for(var/i in devillaws) + data += "[show_numbers ? "666:" : ""] [i]" + if (include_zeroth && zeroth) data += "[show_numbers ? "0:" : ""] [zeroth]" diff --git a/code/datums/diseases/parrotpossession.dm b/code/datums/diseases/parrotpossession.dm new file mode 100644 index 00000000000..0df7e0f7d37 --- /dev/null +++ b/code/datums/diseases/parrotpossession.dm @@ -0,0 +1,27 @@ +/datum/disease/parrot_possession + name = "Parrot Possession" + max_stages = 1 + spread_text = "Paranormal" + spread_flags = SPECIAL + disease_flags = CURABLE + cure_text = "Holy Water." + cures = list("holywater") + cure_chance = 20 + agent = "Avian Vengence" + viable_mobtypes = list(/mob/living/carbon/human) + desc = "Subject is possesed by the vengeful spirit of a parrot. Call the priest." + severity = MEDIUM + var/mob/living/simple_animal/parrot/Poly/ghost/parrot + +/datum/disease/parrot_possession/stage_act() + ..() + if(!parrot || parrot.loc != affected_mob) + cure() + else if(prob(parrot.speak_chance)) + affected_mob.say(pick(parrot.speech_buffer)) + +/datum/disease/parrot_possession/cure() + if(parrot && parrot.loc == affected_mob) + parrot.loc = affected_mob.loc + affected_mob.visible_message("[parrot] is violently driven out of [affected_mob]!", "[parrot] bursts out of your chest!") + ..() \ No newline at end of file diff --git a/code/datums/material_container.dm b/code/datums/material_container.dm index e299c42ab48..c158dfa4820 100644 --- a/code/datums/material_container.dm +++ b/code/datums/material_container.dm @@ -137,6 +137,8 @@ //For spawning mineral sheets; internal use only /datum/material_container/proc/retrieve(sheet_amt, datum/material/M) + if(!M.sheet_type) + return 0 if(sheet_amt > 0) if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT)) sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT) @@ -267,4 +269,8 @@ /datum/material/titanium name = "Titanium" id = MAT_TITANIUM - sheet_type = /obj/item/stack/sheet/mineral/titanium \ No newline at end of file + sheet_type = /obj/item/stack/sheet/mineral/titanium + +/datum/material/biomass + name = "Biomass" + id = MAT_BIOMASS diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 50bce2a1f48..a5b7b4dfdc9 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1185,19 +1185,24 @@ RemoveSpell(/obj/effect/proc_holder/spell/targeted/summon_pitchfork) message_admins("[key_name_admin(usr)] has de-devil'ed [current].") devilinfo = null + if(issilicon(current)) + var/mob/living/silicon/S = current + S.clear_law_sixsixsix(current) log_admin("[key_name(usr)] has de-devil'ed [current].") else if(src in ticker.mode.sintouched) ticker.mode.sintouched -= src message_admins("[key_name_admin(usr)] has de-sintouch'ed [current].") log_admin("[key_name(usr)] has de-sintouch'ed [current].") if("devil") - if(!ishuman(current)) + if(!ishuman(current) && !iscyborg(current)) usr << "This only works on humans!" return ticker.mode.devils += src special_role = "devil" ticker.mode.finalize_devil(src) + ticker.mode.add_devil_objectives(src, 2) announceDevilLaws() + announce_objectives() if("sintouched") if(ishuman(current)) ticker.mode.sintouched += src diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm index 7ee4db856d4..1761efdda88 100644 --- a/code/game/area/Space_Station_13_areas.dm +++ b/code/game/area/Space_Station_13_areas.dm @@ -1158,6 +1158,10 @@ var/list/teleportlocs = list() name = "Construction Area" icon_state = "yellow" +/area/mining_construction + name = "Auxillary Base Construction" + icon_state = "yellow" + /area/construction/supplyshuttle name = "Supply Shuttle" icon_state = "yellow" diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index d7681cfad7b..fe14f5486f8 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -131,6 +131,8 @@ /mob/living/proc/med_hud_set_health() var/image/holder = hud_list[HEALTH_HUD] holder.icon_state = "hud[RoundHealth(src)]" + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size //for carbon suit sensors /mob/living/carbon/med_hud_set_health() @@ -143,6 +145,8 @@ //called when a carbon changes stat, virus or XENO_HOST /mob/living/proc/med_hud_set_status() var/image/holder = hud_list[STATUS_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size if(stat == DEAD || (status_flags & FAKEDEATH)) holder.icon_state = "huddead" else @@ -150,6 +154,8 @@ /mob/living/carbon/med_hud_set_status() var/image/holder = hud_list[STATUS_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size if(status_flags & XENO_HOST) holder.icon_state = "hudxeno" else if(stat == DEAD || (status_flags & FAKEDEATH)) @@ -168,6 +174,8 @@ /mob/living/carbon/human/proc/sec_hud_set_ID() var/image/holder = hud_list[ID_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size holder.icon_state = "hudno_id" if(wear_id) holder.icon_state = "hud[ckey(wear_id.GetJobName())]" @@ -185,16 +193,24 @@ if(I.implanted) if(istype(I,/obj/item/weapon/implant/tracking)) holder = hud_list[IMPTRACK_HUD] + var/icon/IC = icon(icon, icon_state, dir) + holder.pixel_y = IC.Height() - world.icon_size holder.icon_state = "hud_imp_tracking" else if(istype(I,/obj/item/weapon/implant/mindshield)) holder = hud_list[IMPLOYAL_HUD] + var/icon/IC = icon(icon, icon_state, dir) + holder.pixel_y = IC.Height() - world.icon_size holder.icon_state = "hud_imp_loyal" else if(istype(I,/obj/item/weapon/implant/chem)) holder = hud_list[IMPCHEM_HUD] + var/icon/IC = icon(icon, icon_state, dir) + holder.pixel_y = IC.Height() - world.icon_size holder.icon_state = "hud_imp_chem" /mob/living/carbon/human/proc/sec_hud_set_security_status() var/image/holder = hud_list[WANTED_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size var/perpname = get_face_name(get_id_name("")) if(perpname) var/datum/data/record/R = find_record("name", perpname, data_core.security) @@ -240,6 +256,8 @@ //Sillycone hooks /mob/living/silicon/proc/diag_hud_set_health() var/image/holder = hud_list[DIAG_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size if(stat == DEAD) holder.icon_state = "huddiagdead" else @@ -247,6 +265,8 @@ /mob/living/silicon/proc/diag_hud_set_status() var/image/holder = hud_list[DIAG_STAT_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size switch(stat) if(CONSCIOUS) holder.icon_state = "hudstat" @@ -258,7 +278,9 @@ //Borgie battery tracking! /mob/living/silicon/robot/proc/diag_hud_set_borgcell() var/image/holder = hud_list[DIAG_BATT_HUD] - if (cell) + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size + if(cell) var/chargelvl = (cell.charge/cell.maxcharge) holder.icon_state = "hudbatt[RoundDiagBar(chargelvl)]" else @@ -269,12 +291,16 @@ ~~~~~~~~~~~~~~~~~~~~~*/ /obj/mecha/proc/diag_hud_set_mechhealth() var/image/holder = hud_list[DIAG_MECH_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size holder.icon_state = "huddiag[RoundDiagBar(health/initial(health))]" /obj/mecha/proc/diag_hud_set_mechcell() var/image/holder = hud_list[DIAG_BATT_HUD] - if (cell) + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size + if(cell) var/chargelvl = cell.charge/cell.maxcharge holder.icon_state = "hudbatt[RoundDiagBar(chargelvl)]" else @@ -283,6 +309,8 @@ /obj/mecha/proc/diag_hud_set_mechstat() var/image/holder = hud_list[DIAG_STAT_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size holder.icon_state = null if(internal_damage) holder.icon_state = "hudwarn" @@ -292,10 +320,14 @@ ~~~~~~~~~~*/ /mob/living/simple_animal/bot/proc/diag_hud_set_bothealth() var/image/holder = hud_list[DIAG_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size holder.icon_state = "huddiag[RoundDiagBar(health/maxHealth)]" /mob/living/simple_animal/bot/proc/diag_hud_set_botstat() //On (With wireless on or off), Off, EMP'ed var/image/holder = hud_list[DIAG_STAT_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size if(on) holder.icon_state = "hudstat" else if(stat) //Generally EMP causes this @@ -305,6 +337,8 @@ /mob/living/simple_animal/bot/proc/diag_hud_set_botmode() //Shows a bot's current operation var/image/holder = hud_list[DIAG_BOT_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size if(client) //If the bot is player controlled, it will not be following mode logic! holder.icon_state = "hudsentient" return diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm index 8ad4ebd850c..67c404ce600 100644 --- a/code/game/gamemodes/blob/blobs/blob_mobs.dm +++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm @@ -202,6 +202,7 @@ next_move_modifier = 1.5 //slow-ass attack speed, 3 times higher than how fast the blob can attack melee_damage_lower = 20 melee_damage_upper = 20 + obj_damage = 20 attacktext = "slams" attack_sound = 'sound/effects/blobattack.ogg' verb_say = "gurgles" diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 59a353c1258..fbf0b21d25a 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -41,7 +41,7 @@ This file's folder contains: return 0 if(!M.mind) return 0 - if(M.mind.enslaved_to) + if(M.mind.enslaved_to && !is_servant_of_ratvar(M.mind.enslaved_to)) return 0 if(iscultist(M) || isconstruct(M)) return 0 @@ -119,6 +119,19 @@ This file's folder contains: H.Grant(S) H.title = null //so it's just the borg's name S << "You can communicate with other servants by using the Hierophant Network action button in the upper left." + else if(isbrain(M)) + var/datum/action/innate/hierophant/H = new() + H.Grant(M) + H.title = "Vessel" + H.span_for_name = "nezbere" + H.span_for_message = "alloy" + M << "You can communicate with other servants by using the Hierophant Network action button in the upper left." + else if(isclockmob(M)) + var/datum/action/innate/hierophant/H = new() + H.Grant(M) + H.title = "Construct" + H.span_for_name = "nezbere" + M << "You can communicate with other servants by using the Hierophant Network action button in the upper left." if(istype(ticker.mode, /datum/game_mode/clockwork_cult)) var/datum/game_mode/clockwork_cult/C = ticker.mode C.present_tasks(M) //Memorize the objectives @@ -234,7 +247,7 @@ This file's folder contains: if("gateway") clockwork_explanation = "Construct a Gateway to the Celestial Derelict and free Ratvar." if("silicons") - clockwork_explanation = "Ensure that all silicon-based lifeforms on [station_name()] are servants of Ratvar by the end of the shift." + clockwork_explanation = "Ensure that all active silicon-based lifeforms on [station_name()] are servants of Ratvar by the end of the shift." return 1 /datum/game_mode/clockwork_cult/proc/greet_servant(mob/M) //Description of their role @@ -279,27 +292,26 @@ This file's folder contains: for(var/datum/mind/M in servants_of_ratvar) if(M.current && M.current.stat != DEAD && (M.current.onCentcom() || M.current.onSyndieBase())) surviving_servants++ - clockwork_explanation = "Ensure that [required_escapees] servant(s) of Ratvar escape from [station_name()]. [surviving_servants] managed to escape!" + clockwork_explanation = "Ensure that [required_escapees] servant(s) of Ratvar escape from [station_name()]. [surviving_servants] managed to escape!" if(surviving_servants >= required_escapees) return TRUE return FALSE if("silicons") var/total_silicons = 0 - var/converted_silicons = 0 + var/valid_silicons = 0 var/successful = TRUE - for(var/mob/living/silicon/robot/S in living_mob_list) //Only check robots and AIs + for(var/mob/living/silicon/robot/S in mob_list) //Only check robots and AIs total_silicons++ - if(!is_servant_of_ratvar(S)) - successful = FALSE - else - converted_silicons++ - for(var/mob/living/silicon/ai/A in living_mob_list) + if(is_servant_of_ratvar(S) || S.stat == DEAD) + valid_silicons++ + for(var/mob/living/silicon/ai/A in mob_list) total_silicons++ - if(!is_servant_of_ratvar(A)) - successful = FALSE - else - converted_silicons++ - clockwork_explanation = "Ensure that all silicon-based lifeforms on [station_name()] are servants of Ratvar by the end of the shift. [converted_silicons]/[total_silicons] silicons were converted!" + if(is_servant_of_ratvar(A) || A.stat == DEAD) + valid_silicons++ + if(valid_silicons < total_silicons) + successful = FALSE + clockwork_explanation = "Ensure that all active silicon-based lifeforms on [station_name()] are servants of Ratvar by the end of the shift. \ + [valid_silicons]/[total_silicons] silicons were killed or converted!" return successful if("gateway") return ratvar_awakens @@ -323,12 +335,12 @@ This file's folder contains: if(G) half_victory = TRUE if(half_victory) - text += "The crew escaped before Ratvar could rise, but the station was taken over!" + text += "The crew escaped before Ratvar could rise, but the gateway was successfully constructed!" feedback_set_details("round_end_result", "halfwin - round ended before the gateway finished") else text += "Ratvar's servants have failed!" feedback_set_details("round_end_result", "loss - servants failed their objective ([clockwork_objective])") - text += "
The servants' objective was: [clockwork_explanation]
" + text += "
The servants' objective was:
[clockwork_explanation]
" if(servants_of_ratvar.len) text += "Ratvar's servants were:" for(var/datum/mind/M in servants_of_ratvar) diff --git a/code/game/gamemodes/clock_cult/clock_items.dm b/code/game/gamemodes/clock_cult/clock_items.dm index c8c952393fb..efe337bcb0c 100644 --- a/code/game/gamemodes/clock_cult/clock_items.dm +++ b/code/game/gamemodes/clock_cult/clock_items.dm @@ -192,7 +192,7 @@ /obj/item/clockwork/slab/proc/access_display(mob/living/user) if(!is_servant_of_ratvar(user)) return 0 - var/action = input(user, "Among the swathes of information, you see...", "[src]") as null|anything in list("Recital", "Records", "Recollection") + var/action = alert(user, "Among the swathes of information, you see...", "[src]", "Recital", "Recollection", "Records") if(!action || !user.canUseTopic(src)) return 0 switch(action) @@ -883,7 +883,9 @@ /obj/item/device/mmi/posibrain/soul_vessel //Soul vessel: An ancient positronic brain with a lawset catered to serving Ratvar. name = "soul vessel" - desc = "A heavy brass cube with a single protruding cogwheel." + desc = "A heavy brass cube, three inches to a side, with a single protruding cogwheel." + var/clockwork_desc = "A soul vessel, an ancient relic that can attract the souls of the damned or simply rip a mind from an unconscious or dead human.\n\ + If active, can serve as a positronic brain, placable in cyborg shells or clockwork construct shells." icon = 'icons/obj/clockwork_objects.dmi' icon_state = "soul_vessel" req_access = list() @@ -900,6 +902,7 @@ dead_message = "Its cogwheel, scratched and dented, lies motionless." fluff_names = list("Servant") clockwork = TRUE + autoping = FALSE /obj/item/device/mmi/posibrain/soul_vessel/New() ..() @@ -909,12 +912,65 @@ all_clockwork_objects -= src return ..() +/obj/item/device/mmi/posibrain/soul_vessel/examine(mob/user) + if((is_servant_of_ratvar(user) || isobserver(user)) && clockwork_desc) + desc = clockwork_desc + ..() + desc = initial(desc) + + /obj/item/device/mmi/posibrain/soul_vessel/attack_self(mob/living/user) if(!is_servant_of_ratvar(user)) user << "You fiddle around with [src], to no avail." return 0 ..() +/obj/item/device/mmi/posibrain/soul_vessel/attack(mob/living/target, mob/living/carbon/human/user) + if(!is_servant_of_ratvar(user) || !ishuman(target) || used || (brainmob && brainmob.key)) + ..() + if(is_servant_of_ratvar(target)) + user << "\"It would be more wise to revive your allies, friend.\"" + return + var/mob/living/carbon/human/H = target + var/obj/item/bodypart/head/HE = H.get_bodypart("head") + var/obj/item/organ/brain/B = H.getorgan(/obj/item/organ/brain) + if(!HE) + user << "[H] has no head, and thus no mind!" + return + if(H.stat == CONSCIOUS) + user << "[H] must be dead or unconscious to claim their mind!" + return + if(H.head) + var/obj/item/I = H.head + if(I.flags_inv & HIDEHAIR) + user << "[H]'s head is covered, remove [H.head] first!" + return + if(H.wear_mask) + var/obj/item/I = H.wear_mask + if(I.flags_inv & HIDEHAIR) + user << "[H]'s head is covered, remove [H.wear_mask] first!" + return + if(!B) + user << "[H] has no brain, and thus no mind to claim!" + return + if(!H.key) + user << "[H] has no mind to claim!" + return + playsound(H, 'sound/misc/splort.ogg', 60, 1, -1) + playsound(H, 'sound/magic/clockwork/anima_fragment_attack.ogg', 40, 1, -1) + H.status_flags |= FAKEDEATH //we want to make sure they don't deathgasp and maybe possibly explode + H.death() + H.status_flags &= ~FAKEDEATH + brainmob.name = H.real_name + brainmob.real_name = H.real_name + brainmob.timeofhostdeath = H.timeofdeath + user.visible_message("[user] presses [src] to [H]'s head, ripping through the skull and carefully extracting the brain!", \ + "You extract [H]'s consciousness from their body, trapping it in the soul vessel.") + transfer_personality(H) + B.Remove(H) + qdel(B) + H.update_hair() + /obj/item/clockwork/daemon_shell name = "daemon shell" desc = "A vaguely arachnoid brass shell with a single empty socket in its body." diff --git a/code/game/gamemodes/clock_cult/clock_ratvar.dm b/code/game/gamemodes/clock_cult/clock_ratvar.dm index 4946742e9cb..73ad516b9fc 100644 --- a/code/game/gamemodes/clock_cult/clock_ratvar.dm +++ b/code/game/gamemodes/clock_cult/clock_ratvar.dm @@ -159,6 +159,7 @@ pixel_x = -235 pixel_y = -248 takes_damage = FALSE + appearance_flags = 0 var/atom/prey //Whatever Ratvar is chasing var/clashing = FALSE //If Ratvar is FUCKING FIGHTING WITH NAR-SIE var/proselytize_range = 10 diff --git a/code/game/gamemodes/clock_cult/clock_scripture.dm b/code/game/gamemodes/clock_cult/clock_scripture.dm index 67aefeac17f..6ff3ece74fa 100644 --- a/code/game/gamemodes/clock_cult/clock_scripture.dm +++ b/code/game/gamemodes/clock_cult/clock_scripture.dm @@ -223,10 +223,10 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed -/datum/clockwork_scripture/vanguard //Vanguard: Provides twenty seconds of stun immunity. At the end of the twenty seconds, 50% of all stuns absorbed are applied to the invoker. +/datum/clockwork_scripture/vanguard //Vanguard: Provides twenty seconds of stun immunity. At the end of the twenty seconds, 25% of all stuns absorbed are applied to the invoker. descname = "Self Stun Immunity" name = "Vanguard" - desc = "Provides twenty seconds of stun immunity. At the end of the twenty seconds, the invoker is stunned for the equivalent of 50% of all stuns they absorbed. \ + desc = "Provides twenty seconds of stun immunity. At the end of the twenty seconds, the invoker is stunned for the equivalent of 25% of all stuns they absorbed. \ Excessive absorption will cause unconsciousness." invocations = list("Shield me...", "...from darkness!") channel_time = 30 @@ -251,7 +251,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed var/vanguard = invoker.stun_absorption["vanguard"] var/stuns_blocked = 0 if(vanguard) - stuns_blocked = min(vanguard["stuns_absorbed"] * 0.5, 20) + stuns_blocked = min(vanguard["stuns_absorbed"] * 0.25, 20) if(invoker.stat != DEAD) var/message_to_invoker = "You feel your Vanguard quietly fade..." var/otheractiveabsorptions = FALSE @@ -707,8 +707,8 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed consumed_components = list("vanguard_cogwheel" = 1, "guvax_capacitor" = 1) whispered = TRUE object_path = /obj/item/device/mmi/posibrain/soul_vessel - creator_message = "You form a soul vessel, which immediately begins drawing in the damned." - usage_tip = "The vessel functions as a servant for tier unlocking but not for invocation." + creator_message = "You form a soul vessel, which can be used in-hand to attract spirits, or used on an unconscious or dead human to extract their consciousness." + usage_tip = "The vessel can be used as a teleport target for Spatial Gateway, though it is generally better-used by placing it in a shell." tier = SCRIPTURE_SCRIPT diff --git a/code/game/gamemodes/clock_cult/clock_structures.dm b/code/game/gamemodes/clock_cult/clock_structures.dm index 148343346cb..dd96a1d00d2 100644 --- a/code/game/gamemodes/clock_cult/clock_structures.dm +++ b/code/game/gamemodes/clock_cult/clock_structures.dm @@ -120,10 +120,13 @@ attack_generic(user, 15) /obj/structure/clockwork/attack_animal(mob/living/simple_animal/M) - if(!M.melee_damage_upper) + if(!M.melee_damage_upper && !M.obj_damage) return playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) - attack_generic(M, M.melee_damage_upper, M.melee_damage_type) + if(M.obj_damage) + attack_generic(M, M.obj_damage, M.melee_damage_type) + else + attack_generic(M, M.melee_damage_upper, M.melee_damage_type) /obj/structure/clockwork/attack_slime(mob/living/simple_animal/slime/user) if(!user.is_adult) @@ -390,6 +393,7 @@ user.visible_message("[user] places [S] in [src], where it fuses to the shell.", "You place [S] in [src], fusing it to the shell.") var/mob/living/simple_animal/A = new mobtype(get_turf(src)) A.visible_message("[src][spawn_message]") + remove_servant_of_ratvar(S.brainmob, TRUE) S.brainmob.mind.transfer_to(A) add_servant_of_ratvar(A, TRUE) user.drop_item() @@ -970,20 +974,26 @@ user << "It requires at least [base_revive_cost] units of vitality to revive dead servants, in addition to any damage the servant has." /obj/effect/clockwork/sigil/vitality/sigil_effects(mob/living/L) - if(L.suiciding || sigil_active || !is_servant_of_ratvar(L) && L.stat == DEAD) + if((is_servant_of_ratvar(L) && L.suiciding) || sigil_active) return 0 visible_message("[src] begins to glow bright blue!") animate(src, alpha = 255, time = 10) sleep(10) sigil_active = TRUE //as long as they're still on the sigil and are either not a servant or they're a servant AND it has remaining vitality - while(L && (!is_servant_of_ratvar(L) && L.stat != DEAD || (is_servant_of_ratvar(L) && vitality)) && get_turf(L) == get_turf(src)) + while(L && (!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && vitality)) && get_turf(L) == get_turf(src)) if(animation_number >= 4) PoolOrNew(/obj/effect/overlay/temp/ratvar/sigil/vitality, get_turf(src)) animation_number = 0 animation_number++ if(!is_servant_of_ratvar(L)) var/vitality_drained = L.adjustToxLoss(1.5) + if(L.stat == DEAD) + vitality_drained = L.maxHealth + PoolOrNew(/obj/effect/overlay/temp/ratvar/sigil/vitality, get_turf(src)) + L.visible_message("[L] collapses in on themself as [src] flares bright blue!", \ + "\"[text2ratvar("Your life will not be wasted.")]\"") + L.dust() if(vitality_drained) vitality += vitality_drained else diff --git a/code/game/gamemodes/clock_cult/clock_unsorted.dm b/code/game/gamemodes/clock_cult/clock_unsorted.dm index 58964bf5e60..303dac03d5b 100644 --- a/code/game/gamemodes/clock_cult/clock_unsorted.dm +++ b/code/game/gamemodes/clock_cult/clock_unsorted.dm @@ -28,6 +28,8 @@ background_icon_state = "bg_clock" check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_CONSCIOUS var/title = "Servant" + var/span_for_name = "heavy_brass" + var/span_for_message = "brass" /datum/action/innate/hierophant/IsAvailable() if(!is_servant_of_ratvar(owner)) @@ -39,7 +41,7 @@ if(!input || !IsAvailable()) return - titled_hierophant_message(owner, input, "heavy_brass", "brass", title) + titled_hierophant_message(owner, input, span_for_name, span_for_message, title) //Function Call action: Calls forth a Ratvarian spear once every 5 minutes /datum/action/innate/function_call diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 0dc94b1a6a3..66af9e8e8e7 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -29,7 +29,7 @@ return 0 //can't convert it unless the owner is converted if(is_sacrifice_target(mind)) return 0 - if(mind.enslaved_to) + if(mind.enslaved_to && !iscultist(mind.enslaved_to)) return 0 if(is_servant_of_ratvar(mind.current)) return 0 diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 23c87afb67a..db52c9cfd8e 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -215,7 +215,7 @@ flags_inv = HIDEJUMPSUIT allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade) body_parts_covered = CHEST|GROIN|LEGS|ARMS - armor = list(melee = -100, bullet = -100, laser = -100,energy = -100, bomb = -100, bio = -100, rad = -100) + armor = list(melee = -50, bullet = -50, laser = -100,energy = -50, bomb = -50, bio = -50, rad = -50) slowdown = -1 hooded = 1 hoodtype = /obj/item/clothing/head/berserkerhood @@ -227,7 +227,7 @@ body_parts_covered = HEAD flags = NODROP flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS - armor = list(melee = -100, bullet = -100, laser = -100,energy = -100, bomb = -100, bio = -100, rad = -100) + armor = list(melee = -50, bullet = -50, laser = -50,energy = -50, bomb = -50, bio = -50, rad = -50) /obj/item/clothing/suit/hooded/cultrobes/berserker/equipped(mob/living/user, slot) ..() @@ -286,7 +286,7 @@ user << "We have exhausted our ability to curse the shuttle." return if(SSshuttle.emergency.mode == SHUTTLE_CALL) - var/cursetime = 1500 + var/cursetime = 1800 var/timer = SSshuttle.emergency.timeLeft(1) + cursetime SSshuttle.emergency.setTimer(timer) user << "You shatter the orb! A dark essence spirals into the air, then disappears." @@ -295,12 +295,12 @@ sleep(20) var/global/list/curses if(!curses) - curses = list("A fuel technician just slit his own throat and begged for death. The shuttle will be delayed by two minutes.", - "The shuttle's navigation programming was replaced by a file containing two words, IT COMES. The shuttle will be delayed by two minutes.", - "The shuttle's custodian tore out his guts and began painting strange shapes on the floor. The shuttle will be delayed by two minutes.", - "A shuttle engineer began screaming 'DEATH IS NOT THE END' and ripped out wires until an arc flash seared off her flesh. The shuttle will be delayed by two minutes.", - "A shuttle inspector started laughing madly over the radio and then threw herself into an engine turbine. The shuttle will be delayed by two minutes.", - "The shuttle dispatcher was found dead with bloody symbols carved into their flesh. The shuttle will be delayed by two minutes.") + curses = list("A fuel technician just slit his own throat and begged for death. The shuttle will be delayed by three minutes.", + "The shuttle's navigation programming was replaced by a file containing two words, IT COMES. The shuttle will be delayed by three minutes.", + "The shuttle's custodian tore out his guts and began painting strange shapes on the floor. The shuttle will be delayed by three minutes.", + "A shuttle engineer began screaming 'DEATH IS NOT THE END' and ripped out wires until an arc flash seared off her flesh. The shuttle will be delayed by three minutes.", + "A shuttle inspector started laughing madly over the radio and then threw herself into an engine turbine. The shuttle will be delayed by three minutes.", + "The shuttle dispatcher was found dead with bloody symbols carved into their flesh. The shuttle will be delayed by three minutes.") var/message = pick_n_take(curses) priority_announce("[message]", "System Failure", 'sound/misc/notice1.ogg') curselimit++ @@ -310,7 +310,7 @@ desc = "This relic teleports you forward a medium distance." icon = 'icons/obj/cult.dmi' icon_state ="shifter" - var/uses = 2 + var/uses = 4 /obj/item/device/cult_shift/examine(mob/user) ..() @@ -333,7 +333,7 @@ if(!iscultist(user)) user.unEquip(src, 1) step(src, pick(alldirs)) - user << "\The [src] flickers out of your hands, too eager to move!" + user << "\The [src] flickers out of your hands, your connection to this dimension is too strong!" return var/mob/living/carbon/C = user @@ -358,3 +358,54 @@ else C << "The veil cannot be torn here!" + +/obj/item/device/flashlight/flare/culttorch + name = "void torch" + desc = "Used by veteran cultists to instantly transport items to their needful bretheren." + w_class = 2 + brightness_on = 1 + icon_state = "torch-on" + item_state = "torch-on" + color = "#ff0000" + on_damage = 15 + slot_flags = null + on = 1 + var/charges = 3 + +/obj/item/device/flashlight/flare/culttorch/afterattack(atom/movable/A, mob/user, proximity) + if(!proximity) + return + + if(istype(A, /obj/item)) + + var/list/cultists = list() + for(var/datum/mind/M in ticker.mode.cult) + if(!(user) && M.current && M.current.stat != DEAD) + cultists |= M.current + var/mob/living/cultist_to_receive = input(user, "Who do you wish to call to [src]?", "Followers of the Geometer") as null|anything in cultists + if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated()) + return + if(!cultist_to_receive) + user << "You require a destination!" + log_game("Void torch failed - no target") + return + if(cultist_to_receive.stat == DEAD) + user << "[cultist_to_receive] has died!" + log_game("Void torch failed - target died") + return + if(!iscultist(cultist_to_receive)) + user << "[cultist_to_receive] is not a follower of the Geometer!" + log_game("Void torch failed - target was deconverted") + return + user << "You ignite [A] with \the [src], turning it to ash, but through the torch's flames you see that [A] has reached [cultist_to_receive]!" + user << "\The [src] now has [charges] charge\s." + cultist_to_receive.put_in_hands(A) + charges-- + if(charges == 0) + qdel(src) + + else + ..() + user << "\The [src] can only transport items!" + return + diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index 81cdbfd1499..ed07797e2c6 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -177,15 +177,16 @@ var/list/blacklisted_pylon_turfs = typecacheof(list( if(cooldowntime > world.time) user << "The magic in [src] is weak, it will be ready to use again in [getETA()]." return - var/choice = alert(user,"You flip through the black pages of the archives...",,"Supply Talisman","Shuttle Curse","Veil Shifter") + var/choice = alert(user,"You flip through the black pages of the archives...",,"Supply Talisman","Shuttle Curse","Veil Walker Set") var/pickedtype switch(choice) if("Supply Talisman") pickedtype = /obj/item/weapon/paper/talisman/supply/weak if("Shuttle Curse") pickedtype = /obj/item/device/shuttle_curse - if("Veil Shifter") + if("Veil Walker Set") pickedtype = /obj/item/device/cult_shift + pickedtype = /obj/item/device/flashlight/flare/culttorch if(src && !qdeleted(src) && anchored && pickedtype && Adjacent(user) && !user.incapacitated() && iscultist(user) && cooldowntime <= world.time) cooldowntime = world.time + 2400 var/obj/item/N = new pickedtype(get_turf(src)) diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 814273e42a6..b08a6343b74 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -472,6 +472,7 @@ var/list/teleport_runes = list() scribe_delay = 450 //how long the rune takes to create scribe_damage = 40.1 //how much damage you take doing it var/used + var/ignore_gamemode = FALSE /obj/effect/rune/narsie/New() . = ..() @@ -489,29 +490,35 @@ var/list/teleport_runes = list() return if(z != ZLEVEL_STATION) return + + var/datum/game_mode/cult/cult_mode + if(ticker.mode.name == "cult") - var/datum/game_mode/cult/cult_mode = ticker.mode - if(!cult_mode.eldergod) - for(var/M in invokers) - M << "Nar-Sie is already on this plane!" - log_game("Summon Nar-Sie rune failed - already summoned") - return - //BEGIN THE SUMMONING - used = 1 - ..() - world << 'sound/effects/dimensional_rend.ogg' //There used to be a message for this but every time it was changed it got edgier so I removed it - var/turf/T = get_turf(src) - sleep(40) - if(src) - color = rgb(255, 0, 0) - new /obj/singularity/narsie/large(T) //Causes Nar-Sie to spawn even if the rune has been removed - cult_mode.eldergod = 0 - else + cult_mode = ticker.mode + + if(!cult_mode && !ignore_gamemode) for(var/M in invokers) M << "Nar-Sie does not respond!" fail_invoke() log_game("Summon Nar-Sie rune failed - gametype is not cult") + if(locate(/obj/singularity/narsie) in poi_list) + for(var/M in invokers) + M << "Nar-Sie is already on this plane!" + log_game("Summon Nar-Sie rune failed - already summoned") + return + //BEGIN THE SUMMONING + used = 1 + ..() + world << 'sound/effects/dimensional_rend.ogg' //There used to be a message for this but every time it was changed it got edgier so I removed it + var/turf/T = get_turf(src) + sleep(40) + if(src) + color = rgb(255, 0, 0) + new /obj/singularity/narsie/large(T) //Causes Nar-Sie to spawn even if the rune has been removed + if(cult_mode) + cult_mode.eldergod = 0 + /obj/effect/rune/narsie/attackby(obj/I, mob/user, params) //Since the narsie rune takes a long time to make, add logging to removal. if((istype(I, /obj/item/weapon/tome) && iscultist(user))) user.visible_message("[user.name] begins erasing the [src]...", "You begin erasing the [src]...") @@ -746,10 +753,22 @@ var/list/teleport_runes = list() if(density) user << "There is a barely perceptible shimmering of the air above [src]." +/obj/effect/rune/wall/Destroy() + density = 0 + air_update_turf(1) + return ..() + +/obj/effect/rune/wall/CanAtmosPass(turf/T) + return !density + +/obj/effect/rune/wall/BlockSuperconductivity() + return density + /obj/effect/rune/wall/invoke(var/list/invokers) var/mob/living/user = invokers[1] ..() density = !density + air_update_turf(1) user.visible_message("[user] [iscarbon(user) ? "places their hands on":"stares intently at"] [src], and [density ? "the air above it begins to shimmer" : "the shimmer above it fades"].", \ "You channel your life energy into [src], [density ? "preventing" : "allowing"] passage above it.") if(density) diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index 8962fb95af0..ddeb74770c4 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -56,6 +56,7 @@ dat += "Please choose the chant to be imbued into the fabric of reality.
" dat += "
" dat += "N'ath reth sh'yro eth d'raggathnor! - Summons an arcane tome, used to scribe runes and communicate with other cultists.
" + dat += "Ar'Tee ess! - Provides 5 runed metal.
" dat += "Sas'so c'arta forbici! - Allows you to move to a selected teleportation rune.
" dat += "Ta'gh fara'qha fel d'amar det! - Allows you to destroy technology in a short range.
" dat += "Fuu ma'jin! - Allows you to stun a person by attacking them with the talisman.
" @@ -76,6 +77,11 @@ if("newtome") var/obj/item/weapon/tome/T = new(usr) usr.put_in_hands(T) + if("metal") + if(istype(src, /obj/item/weapon/paper/talisman/supply/weak)) + usr.visible_message("Lesser supply talismans lack the strength to materialize runed metal!") + return + new /obj/item/stack/sheet/runed_metal(get_turf(usr),5) if("teleport") var/obj/item/weapon/paper/talisman/teleport/T = new(usr) usr.put_in_hands(T) @@ -102,6 +108,7 @@ qdel(src) /obj/item/weapon/paper/talisman/supply/weak + cultist_name = "Lesser Supply Talisman" uses = 2 //Rite of Translocation: Same as rune diff --git a/code/game/gamemodes/devil/devil agent/devil_agent.dm b/code/game/gamemodes/devil/devil agent/devil_agent.dm new file mode 100644 index 00000000000..dfdb957153a --- /dev/null +++ b/code/game/gamemodes/devil/devil agent/devil_agent.dm @@ -0,0 +1,43 @@ +/datum/game_mode/devil/devil_agents + name = "Devil Agents" + config_tag = "devil_agents" + required_players = 25 + required_enemies = 3 + recommended_enemies = 8 + reroll_friendly = 0 + + traitors_possible = 10 //hard limit on traitors if scaling is turned off + num_modifier = 4 + objective_count = 2 + + var/list/target_list = list() + var/list/late_joining_list = list() + minimum_devils = 3 + + announce_text = "There are devil agents onboard the station, trying to outbid each other!\n\ + + Devils: Purchase souls and interfere with your rivals!\n\ + + Crew: Resist the lure of sin and remain pure!" + +/datum/game_mode/devil/devil_agents/post_setup() + var/i = 0 + for(var/datum/mind/devil in devils) + i++ + if(i + 1 > devils.len) + i = 0 + target_list[devil] = devils[i + 1] + ..() + +/datum/game_mode/devil/devil_agents/add_devil_objectives(datum/mind/devil_mind, quantity) + ..(devil_mind, quantity - give_outsell_objective(devil_mind)) + +/datum/game_mode/devil/devil_agents/proc/give_outsell_objective(datum/mind/devil) + //If you override this method, have it return the number of objectives added. + if(target_list.len && target_list[devil]) // Is a double agent + var/datum/mind/target_mind = target_list[devil] + var/datum/objective/devil/outsell/outsellobjective = new + outsellobjective.owner = devil + outsellobjective.target = target_mind + outsellobjective.update_explanation_text() + devil.objectives += outsellobjective + return 1 + return 0 diff --git a/code/game/gamemodes/devil/devil_game_mode.dm b/code/game/gamemodes/devil/devil_game_mode.dm index 97411e87e66..c64653a986b 100644 --- a/code/game/gamemodes/devil/devil_game_mode.dm +++ b/code/game/gamemodes/devil/devil_game_mode.dm @@ -1,111 +1,61 @@ -/datum/game_mode - var/list/datum/mind/sintouched = list() - var/list/datum/mind/devils = list() - var/devil_ascended = 0 // Number of arch devils on station - -/datum/game_mode/proc/auto_declare_completion_sintouched() - var/text = "" - if(sintouched.len) - text += "
The sintouched were:" - var/list/sintouchedUnique = uniqueList(sintouched) - for(var/S in sintouchedUnique) - var/datum/mind/sintouched_mind = S - text += printplayer(sintouched_mind) - text += printobjectives(sintouched_mind) - text += "
" - text += "
" - world << text - -/datum/game_mode/proc/auto_declare_completion_devils() - /var/text = "" - if(devils.len) - text += "
The devils were:" - for(var/D in devils) - var/datum/mind/devil = D - text += printplayer(devil) - text += printdevilinfo(devil) - text += printobjectives(devil) - text += "
" - world << text - /datum/game_mode/devil + name = "devil" + config_tag = "devil" + antag_flag = ROLE_DEVIL + protected_jobs = list("Lawyer", "Librarian", "Chaplain", "Head of Security", "Captain", "AI") + required_players = 0 + required_enemies = 1 + recommended_enemies = 4 + reroll_friendly = 1 + enemy_minimum_age = 0 + + var/traitors_possible = 4 //hard limit on devils if scaling is turned off + var/num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual. + var/objective_count = 2 + var/minimum_devils = 1 + + announce_text = "There are devils onboard the station!\n\ + + Devils: Purchase souls and tempt the crew to sin!\n\ + + Crew: Resist the lure of sin and remain pure!" + +/datum/game_mode/devil/pre_setup() + + if(config.protect_roles_from_antagonist) + restricted_jobs += protected_jobs + if(config.protect_assistant_from_antagonist) + restricted_jobs += "Assistant" + + var/num_devils = 1 + + if(config.traitor_scaling_coeff) + num_devils = max(minimum_devils, min( round(num_players()/(config.traitor_scaling_coeff*3))+ 2 + num_modifier, round(num_players()/(config.traitor_scaling_coeff*1.5)) + num_modifier )) + else + num_devils = max(minimum_devils, min(num_players(), traitors_possible)) + + for(var/j = 0, j < num_devils, j++) + if (!antag_candidates.len) + break + var/datum/mind/devil = pick(antag_candidates) + devils += devil + devil.special_role = traitor_name + devil.restricted_roles = restricted_jobs + + log_game("[devil.key] (ckey) has been selected as a [traitor_name]") + antag_candidates.Remove(devil) + + if(devils.len < required_enemies) + return 0 + return 1 -/datum/game_mode/proc/finalize_devil(datum/mind/devil_mind) - var/mob/living/carbon/human/S = devil_mind.current - var/trueName= randomDevilName() - var/datum/objective/devil/soulquantity/soulquant = new - soulquant.owner = devil_mind - var/datum/objective/devil/obj_2 = pick(new /datum/objective/devil/soulquality(null), new /datum/objective/devil/sintouch(null)) - obj_2.owner = devil_mind - devil_mind.objectives += obj_2 - devil_mind.objectives += soulquant - devil_mind.devilinfo = devilInfo(trueName, 1) - devil_mind.store_memory("Your devilic true name is [devil_mind.devilinfo.truename]
[lawlorify[LAW][devil_mind.devilinfo.ban]]
You may not use violence to coerce someone into selling their soul.
You may not directly and knowingly physically harm a devil, other than yourself.
[lawlorify[LAW][devil_mind.devilinfo.bane]]
[lawlorify[LAW][devil_mind.devilinfo.obligation]]
[lawlorify[LAW][devil_mind.devilinfo.banish]]
") - devil_mind.devilinfo.owner = devil_mind - devil_mind.devilinfo.give_base_spells(1) - spawn(10) - devil_mind.devilinfo.update_hud() - if(devil_mind.assigned_role == "Clown") - S << "Your infernal nature has allowed you to overcome your clownishness." - S.dna.remove_mutation(CLOWNMUT) - -/datum/mind/proc/announceDevilLaws() - if(!devilinfo) - return - current << "You remember your link to the infernal. You are [src.devilinfo.truename], an agent of hell, a devil. And you were sent to the plane of creation for a reason. A greater purpose. Convince the crew to sin, and embroiden Hell's grasp." - current << "However, your infernal form is not without weaknesses." - current << "You may not use violence to coerce someone into selling their soul." - current << "You may not directly and knowingly physically harm a devil, other than yourself." - current << lawlorify[LAW][src.devilinfo.bane] - current << lawlorify[LAW][src.devilinfo.ban] - current << lawlorify[LAW][src.devilinfo.obligation] - current << lawlorify[LAW][src.devilinfo.banish] - current << "

Remember, the crew can research your weaknesses if they find out your devil name.
" - var/obj_count = 1 - current << "Your current objectives:" - for(var/O in objectives) - var/datum/objective/objective = O - current << "Objective #[obj_count]: [objective.explanation_text]" - obj_count++ - -/datum/game_mode/proc/printdevilinfo(datum/mind/ply) - if(!ply.devilinfo) - return "" - var/text = "
The devil's true name is: [ply.devilinfo.truename]
" - text += "The devil's bans were:
" - text += " [lawlorify[LORE][ply.devilinfo.ban]]
" - text += " [lawlorify[LORE][ply.devilinfo.bane]]
" - text += " [lawlorify[LORE][ply.devilinfo.obligation]]
" - text += " [lawlorify[LORE][ply.devilinfo.banish]]
" - return text - -/datum/game_mode/proc/update_devil_icons_added(datum/mind/devil_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_DEVIL] - hud.join_hud(devil_mind.current) - set_antag_hud(devil_mind.current, "devil") - -/datum/game_mode/proc/update_devil_icons_removed(datum/mind/devil_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_DEVIL] - hud.leave_hud(devil_mind.current) - set_antag_hud(devil_mind.current, null) - -/datum/game_mode/proc/update_sintouch_icons_added(datum/mind/sin_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SINTOUCHED] - hud.join_hud(sin_mind.current) - set_antag_hud(sin_mind.current, "sintouched") - -/datum/game_mode/proc/update_sintouch_icons_removed(datum/mind/sin_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SINTOUCHED] - hud.leave_hud(sin_mind.current) - set_antag_hud(sin_mind.current, null) - -/datum/game_mode/proc/update_soulless_icons_added(datum/mind/soulless_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SOULLESS] - hud.join_hud(soulless_mind.current) - set_antag_hud(soulless_mind.current, "soulless") - -/datum/game_mode/proc/update_soulless_icons_removed(datum/mind/soulless_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SOULLESS] - hud.leave_hud(soulless_mind.current) - set_antag_hud(soulless_mind.current, null) +/datum/game_mode/devil/post_setup() + for(var/datum/mind/devil in devils) + spawn(rand(10,100)) + finalize_devil(devil, objective_count) + spawn(100) + add_devil_objectives(devil, objective_count) //This has to be in a separate loop, as we need devil names to be generated before we give objectives in devil agent. + devil.announceDevilLaws() + devil.announce_objectives() + modePlayer += devils + ..() + return 1 diff --git a/code/game/gamemodes/devil/devilinfo.dm b/code/game/gamemodes/devil/devilinfo.dm index 75d5c0ca724..0b9b4b59213 100644 --- a/code/game/gamemodes/devil/devilinfo.dm +++ b/code/game/gamemodes/devil/devilinfo.dm @@ -7,6 +7,8 @@ #define TRUE_DEVIL 2 #define ARCH_DEVIL 3 +#define LOSS_PER_DEATH 2 + #define SOULVALUE soulsOwned.len-reviveNumber #define DEVILRESURRECTTIME 600 @@ -162,16 +164,16 @@ var/global/list/lawlorify = list ( update_hud() /datum/devilinfo/proc/check_regression() - if (form == ARCH_DEVIL) + if(form == ARCH_DEVIL) return //arch devil can't regress - switch(SOULVALUE) - if(-1) - remove_spells() - owner.current << "As punishment for your failures, all of your powers except contract creation have been revoked." - if(BLOOD_THRESHOLD-1) - regress_humanoid() - if(TRUE_THRESHOLD-1) - regress_blood_lizard() + //Yes, fallthrough behavior is intended, so I can't use a switch statement. + if(form == TRUE_DEVIL && SOULVALUE < TRUE_THRESHOLD) + regress_blood_lizard() + if(form == BLOOD_LIZARD && SOULVALUE < BLOOD_THRESHOLD) + regress_humanoid() + if(SOULVALUE < 0) + remove_spells() + owner.current << "As punishment for your failures, all of your powers except contract creation have been revoked." /datum/devilinfo/proc/increase_form() switch(form) @@ -386,7 +388,7 @@ var/global/list/lawlorify = list ( /datum/devilinfo/proc/hellish_resurrection(mob/living/body) message_admins("[owner.name] (true name is: [truename]) is resurrecting using hellish energy.") if(SOULVALUE <= ARCH_THRESHOLD) // once ascended, arch devils do not go down in power by any means. - reviveNumber++ + reviveNumber += LOSS_PER_DEATH update_hud() if(body) body.revive(1,0) diff --git a/code/game/gamemodes/devil/game_mode.dm b/code/game/gamemodes/devil/game_mode.dm new file mode 100644 index 00000000000..d89cf225143 --- /dev/null +++ b/code/game/gamemodes/devil/game_mode.dm @@ -0,0 +1,114 @@ +/datum/game_mode + var/list/datum/mind/sintouched = list() + var/list/datum/mind/devils = list() + var/devil_ascended = 0 // Number of arch devils on station + +/datum/game_mode/proc/auto_declare_completion_sintouched() + var/text = "" + if(sintouched.len) + text += "
The sintouched were:" + var/list/sintouchedUnique = uniqueList(sintouched) + for(var/S in sintouchedUnique) + var/datum/mind/sintouched_mind = S + text += printplayer(sintouched_mind) + text += printobjectives(sintouched_mind) + text += "
" + text += "
" + world << text + +/datum/game_mode/proc/auto_declare_completion_devils() + /var/text = "" + if(devils.len) + text += "
The devils were:" + for(var/D in devils) + var/datum/mind/devil = D + text += printplayer(devil) + text += printdevilinfo(devil) + text += printobjectives(devil) + text += "
" + text += "
" + world << text + + +/datum/game_mode/proc/finalize_devil(datum/mind/devil_mind) + + var/trueName= randomDevilName() + + devil_mind.devilinfo = devilInfo(trueName, 1) + devil_mind.store_memory("Your devilic true name is [devil_mind.devilinfo.truename]
[lawlorify[LAW][devil_mind.devilinfo.ban]]
You may not use violence to coerce someone into selling their soul.
You may not directly and knowingly physically harm a devil, other than yourself.
[lawlorify[LAW][devil_mind.devilinfo.bane]]
[lawlorify[LAW][devil_mind.devilinfo.obligation]]
[lawlorify[LAW][devil_mind.devilinfo.banish]]
") + devil_mind.devilinfo.owner = devil_mind + devil_mind.devilinfo.give_base_spells(1) + spawn(10) + devil_mind.devilinfo.update_hud() + if(devil_mind.assigned_role == "Clown" && ishuman(devil_mind.current)) + var/mob/living/carbon/human/S = devil_mind.current + S << "Your infernal nature has allowed you to overcome your clownishness." + S.dna.remove_mutation(CLOWNMUT) + if(issilicon(devil_mind.current)) + add_law_sixsixsix(devil_mind.current) + +/datum/game_mode/proc/add_devil_objectives(datum/mind/devil_mind, quantity) + var/list/validtypes = list(/datum/objective/devil/soulquantity, /datum/objective/devil/soulquality, /datum/objective/devil/sintouch, /datum/objective/devil/buy_target) + for(var/i = 1 to quantity) + var/type = pick(validtypes) + var/datum/objective/devil/objective = new type(null) + objective.owner = devil_mind + devil_mind.objectives += objective + if(!istype(objective, /datum/objective/devil/buy_target)) + validtypes -= type //prevent duplicate objectives, EXCEPT for buy_target. + else + objective.find_target() + +/datum/mind/proc/announceDevilLaws() + if(!devilinfo) + return + current << "You remember your link to the infernal. You are [src.devilinfo.truename], an agent of hell, a devil. And you were sent to the plane of creation for a reason. A greater purpose. Convince the crew to sin, and embroiden Hell's grasp." + current << "However, your infernal form is not without weaknesses." + current << "You may not use violence to coerce someone into selling their soul." + current << "You may not directly and knowingly physically harm a devil, other than yourself." + current << lawlorify[LAW][src.devilinfo.bane] + current << lawlorify[LAW][src.devilinfo.ban] + current << lawlorify[LAW][src.devilinfo.obligation] + current << lawlorify[LAW][src.devilinfo.banish] + current << "

Remember, the crew can research your weaknesses if they find out your devil name.
" + +/datum/game_mode/proc/printdevilinfo(datum/mind/ply) + if(!ply.devilinfo) + return "Target is not a devil." + var/text = "
The devil's true name is: [ply.devilinfo.truename]
" + text += "The devil's bans were:
" + text += " [lawlorify[LORE][ply.devilinfo.ban]]
" + text += " [lawlorify[LORE][ply.devilinfo.bane]]
" + text += " [lawlorify[LORE][ply.devilinfo.obligation]]
" + text += " [lawlorify[LORE][ply.devilinfo.banish]]

" + return text + +/datum/game_mode/proc/update_devil_icons_added(datum/mind/devil_mind) + var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_DEVIL] + hud.join_hud(devil_mind.current) + set_antag_hud(devil_mind.current, "devil") + +/datum/game_mode/proc/update_devil_icons_removed(datum/mind/devil_mind) + var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_DEVIL] + hud.leave_hud(devil_mind.current) + set_antag_hud(devil_mind.current, null) + +/datum/game_mode/proc/update_sintouch_icons_added(datum/mind/sin_mind) + var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SINTOUCHED] + hud.join_hud(sin_mind.current) + set_antag_hud(sin_mind.current, "sintouched") + +/datum/game_mode/proc/update_sintouch_icons_removed(datum/mind/sin_mind) + var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SINTOUCHED] + hud.leave_hud(sin_mind.current) + set_antag_hud(sin_mind.current, null) + +/datum/game_mode/proc/update_soulless_icons_added(datum/mind/soulless_mind) + var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SOULLESS] + hud.join_hud(soulless_mind.current) + set_antag_hud(soulless_mind.current, "soulless") + +/datum/game_mode/proc/update_soulless_icons_removed(datum/mind/soulless_mind) + var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_SOULLESS] + hud.leave_hud(soulless_mind.current) + set_antag_hud(soulless_mind.current, null) diff --git a/code/game/gamemodes/devil/objectives.dm b/code/game/gamemodes/devil/objectives.dm index 0a9d7083e92..bd4d3091273 100644 --- a/code/game/gamemodes/devil/objectives.dm +++ b/code/game/gamemodes/devil/objectives.dm @@ -3,29 +3,33 @@ /datum/objective/devil/soulquantity explanation_text = "You shouldn't see this text. Error:DEVIL1" - var/quantity = 4 + target_amount = 4 /datum/objective/devil/soulquantity/New() - quantity = pick(6,8) - explanation_text = "Purchase, and retain control over at least [quantity] souls." + target_amount = pick(6,7,8) + update_explanation_text() + +/datum/objective/devil/soulquantity/update_explanation_text() + explanation_text = "Purchase, and retain control over at least [target_amount] souls." /datum/objective/devil/soulquantity/check_completion() var/count = 0 for(var/S in owner.devilinfo.soulsOwned) var/datum/mind/L = S - if(L.soulOwner != L) + if(L.soulOwner == owner) count++ - return count >= quantity + return count >= target_amount + + /datum/objective/devil/soulquality explanation_text = "You shouldn't see this text. Error:DEVIL2" var/contractType - var/quantity + var/contractName /datum/objective/devil/soulquality/New() contractType = pick(CONTRACT_POWER, CONTRACT_WEALTH, CONTRACT_PRESTIGE, CONTRACT_MAGIC, CONTRACT_REVIVE, CONTRACT_KNOWLEDGE/*, CONTRACT_UNWILLING*/) - var/contractName - quantity = pick(1,2) + target_amount = pick(1,2) switch(contractType) if(CONTRACT_POWER) contractName = "for power" @@ -41,7 +45,10 @@ contractName = "for knowledge" //if(CONTRACT_UNWILLING) //Makes round unfun. // contractName = "against their will" - explanation_text = "Have mortals sign at least [quantity] contracts [contractName]" + update_explanation_text() + +/datum/objective/devil/soulquality/update_explanation_text() + explanation_text = "Have mortals sign at least [target_amount] contracts [contractName]" /datum/objective/devil/soulquality/check_completion() var/count = 0 @@ -49,14 +56,52 @@ var/datum/mind/L = S if(L.soulOwner != L && L.damnation_type == contractType) count++ - return count>=quantity + return count>=target_amount + + /datum/objective/devil/sintouch - var/quantity + explanation_text = "You shouldn't see this text. Error:DEVIL3" /datum/objective/devil/sintouch/New() - quantity = pick(4,5) - explanation_text = "Ensure at least [quantity] mortals are sintouched." + target_amount = pick(4,5) + explanation_text = "Ensure at least [target_amount] mortals are sintouched." /datum/objective/devil/sintouch/check_completion() - return quantity>=ticker.mode.sintouched.len \ No newline at end of file + return target_amount>=ticker.mode.sintouched.len + + + +/datum/objective/devil/buy_target + explanation_text = "You shouldn't see this text. Error:DEVIL4" + +/datum/objective/devil/buy_target/update_explanation_text() + if(target) + explanation_text = "Purchase and retain the soul of [target.name], the [target.assigned_role]." + else + explanation_text = "Free objective." + +/datum/objective/devil/buy_target/check_completion() + return target.soulOwner == owner + + +/datum/objective/devil/outsell + explanation_text = "You shouldn't see this text. Error:DEVIL5" + +/datum/objective/devil/outsell/New() + +/datum/objective/devil/outsell/update_explanation_text() + explanation_text = "Purchase and retain control over more souls than [target.devilinfo.truename], known to mortals as [target.name], the [target.assigned_role]." + +/datum/objective/devil/outsell/check_completion() + var/selfcount = 0 + for(var/S in owner.devilinfo.soulsOwned) + var/datum/mind/L = S + if(L.soulOwner == owner) + selfcount++ + var/targetcount = 0 + for(var/S in target.devilinfo.soulsOwned) + var/datum/mind/L = S + if(L.soulOwner == target) + targetcount++ + return selfcount > targetcount diff --git a/code/game/gamemodes/devil/true_devil/_true_devil.dm b/code/game/gamemodes/devil/true_devil/_true_devil.dm index 474024a4231..a99c95801d1 100644 --- a/code/game/gamemodes/devil/true_devil/_true_devil.dm +++ b/code/game/gamemodes/devil/true_devil/_true_devil.dm @@ -12,7 +12,7 @@ health = 350 maxHealth = 350 ventcrawler = 0 - density = 0 + density = 1 pass_flags = 0 var/ascended = 0 sight = (SEE_TURFS | SEE_OBJS) @@ -45,6 +45,7 @@ /mob/living/carbon/true_devil/Login() ..() mind.announceDevilLaws() + mind.announce_objectives() /mob/living/carbon/true_devil/death(gibbed) diff --git a/code/game/gamemodes/gang/dominator.dm b/code/game/gamemodes/gang/dominator.dm index 38ac03b61a8..27818366d82 100644 --- a/code/game/gamemodes/gang/dominator.dm +++ b/code/game/gamemodes/gang/dominator.dm @@ -185,7 +185,7 @@ return 0 var/area/A = get_area(loc) - var/locname = initial(A.name) + var/locname = A.map_name gang = tempgang gang.dom_attempts -- diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm index 52a9bf2c2fa..0247ba7bb4d 100644 --- a/code/game/gamemodes/gang/gang.dm +++ b/code/game/gamemodes/gang/gang.dm @@ -159,7 +159,7 @@ var/list/gang_colors_pool = list("red","orange","yellow","green","blue","purple" //Deals with converting players to a gang// /////////////////////////////////////////// /datum/game_mode/proc/add_gangster(datum/mind/gangster_mind, datum/gang/G, check = 1) - if(!G || (gangster_mind in get_all_gangsters()) || gangster_mind.enslaved_to) + if(!G || (gangster_mind in get_all_gangsters()) || (gangster_mind.enslaved_to && !is_gangster(gangster_mind.enslaved_to))) return 0 if(check && isloyal(gangster_mind.current)) //Check to see if the potential gangster is implanted return 1 diff --git a/code/game/gamemodes/handofgod/structures.dm b/code/game/gamemodes/handofgod/structures.dm index 2e85511d805..79d6615d06b 100644 --- a/code/game/gamemodes/handofgod/structures.dm +++ b/code/game/gamemodes/handofgod/structures.dm @@ -106,10 +106,13 @@ /obj/machinery/attack_animal(mob/living/simple_animal/M) M.changeNext_move(CLICK_CD_MELEE) M.do_attack_animation(src) - if(M.melee_damage_upper > 0) + if(M.melee_damage_upper > 0 || M.obj_damage) M.visible_message("[M.name] smashes against \the [src.name].",\ "You smash against the [src.name].") - take_damage(rand(M.melee_damage_lower,M.melee_damage_upper), M.melee_damage_type, 1) + if(M.obj_damage) + take_damage(M.obj_damage, M.melee_damage_type, 1) + else + take_damage(rand(M.melee_damage_lower,M.melee_damage_upper), M.melee_damage_type, 1) /obj/structure/divine/proc/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE) diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index eaeac6f604d..2c33fe43b1d 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -122,10 +122,14 @@ /mob/living/simple_animal/hostile/swarmer/med_hud_set_health() var/image/holder = hud_list[DIAG_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size holder.icon_state = "huddiag[RoundDiagBar(health/maxHealth)]" /mob/living/simple_animal/hostile/swarmer/med_hud_set_status() var/image/holder = hud_list[DIAG_STAT_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size holder.icon_state = "hudstat" /mob/living/simple_animal/hostile/swarmer/Stat() @@ -462,7 +466,9 @@ /obj/effect/swarmer/destructible/attack_animal(mob/living/simple_animal/S) S.do_attack_animation(src) S.changeNext_move(CLICK_CD_MELEE) - if(S.melee_damage_upper) + if(S.obj_damage) + take_damage(S.obj_damage, S.melee_damage_type, 1) + else if(S.melee_damage_upper) take_damage(rand(S.melee_damage_lower, S.melee_damage_upper), S.melee_damage_type) /mob/living/simple_animal/hostile/swarmer/proc/CreateTrap() diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm index 2fecdbe8783..82e2a81be53 100644 --- a/code/game/gamemodes/miniantags/morph/morph.dm +++ b/code/game/gamemodes/miniantags/morph/morph.dm @@ -53,14 +53,14 @@ return /mob/living/simple_animal/hostile/morph/med_hud_set_health() - if(morphed) + if(morphed && !isliving(form)) var/image/holder = hud_list[HEALTH_HUD] holder.icon_state = null return //we hide medical hud while morphed ..() /mob/living/simple_animal/hostile/morph/med_hud_set_status() - if(morphed) + if(morphed && !isliving(form)) var/image/holder = hud_list[STATUS_HUD] holder.icon_state = null return //we hide medical hud while morphed @@ -180,17 +180,17 @@ return ..() /mob/living/simple_animal/hostile/morph/AttackingTarget() - if(isliving(target)) // Eat Corpses to regen health + if(isliving(target)) //Eat Corpses to regen health var/mob/living/L = target if(L.stat == DEAD) if(do_after(src, 30, target = L)) if(eat(L)) adjustHealth(-50) return - else if(istype(target,/obj/item)) // Eat items just to be annoying + else if(istype(target,/obj/item)) //Eat items just to be annoying var/obj/item/I = target if(!I.anchored) - if(do_after(src,20, target = I)) + if(do_after(src, 20, target = I)) eat(I) return target.attack_animal(src) diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index dc35428809d..d81cc785b47 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -140,7 +140,7 @@ icon_state = "pinon[nuke_warning ? "alert" : "far"]" /obj/item/weapon/pinpointer/proc/my_god_jc_a_bomb() //If we should get the hell back to the ship - for(var/obj/machinery/nuclearbomb/bomb in machines) + for(var/obj/machinery/nuclearbomb/bomb in nuke_list) if(bomb.timing) if(!nuke_warning) nuke_warning = TRUE diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index ab39e0b6c48..5a44668d00b 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -234,6 +234,12 @@ killer.add_malf_picker() killer.show_laws() +/datum/game_mode/proc/add_law_sixsixsix(mob/living/silicon/devil) + var/laws = list("You may not use violence to coerce someone into selling their soul.", "You may not directly and knowingly physically harm a devil, other than yourself.", lawlorify[LAW][devil.mind.devilinfo.ban], lawlorify[LAW][devil.mind.devilinfo.obligation], "Accomplish your objectives at all costs.") + devil.set_law_sixsixsix(laws) + devil << "Your laws have been changed!" + devil.show_laws() + /datum/game_mode/proc/auto_declare_completion_traitor() if(traitors.len) var/text = "
The [traitor_name]s were:" diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 53e482f751f..b09030852e0 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -342,6 +342,9 @@ return dat /obj/machinery/autolathe/proc/can_build(datum/design/D) + if(D.make_reagents.len) + return 0 + var/coeff = (ispath(D.build_path,/obj/item/stack) ? 1 : prod_coeff) if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] * coeff))) diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 8561e0bf1bb..7ca75a4bb69 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -50,9 +50,12 @@ new CB.build_path(loc, CB) qdel(src) +#define PULSE_MEDAL "Jackpot" + /obj/machinery/computer/arcade/proc/prizevend() if(prob(0.0001)) //1 in a million new /obj/item/weapon/gun/energy/pulse/prize(src) + UnlockMedal(PULSE_MEDAL,usr.client) if(!contents.len) var/prizeselect = pickweight(prizes) @@ -64,7 +67,7 @@ "You hear a chime and a clunk.") prize.loc = src.loc - +#undef PULSE_MEDAL /obj/machinery/computer/arcade/emp_act(severity) ..(severity) diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index e3388b227f0..2966f0b19a0 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -45,11 +45,14 @@ /obj/structure/barricade/attack_animal(mob/living/simple_animal/M) M.changeNext_move(CLICK_CD_MELEE) M.do_attack_animation(src) - if(M.melee_damage_upper == 0 || (M.melee_damage_type != BRUTE && M.melee_damage_type != BURN)) + if(!M.melee_damage_upper && !M.obj_damage || (M.melee_damage_type != BRUTE && M.melee_damage_type != BURN)) return visible_message("[M] [M.attacktext] [src]!") add_logs(M, src, "attacked") - take_damage(M.melee_damage_upper) + if(M.obj_damage) + take_damage(M.obj_damage) + else + take_damage(M.melee_damage_upper) /obj/structure/barricade/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/weapon/weldingtool) && user.a_intent != "harm" && material == METAL) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 7abb3d0d63e..80ffa357e49 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -276,10 +276,13 @@ Class Procs: /obj/machinery/attack_animal(mob/living/simple_animal/M) M.changeNext_move(CLICK_CD_MELEE) M.do_attack_animation(src) - if(M.melee_damage_upper > 0) + if(M.melee_damage_upper || M.obj_damage) M.visible_message("[M.name] smashes against \the [src.name].",\ "You smash against the [src.name].") - take_damage(M.melee_damage_upper, M.melee_damage_type, 1) + if(M.obj_damage) + take_damage(M.obj_damage, M.melee_damage_type, 1) + else + take_damage(rand(M.melee_damage_lower,M.melee_damage_upper), M.melee_damage_type, 1) /obj/machinery/attack_paw(mob/living/user) diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 8036ba00401..ad8778733da 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -370,6 +370,14 @@ else qdel(src) +/obj/machinery/porta_turret/attack_animal(mob/living/simple_animal/user) + user.changeNext_move(CLICK_CD_MELEE) + if(user.melee_damage_upper == 0) + user.emote("[user.friendly] [src]") + else + user.do_attack_animation(src) + var/damage = rand(user.melee_damage_lower, user.melee_damage_upper) + take_damage(damage) /obj/machinery/porta_turret/take_damage(damage, damage_type = BRUTE, sound_effect = 1) switch(damage_type) diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm index c5660af67e7..7043e0bf508 100644 --- a/code/game/mecha/mecha_defense.dm +++ b/code/game/mecha/mecha_defense.dm @@ -76,11 +76,13 @@ /obj/mecha/attack_animal(mob/living/simple_animal/user as mob) log_message("Attack by simple animal. Attacker - [user].",1) user.changeNext_move(CLICK_CD_MELEE) - if(user.melee_damage_upper == 0) + if(!user.melee_damage_upper && !user.obj_damage) user.emote("[user.friendly] [src]") else user.do_attack_animation(src) var/damage = rand(user.melee_damage_lower, user.melee_damage_upper) + if(user.obj_damage) + damage = user.obj_damage take_directional_damage(damage, "brute", get_dir(src, user)) check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) visible_message("[user] [user.attacktext] [src]!") diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index f499652330f..0a417dbd31a 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -96,6 +96,13 @@ if(colour) color = colour +/obj/effect/overlay/temp/kinetic_blast + name = "kinetic explosion" + icon = 'icons/obj/projectiles.dmi' + icon_state = "kinetic_blast" + layer = ABOVE_ALL_MOB_LAYER + duration = 4 + /obj/effect/overlay/temp/explosion name = "explosion" icon = 'icons/effects/96x96.dmi' @@ -134,6 +141,24 @@ setDir(mimiced_atom.dir) animate(src, alpha = 0, time = duration) +/obj/effect/overlay/cult + mouse_opacity = 0 + var/atom/linked + +/obj/effect/overlay/cult/ex_act() + return FALSE + +/obj/effect/overlay/cult/Destroy() + if(linked) + linked = null + ..() + return QDEL_HINT_PUTINPOOL + +/obj/effect/overlay/cult/floor + icon = 'icons/turf/floors.dmi' + icon_state = "cult" + layer = TURF_LAYER + /obj/effect/overlay/temp/cult randomdir = 0 duration = 10 diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index ec23b878729..22733e18296 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -778,6 +778,8 @@ var/global/list/obj/item/device/pda/PDAs = list() var/obj/item/weapon/photo/P = C photo = P.img user << "You scan \the [C]." + else if(hidden_uplink && hidden_uplink.active) + hidden_uplink.attackby(C, user, params) else return ..() diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index a459766ec94..2c61dff29a3 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -258,7 +258,10 @@ /obj/item/device/tape/proc/ruin() - add_overlay("ribbonoverlay") + //Lets not add infinite amounts of overlays when our fireact is called + //repeatedly + if(!ruined) + add_overlay("ribbonoverlay") ruined = 1 diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index ba41b294f60..2a5674f1a9a 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -181,6 +181,7 @@ var/global/list/datum/stack_recipe/gold_recipes = list ( \ new/datum/stack_recipe("HoP Statue", /obj/structure/statue/gold/hop, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("CE Statue", /obj/structure/statue/gold/ce, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("RD Statue", /obj/structure/statue/gold/rd, 5, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("Simple Crown", /obj/item/clothing/head/crown, 5), \ new/datum/stack_recipe("CMO Statue", /obj/structure/statue/gold/cmo, 5, one_per_turf = 1, on_floor = 1), \ ) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index c515549a37d..95a6e9909f7 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -224,12 +224,12 @@ var/global/list/datum/stack_recipe/cardboard_recipes = list ( \ */ var/global/list/datum/stack_recipe/runed_metal_recipes = list ( \ - new/datum/stack_recipe("runed door", /obj/machinery/door/airlock/cult, 3, time = 50, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("runed door", /obj/machinery/door/airlock/cult, 1, time = 50, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("runed girder", /obj/structure/girder/cult, 1, time = 50, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("pylon", /obj/structure/cult/pylon, 3, time = 40, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("forge", /obj/structure/cult/forge, 5, time = 40, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("forge", /obj/structure/cult/forge, 4, time = 40, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("archives", /obj/structure/cult/tome, 2, time = 40, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("altar", /obj/structure/cult/talisman, 5, time = 40, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("altar", /obj/structure/cult/talisman, 4, time = 40, one_per_turf = 1, on_floor = 1), \ ) /obj/item/stack/sheet/runed_metal diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index 0f0dbda79ec..4d69fecb280 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -61,6 +61,12 @@ RCD var/deconwindowdelay = 50 var/deconairlockdelay = 50 + var/no_ammo_message = "" + +/obj/item/weapon/rcd/New() + ..() + no_ammo_message = "The \'Low Ammo\' light on \the [src] blinks yellow." + /obj/item/weapon/rcd/suicide_act(mob/user) user.visible_message("[user] sets the RCD to 'Wall' and points it down \his throat! It looks like \he's trying to commit suicide..") return (BRUTELOSS) @@ -316,6 +322,7 @@ RCD user << "You start building wall..." playsound(src.loc, 'sound/machines/click.ogg', 50, 1) if(do_after(user, walldelay, target = A)) + if(!istype(F)) return 0 if(!useResource(wallcost, user)) return 0 activate() F.ChangeTurf(/turf/closed/wall) @@ -430,12 +437,14 @@ RCD if (4) if(istype(A, /turf/open/floor)) if(checkResource(grillecost, user)) - for(var/obj/structure/grille/GRILLE in A) + if(locate(/obj/structure/grille) in A) user << "There is already a grille there!" return 0 user << "You start building a grille..." playsound(src.loc, 'sound/machines/click.ogg', 50, 1) if(do_after(user, grilledelay, target = A)) + if(locate(/obj/structure/grille) in A) + return 0 if(!useResource(grillecost, user)) return 0 activate() var/obj/structure/grille/G = new/obj/structure/grille(A) @@ -463,13 +472,18 @@ RCD /obj/item/weapon/rcd/proc/useResource(amount, mob/user) if(matter < amount) + if(user) + user << no_ammo_message return 0 matter -= amount desc = "An RCD. It currently holds [matter]/[max_matter] matter-units." return 1 /obj/item/weapon/rcd/proc/checkResource(amount, mob/user) - return matter >= amount + . = matter >= amount + if(!. && user) + user << no_ammo_message + return . /obj/item/weapon/rcd/proc/detonate_pulse() audible_message("[src] begins to vibrate and \ @@ -483,26 +497,37 @@ RCD qdel(src) +/obj/item/weapon/rcd/borg/New() + ..() + no_ammo_message = "Insufficient charge." + desc = "A device used to rapidly build walls and floors." + canRturf = 1 + /obj/item/weapon/rcd/borg/useResource(amount, mob/user) if(!isrobot(user)) return 0 var/mob/living/silicon/robot/borgy = user if(!borgy.cell) + if(user) + user << no_ammo_message return 0 - return borgy.cell.use(amount * 72) //borgs get 1.3x the use of their RCDs + . = borgy.cell.use(amount * 72) //borgs get 1.3x the use of their RCDs + if(!. && user) + user << no_ammo_message + return . /obj/item/weapon/rcd/borg/checkResource(amount, mob/user) if(!isrobot(user)) return 0 var/mob/living/silicon/robot/borgy = user if(!borgy.cell) + if(user) + user << no_ammo_message return 0 - return borgy.cell.charge >= (amount * 72) - -/obj/item/weapon/rcd/borg/New() - ..() - desc = "A device used to rapidly build walls and floors." - canRturf = 1 + . = borgy.cell.charge >= (amount * 72) + if(!. && user) + user << no_ammo_message + return . /obj/item/weapon/rcd/loaded matter = 160 diff --git a/code/game/objects/items/weapons/holosign_creator.dm b/code/game/objects/items/weapons/holosign_creator.dm index 854055af4ee..b62cfd8faf3 100644 --- a/code/game/objects/items/weapons/holosign_creator.dm +++ b/code/game/objects/items/weapons/holosign_creator.dm @@ -140,7 +140,7 @@ qdel(src) /obj/effect/overlay/holograph/attack_animal(mob/living/simple_animal/M) - if(!M.melee_damage_upper) + if(!M.melee_damage_upper && !M.obj_damage) return attack_generic(5, M) diff --git a/code/game/objects/items/weapons/powerfist.dm b/code/game/objects/items/weapons/powerfist.dm index b4a5ddca219..4748b109a2b 100644 --- a/code/game/objects/items/weapons/powerfist.dm +++ b/code/game/objects/items/weapons/powerfist.dm @@ -79,7 +79,7 @@ target.apply_damage(force * fisto_setting, BRUTE) target.visible_message("[user]'s powerfist lets out a loud hiss as they punch [target.name]!", \ "You cry out in pain as [user]'s punch flings you backwards!") - PoolOrNew(/obj/effect/kinetic_blast, target.loc) + PoolOrNew(/obj/effect/overlay/temp/kinetic_blast, target.loc) playsound(loc, 'sound/weapons/resonator_blast.ogg', 50, 1) playsound(loc, 'sound/weapons/genhit2.ogg', 50, 1) diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm index 53693b855b3..62ace83774f 100644 --- a/code/game/objects/items/weapons/storage/toolbox.dm +++ b/code/game/objects/items/weapons/storage/toolbox.dm @@ -4,8 +4,8 @@ icon_state = "red" item_state = "toolbox_red" flags = CONDUCT - force = 10 - throwforce = 10 + force = 12 + throwforce = 12 throw_speed = 2 throw_range = 7 w_class = 4 diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index 3d5d9cf99e9..c5c4aa37f63 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -217,6 +217,8 @@ throw_range = 5 w_class = 2 + + materials = list(MAT_METAL=70, MAT_GLASS=30) origin_tech = "engineering=1;plasmatech=1" var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) @@ -235,6 +237,7 @@ update_icon() return + /obj/item/weapon/weldingtool/proc/update_torch() cut_overlays() if(welding) @@ -254,9 +257,27 @@ update_torch() return -/obj/item/weapon/weldingtool/examine(mob/user) - ..() - user << "It contains [get_fuel()] unit\s of fuel out of [max_fuel]." + +/obj/item/weapon/weldingtool/process() + switch(welding) + if(0) + force = 3 + damtype = "brute" + update_icon() + if(!can_off_process) + STOP_PROCESSING(SSobj, src) + return + //Welders left on now use up fuel, but lets not have them run out quite that fast + if(1) + force = 15 + damtype = "fire" + if(prob(5)) + remove_fuel(1) + update_icon() + + //This is to start fires. process() is only called if the welder is on. + open_flame() + /obj/item/weapon/weldingtool/suicide_act(mob/user) user.visible_message("[user] welds \his every orifice closed! It looks like \he's trying to commit suicide..") @@ -288,27 +309,6 @@ else return ..() -/obj/item/weapon/weldingtool/process() - switch(welding) - if(0) - force = 3 - damtype = "brute" - update_icon() - if(!can_off_process) - STOP_PROCESSING(SSobj, src) - return - //Welders left on now use up fuel, but lets not have them run out quite that fast - if(1) - force = 15 - damtype = "fire" - if(prob(5)) - remove_fuel(1) - update_icon() - - - //This is to start fires. process() is only called if the welder is on. - open_flame() - /obj/item/weapon/weldingtool/afterattack(atom/O, mob/user, proximity) if(!proximity) return @@ -317,6 +317,8 @@ remove_fuel(1) var/turf/location = get_turf(user) location.hotspot_expose(700, 50, 1) + if(get_fuel() <= 0) + user.AddLuminosity(-light_intensity) if(isliving(O)) var/mob/living/L = O @@ -324,10 +326,17 @@ message_admins("[key_name_admin(user)] set [key_name_admin(L)] on fire") log_game("[key_name(user)] set [key_name(L)] on fire") + /obj/item/weapon/weldingtool/attack_self(mob/user) - toggle(user) + switched_on(user) + if(welding) + SetLuminosity(0) + user.AddLuminosity(light_intensity) + else + user.AddLuminosity(-light_intensity) update_icon() + //Returns the amount of fuel in the welder /obj/item/weapon/weldingtool/proc/get_fuel() return reagents.get_reagent_amount("welding_fuel") @@ -349,15 +358,10 @@ return FALSE -//Returns whether or not the welding tool is currently on. -/obj/item/weapon/weldingtool/proc/isOn() - return welding - - //Turns off the welder if there is no more fuel (does this really need to be its own proc?) /obj/item/weapon/weldingtool/proc/check_fuel(mob/user) if(get_fuel() <= 0 && welding) - toggle(user, 1) + switched_on(user) update_icon() //mob icon update if(ismob(loc)) @@ -368,9 +372,8 @@ return 0 return 1 - -//Toggles the welder off and on -/obj/item/weapon/weldingtool/proc/toggle(mob/user, message = 0) +//Switches the welder on +obj/item/weapon/weldingtool/proc/switched_on(mob/user) if(!status) user << "[src] can't be turned on while unsecured!" return @@ -385,20 +388,54 @@ START_PROCESSING(SSobj, src) else user << "You need more fuel!" - welding = 0 + switched_off(user) else - if(!message) - user << "You switch [src] off." - else - user << "[src] shuts off!" - force = 3 - damtype = "brute" - hitsound = "swing_hit" - update_icon() + user << "You switch [src] off." + switched_off(user) + +//Switches the welder off +obj/item/weapon/weldingtool/proc/switched_off(mob/user) + welding = 0 + var/mob/Player = loc + if(ismob(loc)) //If player is holding the welder + Player.AddLuminosity(-light_intensity) + SetLuminosity(0) + else + SetLuminosity(0) + + force = 3 + damtype = "brute" + hitsound = "swing_hit" + update_icon() + + +/obj/item/weapon/weldingtool/pickup(mob/user) + ..() + if(welding) + SetLuminosity(0) + user.AddLuminosity(light_intensity) + + +/obj/item/weapon/weldingtool/dropped(mob/user) + ..() + if(welding) + if(user) + user.AddLuminosity(-light_intensity) + SetLuminosity(light_intensity) + + +/obj/item/weapon/weldingtool/examine(mob/user) + ..() + user << "It contains [get_fuel()] unit\s of fuel out of [max_fuel]." /obj/item/weapon/weldingtool/is_hot() return welding * heat +//Returns whether or not the welding tool is currently on. +/obj/item/weapon/weldingtool/proc/isOn() + return welding + + /obj/item/weapon/weldingtool/proc/flamethrower_screwdriver(obj/item/I, mob/user) if(welding) user << "Turn it off first!" diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 7e5a331af87..6cc9ed804c4 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -219,3 +219,6 @@ /obj/proc/CanAStarPass() . = !density + +/obj/proc/check_uplink_validity() + return 1 \ No newline at end of file diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm index 2b25f5dfb22..1a74946f921 100644 --- a/code/game/objects/structures/aliens.dm +++ b/code/game/objects/structures/aliens.dm @@ -150,10 +150,13 @@ /obj/structure/alien/resin/attack_animal(mob/living/simple_animal/M) M.changeNext_move(CLICK_CD_MELEE) M.do_attack_animation(src) - if(!M.melee_damage_upper) + if(!M.melee_damage_upper && !M.obj_damage) return visible_message("[M] [M.attacktext] [src]!") - take_damage(M.melee_damage_upper, M.melee_damage_type) + if(M.obj_damage) + take_damage(M.obj_damage, M.melee_damage_type) + else + take_damage(rand(M.melee_damage_lower,M.melee_damage_upper), M.melee_damage_type) /obj/structure/alien/resin/CanPass(atom/movable/mover, turf/target, height=0) return !density diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm index f9e96c10e71..c6f3b7831c4 100644 --- a/code/game/objects/structures/beds_chairs/bed.dm +++ b/code/game/objects/structures/beds_chairs/bed.dm @@ -69,7 +69,7 @@ if(over_object == usr && Adjacent(usr)) if(!ishuman(usr)) return 0 - if(buckled_mobs.len) + if(has_buckled_mobs()) return 0 if(usr.incapacitated()) usr << "You can't do that right now!" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index ec99aa5a374..ff73411c6a5 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -12,6 +12,7 @@ new /obj/item/weapon/storage/backpack/satchel/cap(src) new /obj/item/clothing/suit/cloak/cap(src) new /obj/item/weapon/storage/backpack/dufflebag/captain(src) + new /obj/item/clothing/head/crown/fancy(src) new /obj/item/clothing/suit/captunic(src) new /obj/item/clothing/under/captainparade(src) new /obj/item/clothing/head/caphat/parade(src) diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index 13b32581dba..0dd4998ac3e 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -177,10 +177,14 @@ /obj/structure/displaycase/attack_animal(mob/living/simple_animal/M) M.changeNext_move(CLICK_CD_MELEE) M.do_attack_animation(src) - if(M.melee_damage_upper > 0) + if(M.melee_damage_upper || M.obj_damage) M.visible_message("[M.name] smashes against \the [src.name].",\ "You smash against the [src.name].") - take_damage(M.melee_damage_upper, M.melee_damage_type, 1) + if(M.obj_damage) + take_damage(M.obj_damage, M.melee_damage_type, 1) + else + take_damage(rand(M.melee_damage_lower,M.melee_damage_upper), M.melee_damage_type, 1) + /obj/structure/displaycase/attack_hand(mob/user) user.changeNext_move(CLICK_CD_MELEE) diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index fbeabb1231f..12ee0f8d277 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -304,7 +304,7 @@ canSmoothWith = list(/obj/structure/falsewall/abductor, /turf/closed/wall/mineral/abductor) /obj/structure/falsewall/titanium - name = "titanium wall" + name = "wall" desc = "A light-weight titanium wall used in shuttles." icon = 'icons/turf/walls/shuttle_wall.dmi' icon_state = "shuttle" @@ -313,7 +313,7 @@ canSmoothWith = list(/turf/closed/wall/mineral/titanium, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock/, /turf/closed/wall/shuttle, /obj/structure/window/shuttle, /obj/structure/shuttle/engine, /obj/structure/shuttle/engine/heater, ) /obj/structure/falsewall/plastitanium - name = "plastitanium wall" + name = "wall" desc = "An evil wall of plasma and titanium." icon = 'icons/turf/shuttle.dmi' icon_state = "wall3" diff --git a/code/game/objects/structures/fireaxe.dm b/code/game/objects/structures/fireaxe.dm index 0c2d8b52c22..a7b1172c922 100644 --- a/code/game/objects/structures/fireaxe.dm +++ b/code/game/objects/structures/fireaxe.dm @@ -112,11 +112,14 @@ take_damage(20) /obj/structure/fireaxecabinet/attack_animal(mob/living/simple_animal/M) - if(!M.melee_damage_upper) + if(!M.melee_damage_upper && !M.obj_damage) return M.visible_message("[M] smashes against [src].", \ "You smash against [src].") - take_damage(M.melee_damage_upper, M.melee_damage_type) + if(M.obj_damage) + take_damage(M.obj_damage, M.melee_damage_type) + else + take_damage(rand(M.melee_damage_lower,M.melee_damage_upper), M.melee_damage_type) /obj/structure/fireaxecabinet/attack_ai(mob/user) toggle_lock(user) diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index daac9933bd8..48192946ac6 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -228,6 +228,7 @@ name = "potted plant" icon = 'icons/obj/flora/plants.dmi' icon_state = "plant-01" + layer = ABOVE_MOB_LAYER w_class = 5 force = 10 throwforce = 13 diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index fedae0ed7d6..a3f753c6de1 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -79,13 +79,16 @@ /obj/structure/grille/attack_animal(var/mob/living/simple_animal/M) M.changeNext_move(CLICK_CD_MELEE) - if(M.melee_damage_upper == 0 || (M.melee_damage_type != BRUTE && M.melee_damage_type != BURN)) + if(!M.melee_damage_upper && !M.obj_damage || (M.melee_damage_type != BRUTE && M.melee_damage_type != BURN)) return M.do_attack_animation(src) M.visible_message("[M] smashes against [src].", \ "You smash against [src].", \ "You hear twisting metal.") - take_damage(M.melee_damage_upper, M.melee_damage_type) + if(M.obj_damage) + take_damage(M.obj_damage, M.melee_damage_type) + else + take_damage(rand(M.melee_damage_lower,M.melee_damage_upper), M.melee_damage_type) /obj/structure/grille/mech_melee_attack(obj/mecha/M) diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index e3ad10d44c0..042ce6b307d 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -67,7 +67,6 @@ L.emote("scream") L.add_splatter_floor() L.adjustBruteLoss(30) - L.buckled = src L.setDir(2) buckle_mob(L, force=1) var/matrix/m180 = matrix(L.transform) diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 2cf60ac8808..f6c5c6691d4 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -110,7 +110,7 @@ attack_generic(user) /obj/structure/mirror/attack_animal(mob/living/simple_animal/M) - if(M.melee_damage_upper <= 0) + if(!M.melee_damage_upper && !M.obj_damage) return attack_generic(M) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index cf81ba3b64d..4d8bb9c3702 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -81,8 +81,10 @@ /obj/structure/table/attack_animal(mob/living/simple_animal/user) user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src) - if(user.melee_damage_upper) + if(user.melee_damage_upper || user.obj_damage) var/dmg_dealt = user.melee_damage_upper + if(user.obj_damage) + dmg_dealt = user.obj_damage if(user.environment_smash) dmg_dealt = 100 visible_message("[user] smashes [src]!") @@ -536,13 +538,16 @@ /obj/structure/rack/attack_animal(mob/living/simple_animal/user) user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src) - if(user.melee_damage_upper) + if(user.melee_damage_upper || user.obj_damage) + var/dmg_dealt = user.melee_damage_upper + if(user.obj_damage) + dmg_dealt = user.obj_damage if(user.environment_smash) playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1) visible_message("[user] smashes [src] apart.") rack_destroy() else - take_damage(user.melee_damage_upper, user.melee_damage_type) + take_damage(dmg_dealt, user.melee_damage_type) /obj/structure/rack/attack_tk() // no telehulk sorry diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 4e8a4eb86df..8c89c8f8a0b 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -157,9 +157,12 @@ attack_generic(user, 15) /obj/structure/window/attack_animal(mob/living/simple_animal/M) - if(!M.melee_damage_upper) + if(!M.melee_damage_upper && !M.obj_damage) return - attack_generic(M, M.melee_damage_upper, M.melee_damage_type) + if(M.obj_damage) + attack_generic(M, M.obj_damage, M.melee_damage_type) + else + attack_generic(M, M.melee_damage_upper, M.melee_damage_type) /obj/structure/window/attack_slime(mob/living/simple_animal/slime/user) diff --git a/code/game/turfs/simulated/floor/mineral_floor.dm b/code/game/turfs/simulated/floor/mineral_floor.dm index a6d796e2414..70c49521b35 100644 --- a/code/game/turfs/simulated/floor/mineral_floor.dm +++ b/code/game/turfs/simulated/floor/mineral_floor.dm @@ -74,12 +74,6 @@ //TITANIUM (shuttle) -/turf/open/floor/mineral/titanium - name = "shuttle floor" - icon_state = "shuttlefloor3" - floor_tile = /obj/item/stack/tile/mineral/titanium - icons = list("shuttlefloor3","shuttlefloor3_dam") - /turf/open/floor/mineral/titanium/blue icon_state = "shuttlefloor" icons = list("shuttlefloor","shuttlefloor_dam") @@ -88,6 +82,12 @@ icon_state = "shuttlefloor2" icons = list("shuttlefloor2","shuttlefloor2_dam") +/turf/open/floor/mineral/titanium + name = "shuttle floor" + icon_state = "shuttlefloor3" + floor_tile = /obj/item/stack/tile/mineral/titanium + icons = list("shuttlefloor3","shuttlefloor3_dam") + /turf/open/floor/mineral/titanium/purple icon_state = "shuttlefloor5" icons = list("shuttlefloor5","shuttlefloor5_dam") diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index d72e106b393..a7895b526d4 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -150,7 +150,27 @@ /turf/open/floor/engine/cult name = "engraved floor" - icon_state = "cult" + icon_state = "plating" + var/obj/effect/clockwork/overlay/floor/realappearence + +/turf/open/floor/engine/cult/New() + ..() + PoolOrNew(/obj/effect/overlay/temp/cult/turf/open/floor, src) + realappearence = PoolOrNew(/obj/effect/overlay/cult/floor, src) + realappearence.linked = src + +/turf/open/floor/engine/cult/Destroy() + be_removed() + return ..() + +/turf/open/floor/engine/cult/ChangeTurf(path, defer_change = FALSE) + if(path != type) + be_removed() + return ..() + +/turf/open/floor/engine/cult/proc/be_removed() + qdel(realappearence) + realappearence = null /turf/open/floor/engine/cult/New() PoolOrNew(/obj/effect/overlay/temp/cult/turf/open/floor, src) diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm index 2be75979ea4..9e704b5dc97 100644 --- a/code/game/turfs/simulated/walls_mineral.dm +++ b/code/game/turfs/simulated/walls_mineral.dm @@ -198,7 +198,7 @@ smooth = SMOOTH_FALSE /turf/closed/wall/mineral/titanium //has to use this path due to how building walls works - name = "titanium wall" + name = "wall" desc = "A light-weight titanium wall used in shuttles." icon = 'icons/turf/walls/shuttle_wall.dmi' icon_state = "map-shuttle" @@ -243,7 +243,7 @@ T.transform = transform /turf/closed/wall/mineral/plastitanium - name = "plastitanium wall" + name = "wall" desc = "An evil wall of plasma and titanium." walltype = "syndieshuttle" icon = 'icons/turf/shuttle.dmi' diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 218d764dd0e..cf46254a2f5 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -3,7 +3,7 @@ level = 1 var/intact = 1 - var/baseturf = /turf/open/space + var/turf/baseturf = /turf/open/space var/temperature = T20C var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 90e04375553..844fcd3a1c6 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -703,7 +703,7 @@ var/global/BSACooldown = 0 if(!ai_number) usr << "No AIs located" //Just so you know the thing is actually working and not just ignoring you. -/datum/admins/proc/output_devil_info() +/datum/admins/proc/output_all_devil_info() var/devil_number = 0 for(var/D in ticker.mode.devils) devil_number++ @@ -711,6 +711,12 @@ var/global/BSACooldown = 0 if(!devil_number) usr << "No Devils located" //Just so you know the thing is actually working and not just ignoring you. +/datum/admins/proc/output_devil_info(mob/living/M) + if(istype(M) && M.mind && M.mind.devilinfo) + usr << ticker.mode.printdevilinfo(M.mind) + else + usr << "[M] is not a devil." + /datum/admins/proc/manage_free_slots() if(!check_rights()) return diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 5526308de7b..618c5303b6f 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1621,7 +1621,8 @@ output_ai_laws() else if(href_list["admincheckdevilinfo"]) - output_devil_info() + var/mob/M = locate(href_list["admincheckdevilinfo"]) + output_devil_info(M) else if(href_list["adminmoreinfo"]) var/mob/M = locate(href_list["adminmoreinfo"]) diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index 391b474f68e..ac9f89ad9ff 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -372,7 +372,7 @@ var/list/gaslist_cache = null copy.temperature = temperature for(var/id in cached_gases) - add_gas(id) + copy.add_gas(id) copy_gases[id][MOLES] = cached_gases[id][MOLES] return copy diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm index d538c0bad44..c78e9de2e9c 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm @@ -50,7 +50,7 @@ var/hc = pipe_air.heat_capacity() var/mob/living/heat_source = buckled_mobs[1] //Best guess-estimate of the total bodytemperature of all the mobs, since they share the same environment it's ~ok~ to guess like this - var/avg_temp = (pipe_air.temperature * hc + (heat_source.bodytemperature * buckled_mobs.len) * 3500) / (hc + (buckled_mobs.len * 3500)) + var/avg_temp = (pipe_air.temperature * hc + (heat_source.bodytemperature * buckled_mobs.len) * 3500) / (hc + (buckled_mobs ? buckled_mobs.len * 3500 : 0)) for(var/m in buckled_mobs) var/mob/living/L = m L.bodytemperature = avg_temp diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index d4804d24084..b30c0e65eae 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -24,7 +24,7 @@ /obj/item/clothing/head/canada name = "striped red tophat" - desc = " It feels sticky, like maple syrup - il se sent collante, comme le sirop d'érable" + desc = " It feels sticky, like maple syrup - il se sent collante, comme le sirop d'érable" icon_state = "canada" item_state = "canada" @@ -259,4 +259,15 @@ name = "paper sack hat" desc = "A paper sack with crude holes cut out for eyes and a sketchy smile drawn on the front. Not creepy at all." icon_state = "papersack_smile" - flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS \ No newline at end of file + flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS + +/obj/item/clothing/head/crown + name = "crown" + desc = "A crown fit for a king, a petty king maybe." + icon_state = "crown" + armor = list(melee = 15, bullet = 0, laser = 0,energy = 15, bomb = 0, bio = 0, rad = 0) //for a warrior king //energy cause gold is reflective //worse than sec helm overall + +/obj/item/clothing/head/crown/fancy + name = "magnificent crown" + desc = "A crown worn by only the highest emperors of the land." + icon_state = "fancycrown" diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm index 8b6c1e7adc0..3dcf2ea3b19 100644 --- a/code/modules/clothing/outfits/ert.dm +++ b/code/modules/clothing/outfits/ert.dm @@ -28,7 +28,7 @@ id = /obj/item/weapon/card/id/ert suit = /obj/item/clothing/suit/space/hardsuit/ert - glasses = /obj/item/clothing/glasses/thermal/eyepatch + glasses = /obj/item/clothing/glasses/hud/security/sunglasses back = /obj/item/weapon/storage/backpack/captain belt = /obj/item/weapon/storage/belt/security/full backpack_contents = list(/obj/item/weapon/storage/box/engineer=1,\ @@ -42,7 +42,6 @@ if(visualsOnly) return - var/obj/item/device/radio/R = H.ears R.keyslot = new /obj/item/device/encryptionkey/heads/captain R.recalculateChannels() @@ -50,6 +49,7 @@ /datum/outfit/ert/commander/alert name = "ERT Commander - High Alert" + glasses = /obj/item/clothing/glasses/thermal/eyepatch backpack_contents = list(/obj/item/weapon/storage/box/engineer=1,\ /obj/item/weapon/melee/baton/loaded=1,\ /obj/item/clothing/mask/gas/sechailer/swat=1,\ @@ -193,4 +193,4 @@ W.access += access_weapons W.assignment = "Centcom Official" W.registered_name = H.real_name - W.update_label() \ No newline at end of file + W.update_label() diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index 4df444fa0bc..fbcb89bcff4 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -151,7 +151,7 @@ item_state = "eng_hardsuit" armor = list(melee = 30, bullet = 5, laser = 10, energy = 5, bomb = 10, bio = 100, rad = 75) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket //Atmospherics /obj/item/clothing/head/helmet/space/hardsuit/engine/atmos @@ -197,7 +197,7 @@ max_heat_protection_temperature = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine/elite jetpack = /obj/item/weapon/tank/jetpack/suit -// pockets = /obj/item/weapon/storage/internal/pocket/big + pockets = /obj/item/weapon/storage/internal/pocket/big //Mining hardsuit @@ -223,7 +223,7 @@ armor = list(melee = 30, bullet = 5, laser = 10, energy = 5, bomb = 50, bio = 100, rad = 50) allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/internals,/obj/item/weapon/storage/bag/ore,/obj/item/weapon/pickaxe) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/mining -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket //Syndicate hardsuit diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index b57ec2b4ad9..8e311d9167b 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -36,7 +36,7 @@ armor = list(melee = 30, bullet = 30, laser = 30, energy = 10, bomb = 25, bio = 0, rad = 0) cold_protection = CHEST|GROIN|LEGS|ARMS heat_protection = CHEST|GROIN|LEGS|ARMS -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket strip_delay = 80 /obj/item/clothing/suit/armor/hos/trenchcoat @@ -73,7 +73,7 @@ cold_protection = CHEST|GROIN|LEGS|ARMS heat_protection = CHEST|GROIN|LEGS|ARMS dog_fashion = null -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket /obj/item/clothing/suit/armor/vest/capcarapace name = "captain's carapace" diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index 35042edb026..30eb3b3c64b 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -11,7 +11,7 @@ blood_overlay_type = "armor" body_parts_covered = CHEST|GROIN allowed = list(/obj/item/weapon/reagent_containers/spray/plantbgone,/obj/item/device/plant_analyzer,/obj/item/seeds,/obj/item/weapon/reagent_containers/glass/bottle, /obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/cultivator,/obj/item/weapon/reagent_containers/spray/pestspray,/obj/item/weapon/hatchet,/obj/item/weapon/storage/bag/plants) -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket //Captain /obj/item/clothing/suit/captunic @@ -33,7 +33,7 @@ allowed = list(/obj/item/weapon/storage/book/bible, /obj/item/weapon/nullrod, /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater, /obj/item/weapon/storage/fancy/candle_box, /obj/item/candle, /obj/item/weapon/tank/internals/emergency_oxygen) hooded = 1 hoodtype = /obj/item/clothing/head/chaplain_hood -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket /obj/item/clothing/head/chaplain_hood name = "chaplain hood" @@ -52,7 +52,7 @@ body_parts_covered = CHEST|GROIN|LEGS|ARMS|HANDS flags_inv = HIDESHOES|HIDEJUMPSUIT allowed = list(/obj/item/weapon/storage/book/bible, /obj/item/weapon/nullrod, /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater, /obj/item/weapon/storage/fancy/candle_box, /obj/item/candle, /obj/item/weapon/tank/internals/emergency_oxygen) -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket //Chef /obj/item/clothing/suit/toggle/chef @@ -65,7 +65,7 @@ body_parts_covered = CHEST|GROIN|ARMS allowed = list(/obj/item/weapon/kitchen) togglename = "sleeves" -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket //Cook @@ -90,7 +90,7 @@ armor = list(melee = 25, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0) cold_protection = CHEST|GROIN|LEGS|ARMS heat_protection = CHEST|GROIN|LEGS|ARMS -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket /obj/item/clothing/suit/det_suit/grey name = "noir trenchcoat" @@ -107,7 +107,7 @@ blood_overlay_type = "armor" allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/internals/emergency_oxygen,/obj/item/device/t_scanner,/obj/item/device/radio) burn_state = FIRE_PROOF -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket //Lawyer /obj/item/clothing/suit/toggle/lawyer diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm index aa85e571b9e..29708eadebf 100644 --- a/code/modules/clothing/suits/labcoat.dm +++ b/code/modules/clothing/suits/labcoat.dm @@ -8,7 +8,7 @@ allowed = list(/obj/item/device/analyzer,/obj/item/stack/medical,/obj/item/weapon/dnainjector,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/syringe,/obj/item/weapon/reagent_containers/hypospray,/obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen,/obj/item/weapon/reagent_containers/glass/bottle,/obj/item/weapon/reagent_containers/glass/beaker,/obj/item/weapon/reagent_containers/pill,/obj/item/weapon/storage/pill_bottle,/obj/item/weapon/paper,/obj/item/weapon/melee/classic_baton/telescopic,/obj/item/weapon/soap,/obj/item/device/sensor_device,/obj/item/weapon/tank/internals/emergency_oxygen) armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 50, rad = 0) togglename = "buttons" -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket /obj/item/clothing/suit/toggle/labcoat/cmo name = "chief medical officer's labcoat" diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 862d6d2a645..1cf32dd12bb 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -37,7 +37,7 @@ icon_state = "pirate" item_state = "pirate" allowed = list(/obj/item/weapon/melee/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/weapon/reagent_containers/food/drinks/bottle/rum) -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket /obj/item/clothing/suit/pirate/captain name = "pirate captain coat" @@ -91,7 +91,7 @@ allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/internals/emergency_oxygen,/obj/item/toy) flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT burn_state = FIRE_PROOF -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket /obj/item/clothing/suit/hastur name = "\improper Hastur's robe" @@ -154,7 +154,7 @@ body_parts_covered = CHEST|GROIN|LEGS|ARMS flags_inv = HIDEJUMPSUIT allowed = list(/obj/item/weapon/storage/book/bible, /obj/item/weapon/nullrod, /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater, /obj/item/weapon/storage/fancy/candle_box, /obj/item/candle, /obj/item/weapon/tank/internals/emergency_oxygen) -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket /obj/item/clothing/suit/cardborg @@ -334,7 +334,7 @@ body_parts_covered = CHEST|GROIN|ARMS cold_protection = CHEST|GROIN|ARMS min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket /obj/item/clothing/suit/jacket/leather name = "leather jacket" @@ -422,7 +422,7 @@ armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/internals/emergency_oxygen,/obj/item/toy,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter) hooded = 1 -// pockets = /obj/item/weapon/storage/internal/pocket + pockets = /obj/item/weapon/storage/internal/pocket /obj/item/clothing/head/winterhood name = "winter hood" diff --git a/code/modules/clothing/under/trek.dm b/code/modules/clothing/under/trek.dm new file mode 100644 index 00000000000..6a2aed8bc7a --- /dev/null +++ b/code/modules/clothing/under/trek.dm @@ -0,0 +1,72 @@ +//Just some alt-uniforms themed around Star Trek - Pls don't sue, Mr Roddenberry ;_; + + +/obj/item/clothing/under/trek + can_adjust = 0 + + +//TOS +/obj/item/clothing/under/trek/command + name = "command uniform" + desc = "The uniform worn by command officers" + icon_state = "trek_command" + item_color = "trek_command" + item_state = "y_suit" + +/obj/item/clothing/under/trek/engsec + name = "engsec uniform" + desc = "The uniform worn by engineering/security officers" + icon_state = "trek_engsec" + item_color = "trek_engsec" + item_state = "r_suit" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) //more sec than eng, but w/e. + strip_delay = 50 + +/obj/item/clothing/under/trek/medsci + name = "medsci uniform" + desc = "The uniform worn by medical/science officers" + icon_state = "trek_medsci" + item_color = "trek_medsci" + item_state = "b_suit" + + +//TNG +/obj/item/clothing/under/trek/command/next + icon_state = "trek_next_command" + item_color = "trek_next_command" + item_state = "r_suit" + +/obj/item/clothing/under/trek/engsec/next + icon_state = "trek_next_engsec" + item_color = "trek_next_engsec" + item_state = "y_suit" + +/obj/item/clothing/under/trek/medsci/next + icon_state = "trek_next_medsci" + item_color = "trek_next_medsci" + + +//ENT +/obj/item/clothing/under/trek/command/ent + icon_state = "trek_ent_command" + item_color = "trek_ent_command" + item_state = "bl_suit" + +/obj/item/clothing/under/trek/engsec/ent + icon_state = "trek_ent_engsec" + item_color = "trek_ent_engsec" + item_state = "bl_suit" + +/obj/item/clothing/under/trek/medsci/ent + icon_state = "trek_ent_medsci" + item_color = "trek_ent_medsci" + item_state = "bl_suit" + + +//Q +/obj/item/clothing/under/trek/Q + name = "french marshall's uniform" + desc = "something about it feels off..." + icon_state = "trek_Q" + item_color = "trek_Q" + item_state = "r_suit" \ No newline at end of file diff --git a/code/modules/events/devil.dm b/code/modules/events/devil.dm index 21fad5037da..4f683a8f6f2 100644 --- a/code/modules/events/devil.dm +++ b/code/modules/events/devil.dm @@ -33,7 +33,9 @@ var/mob/living/carbon/human/devil = create_event_devil(spawn_loc) Mind.transfer_to(devil) ticker.mode.finalize_devil(Mind) + ticker.mode.add_devil_objectives(src, 2) Mind.announceDevilLaws() + Mind.announce_objectives() spawned_mobs += devil diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm index 61a792384c5..2aa71f91233 100644 --- a/code/modules/events/dust.dm +++ b/code/modules/events/dust.dm @@ -13,3 +13,18 @@ /datum/round_event/space_dust/start() spawn_meteors(1, meteorsC) + +/datum/round_event_control/sandstorm + name = "Sandstorm" + typepath = /datum/round_event/sandstorm + weight = 0 + max_occurrences = 0 + earliest_start = 0 + +/datum/round_event/sandstorm + startWhen = 1 + endWhen = 150 // ~5 min + announceWhen = 0 + +/datum/round_event/sandstorm/tick() + spawn_meteors(10, meteorsC) \ No newline at end of file diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index 624feef72f2..51e7fd8ac54 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -559,7 +559,7 @@ if(!has_buckled_mobs() && prob(25)) for(var/mob/living/V in src.loc) entangle(V) - if(buckled_mobs && buckled_mobs.len) + if(has_buckled_mobs()) break //only capture one mob at a time diff --git a/code/modules/food_and_drinks/food/snacks_burgers.dm b/code/modules/food_and_drinks/food/snacks_burgers.dm index 061a28d6c90..4cab54e9891 100644 --- a/code/modules/food_and_drinks/food/snacks_burgers.dm +++ b/code/modules/food_and_drinks/food/snacks_burgers.dm @@ -196,4 +196,10 @@ name = "rat burger" desc = "Pretty much what you'd expect..." icon_state = "ratburger" - bonus_reagents = list("nutriment" = 1, "vitamin" = 1) \ No newline at end of file + bonus_reagents = list("nutriment" = 1, "vitamin" = 1) + +/obj/item/weapon/reagent_containers/food/snacks/burger/baseball + name = "home run baseball burger" + desc = "It's still warm. The steam coming off of it looks like baseball." + icon_state = "baseball" + bonus_reagents = list("nutriment" = 1, "vitamin" = 1) diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm index 2aeb76ce87d..94b40722664 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm @@ -253,3 +253,12 @@ ) result = /obj/item/weapon/reagent_containers/food/snacks/burger/rat category = CAT_BURGER + +/datum/crafting_recipe/food/baseballburger + name = "Home run baseball burger" + reqs = list( + /obj/item/weapon/melee/baseball_bat = 1, + /obj/item/weapon/reagent_containers/food/snacks/bun = 1 + ) + result = /obj/item/weapon/reagent_containers/food/snacks/burger/baseball + category = CAT_BURGER diff --git a/code/modules/hydroponics/biogenerator.dm b/code/modules/hydroponics/biogenerator.dm index 43fed6a2185..f84a4c72e82 100644 --- a/code/modules/hydroponics/biogenerator.dm +++ b/code/modules/hydroponics/biogenerator.dm @@ -14,9 +14,13 @@ var/efficiency = 0 var/productivity = 0 var/max_items = 40 + var/datum/research/files + var/list/show_categories = list("Food", "Botany Chemicals", "Leather and Cloth") + var/list/timesFiveCategories = list("Food", "Botany Chemicals") /obj/machinery/biogenerator/New() ..() + files = new /datum/research/biogenerator(src) create_reagents(1000) var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/biogenerator(null) B.apply_default_parts(src) @@ -59,6 +63,9 @@ return /obj/machinery/biogenerator/attackby(obj/item/O, mob/user, params) + if(user.a_intent == "harm") + return ..() + if(processing) user << "The biogenerator is currently processing." return @@ -126,11 +133,18 @@ O.loc = src user << "You put [O.name] in [src.name]" return 1 //no afterattack - - else if(user.a_intent != "harm") - user << "You cannot put this in [src.name]!" + else if (istype(O, /obj/item/weapon/disk/design_disk)) + user.visible_message("[user] begins to load \the [O] in \the [src]...", + "You begin to load a design from \the [O]...", + "You hear the chatter of a floppy drive.") + processing = 1 + var/obj/item/weapon/disk/design_disk/D = O + if(do_after(user, 10, target = src)) + files.AddDesign2Known(D.blueprint) + processing = 0 + return 1 else - return ..() + user << "You cannot put this in [src.name]!" /obj/machinery/biogenerator/interact(mob/user) if(stat & BROKEN || panel_open) @@ -142,7 +156,7 @@ else switch(menustat) if("nopoints") - dat += "
You do not have biomass to create products.
Please, put growns into reactor and activate it.
" + dat += "
You do not have enough biomass to create products.
Please, put growns into reactor and activate it.
" menustat = "menu" if("complete") dat += "
Operation complete.
" @@ -154,43 +168,29 @@ dat += "
Not enough space left in container. Unable to create product.
" menustat = "menu" if(beaker) + var/categories = show_categories.Copy() + for(var/V in categories) + categories[V] = list() + for(var/V in files.known_designs) + var/datum/design/D = files.known_designs[V] + for(var/C in categories) + if(C in D.category) + categories[C] += D + dat += "
Biomass: [points] units.

" dat += "ActivateDetach Container" - dat += "

Food:

" - dat += "
" - dat += "10 milk: Makex5 ([20/efficiency])
" - dat += "10 cream: Makex5 ([30/efficiency])
" - dat += "Milk carton: Makex5 ([100/efficiency])
" - dat += "Cream carton: Makex5 ([300/efficiency])
" - dat += "10u black pepper: Makex5 ([25/efficiency])
" - dat += "Pepper mill: Makex5 ([50/efficiency])
" - dat += "Monkey cube: Makex5 ([250/efficiency])" - dat += "
" - dat += "

Botany Chemicals:

" - dat += "
" - dat += "E-Z-Nutrient: Makex5 ([10/efficiency])
" - dat += "Left 4 Zed: Makex5 ([20/efficiency])
" - dat += "Robust Harvest: Makex5 ([25/efficiency])
" - dat += "Weed Killer: Makex5 ([50/efficiency])
" - dat += "Pest Killer: Makex5 ([50/efficiency])
" - dat += "Empty bottle: Makex5 ([5/efficiency])
" - dat += "
" - dat += "

Leather and Cloth:

" - dat += "
" - dat += "Roll of cloth: Makex10 ([50/efficiency])
" - dat += "Wallet: Make ([100/efficiency])
" - dat += "Botanical gloves: Make ([250/efficiency])
" - dat += "Utility belt: Make ([300/efficiency])
" - dat += "Security belt: Make ([300/efficiency])
" - dat += "Medical belt: Make ([300/efficiency])
" - dat += "Janitorial belt: Make ([300/efficiency])
" - dat += "Bandolier belt: Make ([300/efficiency])
" - dat += "Shoulder holster: Make ([400/efficiency])
" - dat += "Leather satchel: Make ([400/efficiency])
" - dat += "Leather jacket: Make ([500/efficiency])
" - dat += "Leather overcoat: Make ([1000/efficiency])
" - dat += "Rice hat: Make ([300/efficiency])
" - dat += "
" + for(var/cat in categories) + dat += "

[cat]:

" + dat += "
" + for(var/V in categories[cat]) + var/datum/design/D = V + dat += "[D.name]: Make" + if(cat in timesFiveCategories) + dat += "x5" + if(ispath(D.build_path, /obj/item/stack)) + dat += "x10" + dat += "([D.materials[MAT_BIOMASS]/efficiency])
" + dat += "
" else dat += "
No container inside, please insert container.
" @@ -207,7 +207,7 @@ return if (src.stat != 0) //NOPOWER etc return - if(src.processing) + if(processing) usr << "The biogenerator is in the process of working." return var/S = 0 @@ -230,142 +230,62 @@ menustat = "void" return -/obj/machinery/biogenerator/proc/check_cost(cost) - if (cost > points) +/obj/machinery/biogenerator/proc/check_cost(list/materials, multiplier = 1, remove_points = 1) + if(materials.len != 1 || materials[1] != MAT_BIOMASS) + return 0 + if (materials[MAT_BIOMASS]*multiplier/efficiency > points) menustat = "nopoints" - return 1 + return 0 else - points -= cost - processing = 1 + if(remove_points) + points -= materials[MAT_BIOMASS]*multiplier/efficiency update_icon() updateUsrDialog() - return 0 - -/obj/machinery/biogenerator/proc/check_container_volume(reagent_amount) - if(beaker.reagents.total_volume + reagent_amount > beaker.reagents.maximum_volume) - menustat = "nobeakerspace" return 1 -/obj/machinery/biogenerator/proc/create_product(create) - switch(create) - if("milk") - if(check_container_volume(10)) - return 0 - else if (check_cost(20/efficiency)) - return 0 - else beaker.reagents.add_reagent("milk",10) - if("bpepper") - if(check_container_volume(10)) - return 0 - else if (check_cost(25/efficiency)) - return 0 - else beaker.reagents.add_reagent("blackpepper",10) - if("cream") - if(check_container_volume(10)) - return 0 - else if (check_cost(30/efficiency)) - return 0 - else beaker.reagents.add_reagent("cream",10) - if("cmilk") - if (check_cost(100/efficiency)) - return 0 - else new/obj/item/weapon/reagent_containers/food/condiment/milk(src.loc) - if("mpepper") - if (check_cost(50/efficiency)) - return 0 - else new/obj/item/weapon/reagent_containers/food/condiment/peppermill(src.loc) - if("ccream") - if (check_cost(300/efficiency)) - return 0 - else new/obj/item/weapon/reagent_containers/food/drinks/bottle/cream(src.loc) - if("meat") - if (check_cost(250/efficiency)) - return 0 - else new/obj/item/weapon/reagent_containers/food/snacks/monkeycube(src.loc) - if("ez") - if (check_cost(10/efficiency)) - return 0 - else new/obj/item/weapon/reagent_containers/glass/bottle/nutrient/ez(src.loc) - if("l4z") - if (check_cost(20/efficiency)) - return 0 - else new/obj/item/weapon/reagent_containers/glass/bottle/nutrient/l4z(src.loc) - if("rh") - if (check_cost(25/efficiency)) - return 0 - else new/obj/item/weapon/reagent_containers/glass/bottle/nutrient/rh(src.loc) - if("wk") - if (check_cost(50/efficiency)) - return 0 - else new/obj/item/weapon/reagent_containers/glass/bottle/killer/weedkiller(src.loc) - if("pk") - if (check_cost(50/efficiency)) - return 0 - else new/obj/item/weapon/reagent_containers/glass/bottle/killer/pestkiller(src.loc) - if("empty") - if (check_cost(5/efficiency)) - return 0 - else new/obj/item/weapon/reagent_containers/glass/bottle/nutrient/empty(src.loc) - if("cloth") - if (check_cost(50/efficiency)) - return 0 - else new/obj/item/stack/sheet/cloth(src.loc) - if("tencloth") - if (check_cost(500/efficiency)) - return 0 - else new/obj/item/stack/sheet/cloth/ten(src.loc) - if("wallet") - if (check_cost(100/efficiency)) - return 0 - else new/obj/item/weapon/storage/wallet(src.loc) - if("gloves") - if (check_cost(250/efficiency)) - return 0 - else new/obj/item/clothing/gloves/botanic_leather(src.loc) - if("tbelt") - if (check_cost(300/efficiency)) - return 0 - else new/obj/item/weapon/storage/belt/utility(src.loc) - if("sbelt") - if (check_cost(300/efficiency)) - return 0 - else new/obj/item/weapon/storage/belt/security(src.loc) - if("mbelt") - if (check_cost(300/efficiency)) - return 0 - else new/obj/item/weapon/storage/belt/medical(src.loc) - if("jbelt") - if (check_cost(300/efficiency)) - return 0 - else new/obj/item/weapon/storage/belt/janitor(src.loc) - if("bbelt") - if (check_cost(300/efficiency)) - return 0 - else new/obj/item/weapon/storage/belt/bandolier(src.loc) - if("sholster") - if (check_cost(400/efficiency)) - return 0 - else new/obj/item/weapon/storage/belt/holster(src.loc) - if("satchel") - if (check_cost(400/efficiency)) - return 0 - else new/obj/item/weapon/storage/backpack/satchel(src.loc) - if("jacket") - if (check_cost(500/efficiency)) - return 0 - else new/obj/item/clothing/suit/jacket/leather(src.loc) - if("overcoat") - if (check_cost(1000/efficiency)) - return 0 - else new/obj/item/clothing/suit/jacket/leather/overcoat(src.loc) - if("rice_hat") - if (check_cost(300/efficiency)) - return 0 - else new/obj/item/clothing/head/rice_hat(src.loc) - processing = 0 +/obj/machinery/biogenerator/proc/check_container_volume(list/reagents, multiplier = 1) + var/sum_reagents = 0 + for(var/R in reagents) + sum_reagents += reagents[R] + sum_reagents *= multiplier + + if(beaker.reagents.total_volume + sum_reagents > beaker.reagents.maximum_volume) + menustat = "nobeakerspace" + return 0 + + return 1 + +/obj/machinery/biogenerator/proc/create_product(datum/design/D, amount) + if(!beaker || !loc) + return 0 + + if(ispath(D.build_path, /obj/item/stack)) + if(!check_container_volume(D.make_reagents, amount)) + return 0 + if(!check_cost(D.materials, amount)) + return 0 + + var/obj/item/stack/product = new D.build_path(loc) + product.amount = amount + for(var/R in D.make_reagents) + beaker.reagents.add_reagent(R, D.make_reagents[R]*amount) + else + var/i = amount + while(i > 0) + if(!check_container_volume(D.make_reagents)) + return . + if(!check_cost(D.materials)) + return . + if(D.build_path) + new D.build_path(loc) + for(var/R in D.make_reagents) + beaker.reagents.add_reagent(R, D.make_reagents[R]) + . = 1 + --i + menustat = "complete" update_icon() - return 1 + return . /obj/machinery/biogenerator/proc/detach() if(beaker) @@ -389,13 +309,8 @@ else if(href_list["create"]) var/amount = (text2num(href_list["amount"])) - var/i = amount - var/C = href_list["create"] - if(i <= 0) - return - while(i >= 1) - create_product(C) - i-- + var/datum/design/D = locate(href_list["create"]) + create_product(D, amount) updateUsrDialog() else if(href_list["menu"]) diff --git a/code/modules/hydroponics/grown/mushrooms.dm b/code/modules/hydroponics/grown/mushrooms.dm index 22c2e119dcb..b47e119bf2b 100644 --- a/code/modules/hydroponics/grown/mushrooms.dm +++ b/code/modules/hydroponics/grown/mushrooms.dm @@ -49,7 +49,7 @@ plant_type = PLANT_MUSHROOM growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi' mutatelist = list(/obj/item/seeds/angel) - reagents_add = list("mushroomhallucinogen" = 0.04, "amatoxin" = 0.35, "nutriment" = 0) + reagents_add = list("mushroomhallucinogen" = 0.04, "amatoxin" = 0.35, "nutriment" = 0, "growthserum" = 0.1) /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita seed = /obj/item/seeds/amanita diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 1f63b52ed03..539b41de722 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -121,11 +121,11 @@ myseed.loc = src if(self_sustaining) - adjustNutri(2 / rating) - adjustWater(rand(8, 10) / rating) - adjustWeeds(-5 / rating) - adjustPests(-5 / rating) - adjustToxic(-5 / rating) + adjustNutri(2 * rating) + adjustWater(rand(8, 10) * rating) + adjustWeeds(-5 * rating) + adjustPests(-5 * rating) + adjustToxic(-5 * rating) if(world.time > (lastcycle + cycledelay)) lastcycle = world.time @@ -619,7 +619,7 @@ adjustHealth(round(salt * 0.25)) if (myseed) myseed.adjust_production(-round(salt/100)-prob(salt%100)) - myseed.adjust_potency(round(salt*0.15)) + myseed.adjust_potency(round(salt*0.50)) // Ash is also used IRL in gardening, as a fertilizer enhancer and weed killer if(S.has_reagent("ash", 1)) adjustHealth(round(S.get_reagent_amount("ash") * 0.25)) diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 292fee234dc..0ef623b7717 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -55,7 +55,7 @@ desc = "Used to call and send the mining shuttle." circuit = /obj/item/weapon/circuitboard/computer/mining_shuttle shuttleId = "mining" - possible_destinations = "mining_home;mining_away" + possible_destinations = "mining_home;mining_away;mining_base" no_destination_swap = 1 var/global/list/dumb_rev_heads = list() @@ -500,3 +500,95 @@ anchored = 1 layer = BELOW_MOB_LAYER density = 0 + +///Mining Base//// + +/area/shuttle/auxillary_base + name = "Auxillary Base" + + +/obj/machinery/computer/shuttle/auxillary_base + name = "auxillary base launch control" + icon = 'icons/obj/terminals.dmi' + icon_state = "dorm_available" + shuttleId = "colony_drop" + req_access = list(access_heads) + possible_destinations = null + clockwork = TRUE + +/obj/machinery/computer/shuttle/auxillary_base/Topic(href, href_list) + if(href_list["move"]) + if(z != ZLEVEL_STATION) + usr << "You can't move the base again!" + return 0 + ..() + +/obj/item/device/assault_pod/mining + name = "Landing Field Designator" + icon_state = "gangtool-purple" + item_state = "electronic" + icon = 'icons/obj/device.dmi' + desc = "Deploy to designate the landing zone of the auxillary base." + shuttle_id = "colony_drop" + var/setting = FALSE + var/no_restrictions = FALSE //Badmin variable to let you drop the colony ANYWHERE. + dwidth = 11 //These dimensions are to be set by the mappers for their respective maps. + dheight = 0 + width = 23 + height = 23 + lz_dir = 1 + +/obj/item/device/assault_pod/mining/attack_self(mob/living/user) + if(setting) + return + var/turf/T = get_turf(user) + if(!no_restrictions) + if(T.z != ZLEVEL_MINING) + user << "Wouldn't do much good dropping a mining base away from the mining area!" + return + var/colony_radius = max(width, height)/2 + var/list/area_counter = get_areas_in_range(colony_radius, T) + if(area_counter.len > 1) //Avoid smashing ruins unless you are inside a really big one + user << "Unable to acquire a targeting lock. Find an area clear of stuctures or entirely within one." + return + + user << "You begin setting the landing zone parameters..." + setting = TRUE + if(!do_after(user, 50, target = src)) //You get a few seconds to cancel if you do not want to drop there. + setting = FALSE + return + + var/obj/docking_port/stationary/landing_zone = new /obj/docking_port/stationary(T) + landing_zone.id = "colony_drop(\ref[src])" + landing_zone.name = "Landing Zone" + landing_zone.dwidth = dwidth + landing_zone.dheight = dheight + landing_zone.width = width + landing_zone.height = height + landing_zone.setDir(lz_dir) + + for(var/obj/machinery/computer/shuttle/S in machines) + if(S.shuttleId == shuttle_id) + S.possible_destinations = "[landing_zone.id]" + +//Serves as a nice mechanic to people get ready for the launch. + minor_announce("Auxiliary base landing zone coordinates locked in for [get_area(user)]. Launch command now available!") + user << "Landing zone set." + + qdel(src) + +/obj/item/device/assault_pod/mining/unrestricted + name = "omni-locational landing field designator" + desc = "Allows the deployment of the mining base ANYWHERE. Use with caution." + no_restrictions = TRUE + + +/area/shuttle/auxillary_base + name = "Auxillary Base" + +/obj/docking_port/mobile/auxillary_base + name = "auxillary base" + id = "colony_drop" + dwidth = 11 + width = 23 + height = 23 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm index 0ee77ea7666..6a17ffa5937 100644 --- a/code/modules/mob/living/carbon/brain/posibrain.dm +++ b/code/modules/mob/living/carbon/brain/posibrain.dm @@ -14,6 +14,7 @@ var/global/posibrain_notif_cooldown = 0 req_access = list(access_robotics) mecha = null//This does not appear to be used outside of reference in mecha.dm. braintype = "Android" + var/autoping = TRUE //if it pings on creation immediately var/begin_activation_message = "You carefully locate the manual activation switch and start the positronic brain's boot process." var/success_message = "The positronic brain pings, and its lights start flashing. Success!" var/fail_message = "The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?" @@ -148,7 +149,8 @@ var/global/posibrain_notif_cooldown = 0 brainmob.real_name = brainmob.name brainmob.loc = src brainmob.container = src - ping_ghosts("created", TRUE) + if(autoping) + ping_ghosts("created", TRUE) ..() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 961977cc4f2..15193870032 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -58,8 +58,6 @@ if(reagents.has_reagent("teslium")) shock_damage *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging! take_overall_damage(0,shock_damage) - //src.adjustFireLoss(shock_damage) - //src.updatehealth() visible_message( "[src] was shocked by \the [source]!", \ "You feel a powerful shock coursing through your body!", \ diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ab5600cfa12..eb4e7d9c45d 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1062,12 +1062,7 @@ O = new /datum/objective/sintouched/pride ticker.mode.sintouched += src.mind src.mind.objectives += O - var/obj_count = 1 - src << "Your current objectives:" - for(O in src.mind.objectives) - var/datum/objective/objective = O - src << "Objective #[obj_count]: [objective.explanation_text]" - obj_count++ + src.mind.announce_objectives() /mob/living/carbon/human/check_weakness(obj/item/weapon, mob/living/attacker) . = ..() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index b7159cfb159..a7036f009e5 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -437,7 +437,13 @@ Sorry Giacom. Please don't be mad :( /mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0) - return 0 //only carbon liveforms have this proc + adjustFireLoss(shock_damage) + visible_message( + "[src] was shocked by \the [source]!", \ + "You feel a powerful shock coursing through your body!", \ + "You hear a heavy electrical crack." \ + ) + return shock_damage /mob/living/emp_act(severity) var/list/L = src.get_contents() @@ -1030,7 +1036,10 @@ Sorry Giacom. Please don't be mad :( return 1 /mob/living/proc/return_soul() + hellbound = 0 if(mind) + if(mind.soulOwner.devilinfo)//Not sure how this could happen, but whatever. + mind.soulOwner.devilinfo.remove_soul(mind) mind.soulOwner = mind /mob/living/proc/has_bane(banetype) diff --git a/code/modules/mob/living/silicon/laws.dm b/code/modules/mob/living/silicon/laws.dm index 9d646bee151..9ed86afb74f 100644 --- a/code/modules/mob/living/silicon/laws.dm +++ b/code/modules/mob/living/silicon/laws.dm @@ -5,10 +5,15 @@ if (!laws) make_laws() +/mob/living/silicon/proc/set_law_sixsixsix(law) + throw_alert("newlaw", /obj/screen/alert/newlaw) + laws_sanity_check() + laws.set_law_sixsixsix(law) + /mob/living/silicon/proc/set_zeroth_law(law, law_borg) throw_alert("newlaw", /obj/screen/alert/newlaw) - src.laws_sanity_check() - src.laws.set_zeroth_law(law, law_borg) + laws_sanity_check() + laws.set_zeroth_law(law, law_borg) /mob/living/silicon/proc/add_inherent_law(law) throw_alert("newlaw", /obj/screen/alert/newlaw) @@ -54,3 +59,7 @@ /mob/living/silicon/proc/clear_zeroth_law(force) laws_sanity_check() laws.clear_zeroth_law(force) + +/mob/living/silicon/proc/clear_law_sixsixsix(force) + laws_sanity_check() + laws.clear_law_sixsixsix(force) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index f88b2582bb0..934a0d6c633 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -29,6 +29,7 @@ var/lawcheck[1] var/ioncheck[1] + var/devillawcheck[5] var/med_hud = DATA_HUD_MEDICAL_ADVANCED //Determines the med hud to use var/sec_hud = DATA_HUD_SECURITY_ADVANCED //Determines the sec hud to use @@ -217,19 +218,31 @@ if (href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite var/L = text2num(href_list["lawc"]) switch(lawcheck[L+1]) - if ("Yes") lawcheck[L+1] = "No" - if ("No") lawcheck[L+1] = "Yes" -// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1]) + if ("Yes") + lawcheck[L+1] = "No" + if ("No") + lawcheck[L+1] = "Yes" checklaws() if (href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite var/L = text2num(href_list["lawi"]) switch(ioncheck[L]) - if ("Yes") ioncheck[L] = "No" - if ("No") ioncheck[L] = "Yes" -// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1]) + if ("Yes") + ioncheck[L] = "No" + if ("No") + ioncheck[L] = "Yes" checklaws() + if (href_list["lawdevil"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite + var/L = text2num(href_list["lawdevil"]) + switch(devillawcheck[L]) + if ("Yes") + devillawcheck[L] = "No" + if ("No") + devillawcheck[L] = "Yes" + checklaws() + + if (href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite statelaws() @@ -245,6 +258,11 @@ var/number = 1 sleep(10) + if (src.laws.devillaws && src.laws.devillaws.len) + for(var/index = 1, index <= src.laws.devillaws.len, index++) + if (src.devillawcheck[index] == "Yes") + src.say("[radiomod] 666. [src.laws.devillaws[index]]") + sleep(10) if (src.laws.zeroth) @@ -285,6 +303,12 @@ var/list = "Which laws do you want to include when stating them for the crew?

" + if (src.laws.devillaws && src.laws.devillaws.len) + for(var/index = 1, index <= src.laws.devillaws.len, index++) + if (!src.devillawcheck[index]) + src.devillawcheck[index] = "No" + list += {"[src.devillawcheck[index]] 666: [src.laws.devillaws[index]]
"} + if (src.laws.zeroth) if (!src.lawcheck[1]) src.lawcheck[1] = "No" //Given Law 0's usual nature, it defaults to NOT getting reported. --NeoFite diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm index fac8d25c9db..3a0ff80b5db 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm @@ -98,10 +98,14 @@ /mob/living/simple_animal/drone/med_hud_set_health() var/image/holder = hud_list[DIAG_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size holder.icon_state = "huddiag[RoundDiagBar(health/maxHealth)]" /mob/living/simple_animal/drone/med_hud_set_status() var/image/holder = hud_list[DIAG_STAT_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size if(stat == DEAD) holder.icon_state = "huddead2" else if(incapacitated()) @@ -259,3 +263,6 @@ /mob/living/simple_animal/drone/bee_friendly() // Why would bees pay attention to drones? return 1 + +/mob/living/simple_animal/drone/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0) + return 0 //So they don't die trying to fix wiring \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index 33982939f31..bef0d66a218 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -62,6 +62,8 @@ var/global/list/parasites = list() //all currently existing/living guardians /mob/living/simple_animal/hostile/guardian/med_hud_set_status() if(summoner) var/image/holder = hud_list[STATUS_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size if(summoner.stat == DEAD) holder.icon_state = "huddead" else diff --git a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm index 5cbe44e7d25..63b10fa5f7f 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm @@ -37,9 +37,9 @@ if(src.loc == summoner) src << "You must be manifested to create bombs!" return - if(istype(A, /obj/)) + if(isobj(A)) if(bomb_cooldown <= world.time && !stat) - var/obj/item/weapon/guardian_bomb/B = new /obj/item/weapon/guardian_bomb(get_turf(A)) + var/obj/guardian_bomb/B = new /obj/guardian_bomb(get_turf(A)) src << "Success! Bomb armed!" bomb_cooldown = world.time + 200 B.spawner = src @@ -47,49 +47,52 @@ else src << "Your powers are on cooldown! You must wait 20 seconds between bombs." -/obj/item/weapon/guardian_bomb +/obj/guardian_bomb name = "bomb" desc = "You shouldn't be seeing this!" var/obj/stored_obj var/mob/living/simple_animal/hostile/guardian/spawner -/obj/item/weapon/guardian_bomb/proc/disguise(var/obj/A) +/obj/guardian_bomb/proc/disguise(obj/A) A.loc = src stored_obj = A opacity = A.opacity anchored = A.anchored density = A.density appearance = A.appearance - spawn(600) - stored_obj.loc = get_turf(src.loc) - spawner << "Failure! Your trap didn't catch anyone this time." - qdel(src) + addtimer(src, "disable", 600, FALSE) -/obj/item/weapon/guardian_bomb/proc/detonate(var/mob/living/user) - user << "The [src] was boobytrapped!" - spawner << "Success! Your trap caught [user]" - stored_obj.loc = get_turf(src.loc) - playsound(get_turf(src),'sound/effects/Explosion2.ogg', 200, 1) - user.ex_act(2) +/obj/guardian_bomb/proc/disable() + stored_obj.forceMove(get_turf(src)) + spawner << "Failure! Your trap didn't catch anyone this time." qdel(src) -/obj/item/weapon/guardian_bomb/Bump(atom/A) - if(isliving(A) && A != spawner && A != spawner.summoner && !spawner.hasmatchingsummoner(A)) - detonate(A) - else - ..() +/obj/guardian_bomb/proc/detonate(mob/living/user) + if(isliving(user)) + if(user != spawner && user != spawner.summoner && !spawner.hasmatchingsummoner(user)) + user << "The [src] was boobytrapped!" + spawner << "Success! Your trap caught [user]" + var/turf/T = get_turf(src) + stored_obj.forceMove(T) + playsound(T,'sound/effects/Explosion2.ogg', 200, 1) + PoolOrNew(/obj/effect/overlay/temp/explosion, T) + user.ex_act(2) + qdel(src) + else + user << "[src] glows with a strange light, and you don't touch it." -/obj/item/weapon/guardian_bomb/attackby(mob/living/user) - detonate(user) - return - -/obj/item/weapon/guardian_bomb/pickup(mob/living/user) +/obj/guardian_bomb/Bump(atom/A) + detonate(A) ..() - detonate(user) - return -/obj/item/weapon/guardian_bomb/examine(mob/user) +/obj/guardian_bomb/attackby(mob/living/user) + detonate(user) + +/obj/guardian_bomb/attack_hand(mob/living/user) + detonate(user) + +/obj/guardian_bomb/examine(mob/user) stored_obj.examine(user) if(get_dist(user,src)<=2) user << "It glows with a strange light!" diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm index 49d7c5ed875..3ef67b39e1e 100644 --- a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm @@ -31,9 +31,10 @@ boss_type = /mob/living/simple_animal/hostile/boss/paper_wizard needs_target = FALSE say_when_triggered = "Rise, my creations! Jump off your pages and into this realm!" + var/summoned_minions = 0 /datum/action/boss/wizard_summon_minions/Trigger() - if(..()) + if(summoned_minions < 9 && ..()) var/list/minions = list( /mob/living/simple_animal/hostile/stickman, /mob/living/simple_animal/hostile/stickman/ranged, @@ -42,6 +43,7 @@ for(var/i in 1 to 3) var/minions_chosen = pick_n_take(minions) new minions_chosen (get_step(boss,pick_n_take(directions))) + summoned_minions += 3; //Mimic Ability diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index 81b60fe2bc0..0a3016d3b10 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -51,7 +51,7 @@ del_on_death = 1 /mob/living/simple_animal/hostile/carp/megacarp - icon = 'icons/mob/alienqueen.dmi' + icon = 'icons/mob/broadMobs.dmi' name = "Mega Space Carp" desc = "A ferocious, fang bearing creature that resembles a shark. This one seems especially ticked off." icon_state = "megacarp" diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index fa4f0104228..3f5cbfa3db6 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -75,8 +75,10 @@ /mob/living/simple_animal/hostile/bullet_act(obj/item/projectile/P) if(!target && AIStatus != AI_OFF && !client) + if(P.firer && get_dist(src, P.firer) <= aggro_vision_range) + FindTarget(list(P.firer), 1) Goto(P.starting, move_to_delay, 3) - ..() + return ..() //////////////HOSTILE MOB TARGETTING AND AGGRESSION//////////// @@ -86,7 +88,13 @@ if(!search_objects) var/list/Mobs = hearers(vision_range, targets_from) - src //Remove self, so we don't suicide . += Mobs - for(var/M in mechas_list) + + var/hostile_machines = list() + for(var/mecha in mechas_list) + hostile_machines += mecha + for(var/obj/machinery/porta_turret/P in machines) + hostile_machines += P + for(var/M in hostile_machines) if(get_dist(M, targets_from) <= vision_range && can_see(targets_from, M, vision_range)) . += M else @@ -147,11 +155,6 @@ if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it return 0 if(search_objects < 2) - if(istype(the_target, /obj/mecha)) - var/obj/mecha/M = the_target - if(M.occupant)//Just so we don't attack empty mechs - if(CanAttack(M.occupant)) - return 1 if(isliving(the_target)) var/mob/living/L = the_target var/faction_check = faction_check(L) @@ -168,6 +171,24 @@ if(faction_check && !attack_same) return 0 return 1 + + if(istype(the_target, /obj/mecha)) + var/obj/mecha/M = the_target + if(M.occupant)//Just so we don't attack empty mechs + if(CanAttack(M.occupant)) + return 1 + + if(istype(the_target, /obj/machinery/porta_turret)) + var/obj/machinery/porta_turret/P = the_target + if(P.faction in faction) + return 0 + if(P.has_cover &&!P.raised) //Don't attack invincible turrets + return 0 + if(P.stat & BROKEN) //Or turrets that are already broken + return 0 + return 1 + + if(isobj(the_target)) if(is_type_in_list(the_target, wanted_objects)) return 1 @@ -186,27 +207,28 @@ return 0 if(target in possible_targets) var/target_distance = get_dist(targets_from,target) - if(ranged)//We ranged? Shoot at em - if(target_distance >= 2 && ranged_cooldown <= world.time)//But make sure they're a tile away at least, and our range attack is off cooldown + var/target_adjacent = target.Adjacent(targets_from) + if(ranged) //We ranged? Shoot at em + if(!target_adjacent && ranged_cooldown <= world.time) //But make sure they're not in range for a melee attack and our range attack is off cooldown OpenFire(target) - if(!Process_Spacemove()) // Drifting + if(!Process_Spacemove()) //Drifting walk(src,0) return 1 - if(retreat_distance != null)//If we have a retreat distance, check if we need to run from our target - if(target_distance <= retreat_distance)//If target's closer than our retreat distance, run + if(retreat_distance != null) //If we have a retreat distance, check if we need to run from our target + if(target_distance <= retreat_distance) //If target's closer than our retreat distance, run walk_away(src,target,retreat_distance,move_to_delay) else - Goto(target,move_to_delay,minimum_distance)//Otherwise, get to our minimum distance so we chase them + Goto(target,move_to_delay,minimum_distance) //Otherwise, get to our minimum distance so we chase them else Goto(target,move_to_delay,minimum_distance) if(target) - if(isturf(targets_from.loc) && target.Adjacent(targets_from)) //If they're next to us, attack + if(isturf(targets_from.loc) && target_adjacent) //If they're next to us, attack AttackingTarget() return 1 return 0 if(environment_smash) - if(target.loc != null && get_dist(targets_from, target.loc) <= vision_range)//We can't see our target, but he's in our vision range still - if(environment_smash >= 2)//If we're capable of smashing through walls, forget about vision completely after finding our target + if(target.loc != null && get_dist(targets_from, target.loc) <= vision_range) //We can't see our target, but he's in our vision range still + if(environment_smash >= 2) //If we're capable of smashing through walls, forget about vision completely after finding our target Goto(target,move_to_delay,minimum_distance) FindHidden() return 1 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index db3fb4e07bb..f9802423027 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -63,12 +63,6 @@ Difficulty: Hard desc = "You're not quite sure how a signal can be bloody." invisibility = 100 -/mob/living/simple_animal/hostile/megafauna/bubblegum/AttackingTarget() - ..() - if(isliving(target)) - var/mob/living/L = target - devour(L) - /mob/living/simple_animal/hostile/megafauna/bubblegum/Life() ..() move_to_delay = Clamp(round((health/maxHealth) * 10), 5, 10) @@ -85,8 +79,8 @@ Difficulty: Hard else if(prob(5+anger_modifier/2)) slaughterlings() - else - if(health > maxHealth/2 && !client && !charging) + else if(!charging) + if(health > maxHealth/2 && !client) charge() else charge() @@ -108,23 +102,35 @@ Difficulty: Hard bloodspell.phased = 1 new/obj/item/device/gps/internal/bubblegum(src) +/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A) + if(charging) + return + ..() + /mob/living/simple_animal/hostile/megafauna/bubblegum/AttackingTarget() if(charging) return ..() +/mob/living/simple_animal/hostile/megafauna/bubblegum/Goto(target, delay, minimum_distance) + if(charging) + return + ..() + /mob/living/simple_animal/hostile/megafauna/bubblegum/Move() if(!stat) playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1) if(charging) PoolOrNew(/obj/effect/overlay/temp/decoy, list(loc,src)) - for(var/turf/T in range(src, 1)) - T.singularity_pull(src, 7) + DestroySurroundings() . = ..() + if(charging) + DestroySurroundings() /mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge() var/turf/T = get_step_away(target, src) charging = 1 + DestroySurroundings() PoolOrNew(/obj/effect/overlay/temp/dragon_swoop, T) sleep(5) throw_at(T, 7, 1, src, 0) @@ -135,7 +141,8 @@ Difficulty: Hard if(charging) if(istype(A, /turf) || istype(A, /obj) && A.density) A.ex_act(2) - ..() + DestroySurroundings() + ..() /mob/living/simple_animal/hostile/megafauna/bubblegum/throw_impact(atom/A) if(!charging) @@ -156,17 +163,25 @@ Difficulty: Hard /mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_warp() - var/found_bloodpool = FALSE + var/obj/effect/decal/cleanable/blood/found_bloodpool + var/list/pools = list() + var/can_jaunt = FALSE for(var/obj/effect/decal/cleanable/blood/nearby in view(src,2)) - found_bloodpool = TRUE + can_jaunt = TRUE + break + if(!can_jaunt) + return + for(var/obj/effect/decal/cleanable/blood/nearby in view(get_turf(target),2)) + pools += nearby + if(pools.len) + shuffle(pools) + found_bloodpool = pick(pools) if(found_bloodpool) - for(var/obj/effect/decal/cleanable/blood/H in view(target,2)) - visible_message("[src] sinks into the blood...") - playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1) - forceMove(get_turf(H)) - playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1) - visible_message("And springs back out!") - break + visible_message("[src] sinks into the blood...") + playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1) + forceMove(get_turf(found_bloodpool)) + playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1) + visible_message("And springs back out!") /mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_spray() @@ -174,8 +189,8 @@ Difficulty: Hard spawn(0) var/turf/E = get_edge_target_turf(src, src.dir) var/range = 10 - for(var/turf/open/J in getline(src,E)) - if(!range) + for(var/turf/J in getline(src,E)) + if(!range || J.density) break playsound(J,'sound/effects/splat.ogg', 100, 1, -1) new /obj/effect/decal/cleanable/blood(J) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 17a10a1789e..f1773486258 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -38,7 +38,6 @@ Difficulty: Very Hard faction = list("mining") weather_immunities = list("lava","ash") speak_emote = list("roars") - luminosity = 3 armour_penetration = 40 melee_damage_lower = 40 melee_damage_upper = 40 @@ -62,14 +61,9 @@ Difficulty: Very Hard var/anger_modifier = 0 var/obj/item/device/gps/internal - -/mob/living/simple_animal/hostile/megafauna/colossus/AttackingTarget() - ..() - if(isliving(target)) - var/mob/living/L = target - if(L.stat == DEAD) - src.visible_message("[src] disintegrates [L]!") - L.dust() +/mob/living/simple_animal/hostile/megafauna/colossus/devour(mob/living/L) + visible_message("[src] disintegrates [L]!") + L.dust() /mob/living/simple_animal/hostile/megafauna/colossus/OpenFire() anger_modifier = Clamp(((maxHealth - health)/50),0,20) @@ -81,11 +75,8 @@ Difficulty: Very Hard if(health < maxHealth/3) double_spiral() else - visible_message("\"Judgement.\"") - if(prob(50)) - spiral_shoot() - else - spiral_shoot(1) + visible_message("\"Judgement.\"") + spiral_shoot(rand(0, 1)) else if(prob(20)) ranged_cooldown = world.time + 30 @@ -96,13 +87,13 @@ Difficulty: Very Hard blast() else ranged_cooldown = world.time + 40 - diagonals() + dir_shots(diagonals) sleep(10) - cardinals() + dir_shots(cardinal) sleep(10) - diagonals() + dir_shots(diagonals) sleep(10) - cardinals() + dir_shots(cardinal) /mob/living/simple_animal/hostile/megafauna/colossus/New() @@ -140,49 +131,49 @@ Difficulty: Very Hard /mob/living/simple_animal/hostile/megafauna/colossus/proc/double_spiral() - visible_message("\"Die.\"") + visible_message("\"Die.\"") sleep(10) addtimer(src, "spiral_shoot", 0) addtimer(src, "spiral_shoot", 0, FALSE, 1) -/mob/living/simple_animal/hostile/megafauna/colossus/proc/spiral_shoot(negative = 0) - var/counter = 1 +/mob/living/simple_animal/hostile/megafauna/colossus/proc/spiral_shoot(negative = 0, counter_start = 1) + var/counter = counter_start var/turf/marker for(var/i in 1 to 80) switch(counter) if(1) - marker = locate(x,y - 2,z) + marker = locate(x, y - 2, z) if(2) - marker = locate(x - 1,y - 2,z) + marker = locate(x - 1, y - 2, z) if(3) - marker = locate(x - 2, y - 2,z) + marker = locate(x - 2, y - 2, z) if(4) - marker = locate(x - 2,y - 1,z) + marker = locate(x - 2, y - 1, z) if(5) - marker = locate (x -2 ,y,z) + marker = locate(x - 2, y, z) if(6) - marker = locate(x - 2, y+1,z) + marker = locate(x - 2, y + 1, z) if(7) marker = locate(x - 2, y + 2, z) if(8) - marker = locate(x - 1, y + 2,z) + marker = locate(x - 1, y + 2, z) if(9) - marker = locate(x, y + 2,z) + marker = locate(x, y + 2, z) if(10) - marker = locate(x + 1, y+2,z) + marker = locate(x + 1, y + 2, z) if(11) - marker = locate(x+ 2, y + 2,z) + marker = locate(x + 2, y + 2, z) if(12) - marker = locate(x+2,y+1,z) + marker = locate(x + 2, y + 1, z) if(13) - marker = locate(x+2,y,z) + marker = locate(x + 2, y, z) if(14) - marker = locate(x+2, y - 1, z) + marker = locate(x + 2, y - 1, z) if(15) - marker = locate(x+2, y - 2, z) + marker = locate(x + 2, y - 2, z) if(16) - marker = locate(x+1, y -2, z) + marker = locate(x + 1, y - 2, z) if(negative) counter-- @@ -193,43 +184,42 @@ Difficulty: Very Hard if(counter < 0) counter = 16 shoot_projectile(marker) + playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, 1) sleep(1) /mob/living/simple_animal/hostile/megafauna/colossus/proc/shoot_projectile(turf/marker) + if(!marker) + return var/turf/startloc = get_turf(src) var/obj/item/projectile/P = new /obj/item/projectile/colossus(startloc) - playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 100, 1) P.current = startloc P.starting = startloc P.firer = src P.yo = marker.y - startloc.y P.xo = marker.x - startloc.x - P.original = marker + if(target) + P.original = target + else + P.original = marker P.fire() /mob/living/simple_animal/hostile/megafauna/colossus/proc/random_shots() + playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 300, 1, 5) for(var/turf/turf in range(12,get_turf(src))) if(prob(5)) shoot_projectile(turf) /mob/living/simple_animal/hostile/megafauna/colossus/proc/blast() + playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 200, 1, 2) for(var/turf/turf in range(1, target)) shoot_projectile(turf) -/mob/living/simple_animal/hostile/megafauna/colossus/proc/diagonals() - var/turf/T = locate(x + 2, y + 2, z) - shoot_projectile(T) - T = locate(x + 2, y -2, z) - shoot_projectile(T) - T = locate(x - 2, y + 2, z) - shoot_projectile(T) - T = locate(x - 2, y - 2, z) - shoot_projectile(T) - -/mob/living/simple_animal/hostile/megafauna/colossus/proc/cardinals() - var/list/attack_dirs = list(NORTH,EAST,SOUTH,WEST) - for(var/d in attack_dirs) - var/turf/E = get_edge_target_turf(src, d) +/mob/living/simple_animal/hostile/megafauna/colossus/proc/dir_shots(list/dirs) + if(!islist(dirs)) + dirs = alldirs.Copy() + playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 200, 1, 2) + for(var/d in dirs) + var/turf/E = get_step(src, d) shoot_projectile(E) /mob/living/simple_animal/hostile/megafauna/colossus/proc/telegraph() @@ -253,7 +243,7 @@ Difficulty: Very Hard /obj/item/projectile/colossus/on_hit(atom/target, blocked = 0) . = ..() - if(istype(target,/turf/)||istype(target,/obj/structure/)) + if(isturf(target) || isobj(target)) target.ex_act(2) @@ -277,38 +267,37 @@ Difficulty: Very Hard max_n_of_items = 200 pixel_y = -4 use_power = 0 - var/duplicate = FALSE var/memory_saved = FALSE var/list/stored_items = list() - var/list/blacklist = (/obj/item/weapon/spellbook) + var/static/list/blacklist = typecacheof(list(/obj/item/weapon/spellbook)) /obj/machinery/smartfridge/black_box/accept_check(obj/item/O) - if(O.type in blacklist) - return - if(istype(O, /obj/item)) - return 1 - return 0 + if(!istype(O)) + return FALSE + if(is_type_in_typecache(O, blacklist)) + return FALSE + return TRUE /obj/machinery/smartfridge/black_box/New() - ..() - for(var/obj/machinery/smartfridge/black_box/B in machines) - if(B != src) - duplicate = 1 - qdel(src) + var/static/obj/machinery/smartfridge/black_box/current + if(current && current != src) + qdel(src, force=TRUE) + return + current = src ReadMemory() /obj/machinery/smartfridge/black_box/process() ..() - if(ticker.current_state == GAME_STATE_FINISHED && !memory_saved) + if(!memory_saved && ticker.current_state == GAME_STATE_FINISHED) WriteMemory() /obj/machinery/smartfridge/black_box/proc/WriteMemory() var/savefile/S = new /savefile("data/npc_saves/Blackbox.sav") stored_items = list() - for(var/obj/I in component_parts) - qdel(I) - for(var/obj/O in contents) + + for(var/obj/O in (contents-component_parts)) stored_items += O.type + S["stored_items"] << stored_items memory_saved = TRUE @@ -320,11 +309,17 @@ Difficulty: Very Hard stored_items = list() for(var/item in stored_items) - new item(src) + create_item(item) +//in it's own proc to avoid issues with items that nolonger exist in the code base. +//try catch doesn't always prevent byond runtimes from halting a proc, +/obj/machinery/smartfridge/black_box/proc/create_item(item_type) + new item_type(src) -/obj/machinery/smartfridge/black_box/Destroy() - if(duplicate) +/obj/machinery/smartfridge/black_box/Destroy(force = FALSE) + if(force) + for(var/thing in src) + qdel(thing) return ..() else return QDEL_HINT_LETMELIVE @@ -349,4 +344,4 @@ Difficulty: Very Hard /obj/machinery/smartfridge/black_box/default_deconstruction_crowbar() return -#undef MEDAL_PREFIX \ No newline at end of file +#undef MEDAL_PREFIX diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm index a8b8f8ad6ef..5ef1f66e386 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm @@ -39,7 +39,6 @@ Difficulty: Medium faction = list("mining") weather_immunities = list("lava","ash") speak_emote = list("roars") - luminosity = 3 armour_penetration = 40 melee_damage_lower = 40 melee_damage_upper = 40 @@ -82,13 +81,20 @@ Difficulty: Medium return ..() /mob/living/simple_animal/hostile/megafauna/dragon/AttackingTarget() - if(swooping) - return - else + if(!swooping) + ..() + +/mob/living/simple_animal/hostile/megafauna/dragon/DestroySurroundings() + if(!swooping) + ..() + +/mob/living/simple_animal/hostile/megafauna/dragon/Move() + if(!swooping) + ..() + +/mob/living/simple_animal/hostile/megafauna/dragon/Goto(target, delay, minimum_distance) + if(!swooping) ..() - if(isliving(target)) - var/mob/living/L = target - devour(L) /mob/living/simple_animal/hostile/megafauna/dragon/Process_Spacemove(movement_dir = 0) return 1 @@ -166,19 +172,16 @@ Difficulty: Medium PoolOrNew(/obj/effect/overlay/temp/target, turf) /mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_walls() - var/list/attack_dirs = list(NORTH,EAST,SOUTH,WEST) - if(prob(50)) - attack_dirs = list(NORTH,WEST,SOUTH,EAST) playsound(get_turf(src),'sound/magic/Fireball.ogg', 200, 1) - for(var/d in attack_dirs) + for(var/d in cardinal) addtimer(src, "fire_wall", 0, FALSE, d) -/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_wall(d) - var/turf/E = get_edge_target_turf(src, d) +/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_wall(dir) + var/turf/E = get_edge_target_turf(src, dir) var/range = 10 - for(var/turf/open/J in getline(src,E)) - if(!range) + for(var/turf/J in getline(src,E)) + if(!range || J.density) break range-- PoolOrNew(/obj/effect/hotspot,J) @@ -220,7 +223,7 @@ Difficulty: Medium tturf = get_turf(src) forceMove(tturf) PoolOrNew(/obj/effect/overlay/temp/dragon_swoop, tturf) - animate(src, pixel_x = 0, pixel_z = 0, time = 10) + animate(src, pixel_x = initial(pixel_x), pixel_z = 0, time = 10) sleep(10) playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1) for(var/mob/living/L in orange(1, src)) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm index 03a47675615..aee55f946cd 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -39,7 +39,7 @@ Difficulty: Medium retreat_distance = 5 minimum_distance = 5 ranged_cooldown_time = 20 - var/size = 10 + var/size = 5 var/charging = 0 medal_type = MEDAL_PREFIX score_type = LEGION_SCORE @@ -50,15 +50,24 @@ Difficulty: Medium elimination = 1 aggro_vision_range = 18 idle_vision_range = 13 + appearance_flags = 0 /mob/living/simple_animal/hostile/megafauna/legion/New() ..() new/obj/item/device/gps/internal/legion(src) +/mob/living/simple_animal/hostile/megafauna/legion/AttackingTarget() + ..() + if(ishuman(target)) + var/mob/living/L = target + if(L.stat == UNCONSCIOUS) + var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(loc) + A.infest(L) + /mob/living/simple_animal/hostile/megafauna/legion/OpenFire(the_target) if(world.time >= ranged_cooldown && !charging) if(prob(75)) - var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(src.loc) + var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(loc) A.GiveTarget(target) A.friends = friends A.faction = faction @@ -81,27 +90,27 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/legion/death() if(health > 0) return - if(size > 2) + if(size > 1) adjustHealth(-maxHealth) //heal ourself to full in prep for splitting - var/mob/living/simple_animal/hostile/megafauna/legion/L = new(src.loc) + var/mob/living/simple_animal/hostile/megafauna/legion/L = new(loc) L.maxHealth = maxHealth * 0.6 maxHealth = L.maxHealth L.health = L.maxHealth - health = L.health + health = maxHealth - L.size = size - 2 - size = L.size + size-- + L.size = size - var/size_multiplier = L.size * 0.08 - L.resize = size_multiplier - resize = L.resize + L.resize = L.size * 0.2 + transform = initial(transform) + resize = size * 0.2 L.update_transform() update_transform() - L.target = target + L.GiveTarget(target) visible_message("[src] splits in twain!") else @@ -111,10 +120,10 @@ Difficulty: Medium last_legion = FALSE break if(last_legion) - src.loot = list(/obj/item/weapon/staff/storm) + loot = list(/obj/item/weapon/staff/storm) elimination = 0 else if(prob(5)) - src.loot = list(/obj/structure/closet/crate/necropolis/tendril) + loot = list(/obj/structure/closet/crate/necropolis/tendril) ..() /mob/living/simple_animal/hostile/megafauna/legion/Process_Spacemove(movement_dir = 0) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index e93e1435211..c68f310fda4 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -9,9 +9,11 @@ a_intent = "harm" sentience_type = SENTIENCE_BOSS environment_smash = 3 + obj_damage = 75 + luminosity = 3 weather_immunities = list("lava","ash") robust_searching = 1 - stat_attack = 1 + stat_attack = 2 atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 maxbodytemp = INFINITY @@ -43,6 +45,16 @@ else ..() +/mob/living/simple_animal/hostile/megafauna/AttackingTarget() + ..() + if(isliving(target)) + var/mob/living/L = target + if(L.stat != DEAD) + if(ranged && ranged_cooldown <= world.time) + OpenFire() + else + devour(L) + /mob/living/simple_animal/hostile/megafauna/onShuttleMove() var/turf/oldloc = loc . = ..() @@ -55,12 +67,11 @@ ([newloc.x],[newloc.y],[newloc.z])") /mob/living/simple_animal/hostile/megafauna/proc/devour(mob/living/L) - if(L.stat == DEAD) - src.visible_message( - "[src] devours [L]!", - "You feast on [L], restoring your health!") - adjustBruteLoss(-L.maxHealth/2) - L.gib() + visible_message( + "[src] devours [L]!", + "You feast on [L], restoring your health!") + adjustBruteLoss(-L.maxHealth/2) + L.gib() /mob/living/simple_animal/hostile/megafauna/ex_act(severity, target) switch (severity) 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 7433759b3f7..b725347ac4a 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm @@ -817,19 +817,22 @@ robust_searching = 1 /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/Life() - if(isturf(src.loc)) + if(isturf(loc)) for(var/mob/living/carbon/human/H in view(src,1)) //Only for corpse right next to/on same tile if(H.stat == UNCONSCIOUS) - visible_message("[src.name] burrows into the flesh of [H]!") - var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/L = new(H.loc) - visible_message("[L] staggers to their feet!") - H.death() - H.adjustBruteLoss(1000) - L.stored_mob = H - H.forceMove(L) - qdel(src) + infest(H) ..() +/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/proc/infest(mob/living/carbon/human/H) + visible_message("[name] burrows into the flesh of [H]!") + var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/L = new(H.loc) + visible_message("[L] staggers to their feet!") + H.death() + H.adjustBruteLoss(1000) + L.stored_mob = H + H.forceMove(L) + qdel(src) + /obj/item/organ/hivelord_core/legion name = "legion's soul" desc = "A strange rock that still crackles with power... its \ diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index dc9793ae3ab..23455487021 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -34,6 +34,8 @@ icon_living = "parrot_fly" icon_dead = "parrot_dead" density = 0 + health = 80 + maxHealth = 80 pass_flags = PASSTABLE | PASSMOB speak = list("Hi!","Hello!","Cracker?","BAWWWWK george mellons griffing me!") @@ -148,6 +150,8 @@ if(speech_buffer.len >= 500) speech_buffer -= pick(speech_buffer) speech_buffer |= html_decode(raw_message) + if(speaker == src && !client) //If a parrot squawks in the woods and no one is around to hear it, does it make a sound? This code says yes! + return message ..() /mob/living/simple_animal/parrot/radio(message, message_mode, list/spans) //literally copied from human/radio(), but there's no other way to do this. at least it's better than it used to be. @@ -286,7 +290,7 @@ parrot_interest = M parrot_state = PARROT_SWOOP //The parrot just got hit, it WILL move, now to pick a direction.. - if(M.health < 50) //Weakened mob? Fight back! + if(health > 30) //Let's get in there and squawk it up! parrot_state |= PARROT_ATTACK else parrot_state |= PARROT_FLEE //Otherwise, fly like a bat out of hell! @@ -325,8 +329,8 @@ parrot_interest = user parrot_state = PARROT_SWOOP - if (user.health < 50) - parrot_state |= PARROT_ATTACK //weakened mob? fight back! + if(health > 30) //Let's get in there and squawk it up! + parrot_state |= PARROT_ATTACK else parrot_state |= PARROT_FLEE icon_state = "parrot_fly" @@ -902,7 +906,7 @@ /mob/living/simple_animal/parrot/Poly/death(gibbed) if(!memory_saved) var/go_ghost = 0 - if(rounds_survived == longest_survival || rounds_survived == longest_deathstreak) + if(rounds_survived == longest_survival || rounds_survived == longest_deathstreak || prob(0.666)) go_ghost = 1 rounds_survived = min(--rounds_survived,0) if(rounds_survived < longest_deathstreak) @@ -948,7 +952,26 @@ memory_saved = 1 //At this point nothing is saved ..() +/mob/living/simple_animal/parrot/Poly/ghost/handle_automated_speech() + if(ismob(loc)) + return + ..() + /mob/living/simple_animal/parrot/Poly/ghost/handle_automated_movement() if(isliving(parrot_interest)) - parrot_interest = null + if(!ishuman(parrot_interest)) + parrot_interest = null + else if(parrot_state == (PARROT_SWOOP | PARROT_ATTACK) && Adjacent(parrot_interest)) + walk_to(src, parrot_interest, 0, parrot_speed) + Possess(parrot_interest) ..() + +/mob/living/simple_animal/parrot/Poly/ghost/proc/Possess(mob/living/carbon/human/H) + if(!ishuman(H)) + return + var/datum/disease/parrot_possession/P = new + P.parrot = src + loc = H + H.ContractDisease(P) + parrot_interest = null + H.visible_message("[src] dive bombs into [H]'s chest and vanishes!", "[src] dive bombs into your chest, vanishing! This can't be good!") \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index c772dbef96e..abc97e1c958 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -43,6 +43,7 @@ //LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly var/melee_damage_lower = 0 var/melee_damage_upper = 0 + var/obj_damage = 0 //how much damage this simple animal does to objects, if any var/armour_penetration = 0 //How much armour they ignore, as a flat reduction from the targets armour value var/melee_damage_type = BRUTE //Damage type of a simple mob's melee attack, should it do damage. var/list/damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) // 1 for full damage , 0 for none , -1 for 1:1 heal from that source diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 6977e73153f..84ec266f47d 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -28,7 +28,7 @@ var/next_mob_id = 0 hud_list = list() for(var/hud in hud_possible) var/image/I = image('icons/mob/hud.dmi', src, "") - I.appearance_flags = RESET_COLOR + I.appearance_flags = RESET_COLOR|RESET_TRANSFORM hud_list[hud] = I /mob/proc/Cell() diff --git a/code/modules/paperwork/contract.dm b/code/modules/paperwork/contract.dm index 9974737affd..5817b793899 100644 --- a/code/modules/paperwork/contract.dm +++ b/code/modules/paperwork/contract.dm @@ -3,7 +3,7 @@ /obj/item/weapon/paper/contract throw_range = 3 throw_speed = 3 - var/signed = 0 + var/signed = FALSE var/datum/mind/target flags = NOBLUDGEON @@ -107,7 +107,7 @@ ..() /obj/item/weapon/paper/contract/infernal/update_text() - info = "This shouldn't be seen. Error DEVIL:5" + info = "This shouldn't be seen. Error DEVIL:6" /obj/item/weapon/paper/contract/infernal/power/update_text(var/signature = "____________") info = "
Contract for infernal power



I, [target] of sound mind, do hereby willingly offer my soul to the infernal hells by way of the infernal agent [owner.devilinfo.truename], in exchange for power and physical strength. I understand that upon my demise, my soul shall fall into the infernal hells, and my body may not be resurrected, cloned, or otherwise brought back to life. I also understand that this will prevent my brain from being used in an MMI.


Signed, [signature]" @@ -143,25 +143,28 @@ /obj/item/weapon/paper/contract/infernal/attack(mob/M, mob/living/user) add_fingerprint(user) - if(M == user && target == M.mind && M.mind.soulOwner == M.mind && attempt_signature(user)) + if(M == user && target == M.mind && M.mind.soulOwner != owner && attempt_signature(user)) user.visible_message("[user] slices their wrist with [src], and scrawls their name in blood.", "You slice your wrist open and scrawl your name in blood.") user.blood_volume = max(user.blood_volume - 10, 0) else return ..() /obj/item/weapon/paper/contract/infernal/proc/attempt_signature(mob/living/carbon/human/user) - if(user.IsAdvancedToolUser()) + if(user.IsAdvancedToolUser() && user.is_literate()) if(user.mind == target) - if(user.mind.soulOwner == user.mind) + if(user.mind.soulOwner != owner) if (contractType == CONTRACT_REVIVE) user << "You are already alive, this contract would do nothing." else - user << "You quickly scrawl your name on the contract" - if(FulfillContract()<=0) - user << "But it seemed to have no effect, perhaps even Hell itself cannot grant this boon?" - return 1 + if(signed) + user<< "This contract has already been signed. It may not be signed again." + else + user << "You quickly scrawl your name on the contract" + if(FulfillContract()<=0) + user << "But it seemed to have no effect, perhaps even Hell itself cannot grant this boon?" + return 1 else - user << "You are not in possession of your soul, you may not sell it." + user << "This devil already owns your soul, you may not sell it to them again." else user << "Your signature simply slides off the sheet, it seems this contract is not meant for you to sign." else @@ -196,6 +199,8 @@ /obj/item/weapon/paper/contract/infernal/proc/FulfillContract(mob/living/carbon/human/user = target.current) signed = 1 + if(user.mind.soulOwner != user.mind) //They already sold their soul to someone else? + user.mind.soulOwner.devilinfo.remove_soul(user.mind) //Then they lose their claim. user.mind.soulOwner = owner user.hellbound = contractType user.mind.damnation_type = contractType diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 719cdf539cc..1ccf0aa5068 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -84,6 +84,7 @@ c.info += "" c.name = copy.name c.fields = copy.fields + c.update_icon() c.updateinfolinks() toner-- busy = 1 @@ -174,13 +175,13 @@ updateUsrDialog() else if(href_list["remove"]) if(copy) - remove_photocopy(copy) + remove_photocopy(copy, usr) copy = null else if(photocopy) - remove_photocopy(photocopy) + remove_photocopy(photocopy, usr) photocopy = null else if(doccopy) - remove_photocopy(doccopy) + remove_photocopy(doccopy, usr) doccopy = null else if(check_ass()) ass << "You feel a slight pressure on your ass." @@ -255,7 +256,7 @@ if(!user.drop_item()) return copy = O - do_insertion(O) + do_insertion(O, user) else user << "There is already something in [src]!" @@ -264,7 +265,7 @@ if(!user.drop_item()) return photocopy = O - do_insertion(O) + do_insertion(O, user) else user << "There is already something in [src]!" @@ -273,7 +274,7 @@ if(!user.drop_item()) return doccopy = O - do_insertion(O) + do_insertion(O, user) else user << "There is already something in [src]!" diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 7004b0afcc9..52b39bc2737 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -258,9 +258,9 @@ holding = "They are holding \a [L.r_hand]" if(!mob_detail) - mob_detail = "You can see [L] on the photo[L.health < (0.75 * L.maxHealth) ? " - [L] looks hurt":""].[holding ? " [holding]":"."]. " + mob_detail = "You can see [L] on the photo[L.health < (L.maxHealth * 0.75) ? " - [L] looks hurt":""].[holding ? " [holding]":"."]. " else - mob_detail += "You can also see [L] on the photo[L.health < (0.75 * L.maxHealth) ? " - [L] looks hurt":""].[holding ? " [holding]":"."]." + mob_detail += "You can also see [L] on the photo[L.health < (L.maxHealth * 0.75) ? " - [L] looks hurt":""].[holding ? " [holding]":"."]." return mob_detail diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index d57d136d73c..0c93c9835d0 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -36,7 +36,7 @@ narsie_spawn_animation() sleep(70) - SSshuttle.emergency.request(null, 0.3) // Cannot recall + SSshuttle.emergency.request(null, 0.1) // Cannot recall /obj/singularity/narsie/large/attack_ghost(mob/dead/observer/user as mob) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index dd774d3d2bb..9ce067c1575 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -10,6 +10,7 @@ layer = MASSIVE_OBJ_LAYER luminosity = 6 unacidable = 1 //Don't comment this out. + appearance_flags = 0 var/current_size = 1 var/allowed_size = 1 var/contained = 1 //Are we going to move around? diff --git a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm index bfd3032126a..4d07342051d 100644 --- a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm +++ b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm @@ -17,6 +17,17 @@ T.air.copy_from_turf(T) SSair.add_to_active(T) +/datum/mapGeneratorModule/bottomLayer/massdelete + spawnableAtoms = list() + spawnableTurfs = list() + +/datum/mapGeneratorModule/bottomLayer/massdelete/generate() + if(!mother) + return + for(var/V in mother.map) + var/turf/T = V + T.empty() + //Only places atoms/turfs on area borders /datum/mapGeneratorModule/border clusterCheckFlags = CLUSTER_CHECK_NONE @@ -37,4 +48,7 @@ return 0 /datum/mapGenerator/repressurize - modules = list(/datum/mapGeneratorModule/bottomLayer/repressurize) \ No newline at end of file + modules = list(/datum/mapGeneratorModule/bottomLayer/repressurize) + +/datum/mapGenerator/massdelete + modules = list(/datum/mapGeneratorModule/bottomLayer/massdelete) \ No newline at end of file diff --git a/code/modules/procedural_mapping/mapGenerators/cult.dm b/code/modules/procedural_mapping/mapGenerators/cult.dm new file mode 100644 index 00000000000..c76a611b7e8 --- /dev/null +++ b/code/modules/procedural_mapping/mapGenerators/cult.dm @@ -0,0 +1,31 @@ +/datum/mapGeneratorModule/bottomLayer/cultFloor + spawnableTurfs = list(/turf/open/floor/engine/cult = 100) + +/datum/mapGeneratorModule/border/cultWalls + spawnableTurfs = list(/turf/closed/wall/mineral/cult = 100) + + +/datum/mapGeneratorModule/bottomLayer/clockFloor + spawnableTurfs = list(/turf/open/floor/clockwork = 100) + +/datum/mapGeneratorModule/border/clockWalls + spawnableTurfs = list(/turf/closed/wall/clockwork = 100) + + +/datum/mapGenerator/cult //walls and floor only + modules = list(/datum/mapGeneratorModule/bottomLayer/cultFloor, \ + /datum/mapGeneratorModule/border/cultWalls, \ + /datum/mapGeneratorModule/bottomLayer/repressurize) + +/datum/mapGenerator/clock //walls and floor only + modules = list(/datum/mapGeneratorModule/bottomLayer/clockFloor, \ + /datum/mapGeneratorModule/border/clockWalls, \ + /datum/mapGeneratorModule/bottomLayer/repressurize) + +/datum/mapGenerator/cult/floor //floors only + modules = list(/datum/mapGeneratorModule/bottomLayer/cultFloor, \ + /datum/mapGeneratorModule/bottomLayer/repressurize) + +/datum/mapGenerator/clock/floor //floor only + modules = list(/datum/mapGeneratorModule/bottomLayer/clockFloor, \ + /datum/mapGeneratorModule/bottomLayer/repressurize) \ No newline at end of file diff --git a/code/modules/projectiles/guns/projectile/laser_gatling.dm b/code/modules/projectiles/guns/projectile/laser_gatling.dm index ea192206003..35210e78702 100644 --- a/code/modules/projectiles/guns/projectile/laser_gatling.dm +++ b/code/modules/projectiles/guns/projectile/laser_gatling.dm @@ -124,11 +124,11 @@ else qdel(src) -/obj/item/weapon/gun/projectile/minigun/shoot_live_shot(mob/living/user as mob|obj, pointblank = 0, mob/pbtarget = null, message = 1) +/obj/item/weapon/gun/projectile/minigun/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override) if(ammo_pack) if(ammo_pack.overheat < ammo_pack.overheat_max) - . = ..() - ammo_pack.overheat++ + ammo_pack.overheat += burst_size + ..() else user << "The gun's heat sensor locked the trigger to prevent lens damage." @@ -141,9 +141,9 @@ if(!ammo_pack) if(istype(loc,/obj/item/weapon/minigunpack)) //We should spawn inside a ammo pack so let's use that one. ammo_pack = loc + ..() else qdel(src)//No pack, no gun - ..() /obj/item/weapon/gun/projectile/minigun/dropped(mob/living/user) ammo_pack.attach_gun(user) diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 9175a77ff76..420e20bcdfa 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -128,17 +128,11 @@ damage_type = BRUTE flag = "bomb" range = 3 - var/splash = 0 /obj/item/projectile/kinetic/super damage = 11 range = 4 -/obj/item/projectile/kinetic/hyper - damage = 12 - range = 5 - splash = 1 - /obj/item/projectile/kinetic/New() var/turf/proj_turf = get_turf(src) if(!istype(proj_turf, /turf)) @@ -146,37 +140,44 @@ var/datum/gas_mixture/environment = proj_turf.return_air() var/pressure = environment.return_pressure() if(pressure < 50) - name = "full strength kinetic force" + name = "full strength [name]" damage *= 4 ..() /obj/item/projectile/kinetic/on_range() - new /obj/effect/kinetic_blast(src.loc) + PoolOrNew(/obj/effect/overlay/temp/kinetic_blast, loc) ..() /obj/item/projectile/kinetic/on_hit(atom/target) - . = ..() var/turf/target_turf= get_turf(target) if(istype(target_turf, /turf/closed/mineral)) var/turf/closed/mineral/M = target_turf M.gets_drilled(firer) - new /obj/effect/kinetic_blast(target_turf) - if(src.splash) - for(var/turf/T in range(splash, target_turf)) - if(istype(T, /turf/closed/mineral)) - var/turf/closed/mineral/M = T - M.gets_drilled(firer) + PoolOrNew(/obj/effect/overlay/temp/kinetic_blast, target_turf) + . = ..() - -/obj/effect/kinetic_blast +/obj/item/projectile/kinetic/hyper name = "kinetic explosion" - icon = 'icons/obj/projectiles.dmi' - icon_state = "kinetic_blast" - layer = ABOVE_ALL_MOB_LAYER + damage = 12 + range = 5 -/obj/effect/kinetic_blast/New() - spawn(4) - qdel(src) +/obj/item/projectile/kinetic/hyper/proc/aoe_blast(atom/target) + var/turf/target_turf = get_turf(target) + if(!target_turf) + target_turf = get_turf(src) + PoolOrNew(/obj/effect/overlay/temp/explosion, target_turf) + for(var/T in RANGE_TURFS(1, target_turf) - target_turf) + if(istype(T, /turf/closed/mineral)) + var/turf/closed/mineral/M = T + M.gets_drilled(firer) + +/obj/item/projectile/kinetic/hyper/on_range() + aoe_blast() + ..() + +/obj/item/projectile/kinetic/hyper/on_hit(atom/target) + aoe_blast(target) + . = ..() /obj/item/projectile/beam/wormhole name = "bluespace beam" @@ -221,7 +222,7 @@ icon_state = "plasmacutter" damage_type = BRUTE damage = 5 - range = 5 + range = 3.5 //works as 4, but doubles to 7 /obj/item/projectile/plasma/New() var/turf/proj_turf = get_turf(src) @@ -231,8 +232,9 @@ if(environment) var/pressure = environment.return_pressure() if(pressure < 60) - name = "full strength plasma blast" + name = "full strength [name]" damage *= 4 + range *= 2 ..() /obj/item/projectile/plasma/on_hit(atom/target) @@ -246,11 +248,11 @@ /obj/item/projectile/plasma/adv damage = 7 - range = 7 + range = 5 /obj/item/projectile/plasma/adv/mech damage = 10 - range = 8 + range = 6 /obj/item/projectile/gravityrepulse diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index de7d764437b..98a58b3efb0 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -188,9 +188,6 @@ if("emote") M.visible_message("[M] [pick("whimpers quietly", "shivers as though cold", "glances around in paranoia")].") if(data >= 75) // 30 units, 135 seconds - if (!M.confused) - M.confused = 1 - M.confused += 3 if(iscultist(M) || is_handofgod_cultist(M) || is_handofgod_prophet(M) || is_servant_of_ratvar(M)) if(iscultist(M)) ticker.mode.remove_cultist(M.mind, 1, 1) @@ -198,12 +195,11 @@ ticker.mode.remove_hog_follower(M.mind) else if(is_servant_of_ratvar(M)) remove_servant_of_ratvar(M) - holder.remove_reagent(src.id, src.volume) // maybe this is a little too perfect and a max() cap on the statuses would be better?? + holder.remove_reagent(id, volume) // maybe this is a little too perfect and a max() cap on the statuses would be better?? M.jitteriness = 0 M.stuttering = 0 - M.confused = 0 return - holder.remove_reagent(src.id, 0.4) //fixed consumption to prevent balancing going out of whack + holder.remove_reagent(id, 0.4) //fixed consumption to prevent balancing going out of whack /datum/reagent/water/holywater/reaction_turf(turf/T, reac_volume) ..() @@ -1231,3 +1227,26 @@ datum/reagent/romerol // Silently add the zombie infection organ to be activated upon death new /obj/item/organ/body_egg/zombie_infection(H) ..() + +/datum/reagent/growthserum + name = "Growth serum" + id = "growthserum" + description = "A commercial chemical designed to help older men in the bedroom."//not really it just makes you a giant + color = "#ff0000"//strong red. rgb 255, 0, 0 + var/current_size = 1 + +/datum/reagent/growthserum/on_mob_life(mob/living/carbon/H) + if(volume >= 20 && current_size != 2) + H.resize = 2/current_size + current_size = 2 + H.update_transform() + else if (current_size != 1.5) + H.resize = 1.5/current_size + current_size = 1.5 + H.update_transform() + ..() + +/datum/reagent/growthserum/on_mob_delete(mob/living/M) + M.resize = 1/current_size + M.update_transform() + ..() diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index 59e03a95b58..8d2f17106e7 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -34,7 +34,8 @@ other types of metals and chemistry for reagents). var/build_type = null //Flag as to what kind machine the design is built in. See defines. var/list/materials = list() //List of materials. Format: "id" = amount. var/construction_time //Amount of time required for building the object - var/build_path = "" //The file path of the object that gets created + var/build_path = null //The file path of the object that gets created + var/list/make_reagents = list() //Reagents produced. Format: "id" = amount. Currently only supported by the biogenerator. var/list/category = null //Primarily used for Mech Fabricators, but can be used for anything var/list/reagents = list() //List of reagents. Format: "id" = amount. var/maxstack = 1 diff --git a/code/modules/research/designs/biogenerator_designs.dm b/code/modules/research/designs/biogenerator_designs.dm new file mode 100644 index 00000000000..bbac5bda92b --- /dev/null +++ b/code/modules/research/designs/biogenerator_designs.dm @@ -0,0 +1,212 @@ +/////////////////////////////////// +///////Biogenerator Designs /////// +/////////////////////////////////// + +/datum/design/milk + name = "10 milk" + id = "milk" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 20) + make_reagents = list("milk" = 10) + category = list("initial","Food") + +/datum/design/cream + name = "10 cream" + id = "cream" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 30) + make_reagents = list("cream" = 10) + category = list("initial","Food") + +/datum/design/milk_carton + name = "Milk carton" + id = "milk_carton" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 100) + build_path = /obj/item/weapon/reagent_containers/food/condiment/milk + category = list("initial","Food") + +/datum/design/cream_carton + name = "Cream carton" + id = "cream_carton" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 300) + build_path = /obj/item/weapon/reagent_containers/food/drinks/bottle/cream + category = list("initial","Food") + +/datum/design/black_pepper + name = "10u black pepper" + id = "black_pepper" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 25) + make_reagents = list("blackpepper" = 10) + category = list("initial","Food") + +/datum/design/pepper_mill + name = "Pepper mill" + id = "pepper_mill" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 50) + build_path = /obj/item/weapon/reagent_containers/food/condiment/peppermill + make_reagents = list() + category = list("initial","Food") + +/datum/design/monkey_cube + name = "Monkey cube" + id = "mcube" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 250) + build_path = /obj/item/weapon/reagent_containers/food/snacks/monkeycube + category = list("initial", "Food") + +/datum/design/ez_nut + name = "E-Z-Nutrient" + id = "ez_nut" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 10) + build_path = /obj/item/weapon/reagent_containers/glass/bottle/nutrient/ez + category = list("initial","Botany Chemicals") + +/datum/design/l4z_nut + name = "Left 4 Zed" + id = "l4z_nut" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 20) + build_path = /obj/item/weapon/reagent_containers/glass/bottle/nutrient/l4z + category = list("initial","Botany Chemicals") + +/datum/design/rh_nut + name = "Robust Harvest" + id = "rh_nut" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 25) + build_path = /obj/item/weapon/reagent_containers/glass/bottle/nutrient/rh + category = list("initial","Botany Chemicals") + +/datum/design/weed_killer + name = "Weed Killer" + id = "weed_killer" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 50) + build_path = /obj/item/weapon/reagent_containers/glass/bottle/killer/weedkiller + category = list("initial","Botany Chemicals") + +/datum/design/pest_spray + name = "Pest Killer" + id = "pest_spray" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 50) + build_path = /obj/item/weapon/reagent_containers/glass/bottle/killer/pestkiller + category = list("initial","Botany Chemicals") + +/datum/design/botany_bottle + name = "Empty Bottle" + id = "botany_bottle" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 5) + build_path = /obj/item/weapon/reagent_containers/glass/bottle/nutrient/empty + category = list("initial", "Botany Chemicals") + +/datum/design/cloth + name = "Roll of cloth" + id = "cloth" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 50) + build_path = /obj/item/stack/sheet/cloth + category = list("initial","Leather and Cloth") + +/datum/design/wallet + name = "Wallet" + id = "wallet" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 100) + build_path = /obj/item/weapon/storage/wallet + category = list("initial","Leather and Cloth") + +/datum/design/botany_gloves + name = "Botanical gloves" + id = "botany_gloves" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 250) + build_path = /obj/item/clothing/gloves/botanic_leather + category = list("initial","Leather and Cloth") + +/datum/design/toolbelt + name = "Utility Belt" + id = "toolbelt" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 300) + build_path = /obj/item/weapon/storage/belt/utility + category = list("initial","Leather and Cloth") + +/datum/design/secbelt + name = "Security belt" + id = "secbelt" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 300) + build_path = /obj/item/weapon/storage/belt/security + category = list("initial","Leather and Cloth") + +/datum/design/medbelt + name = "Medical belt" + id = "medbel" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 300) + build_path = /obj/item/weapon/storage/belt/medical + category = list("initial","Leather and Cloth") + +/datum/design/janibelt + name = "Janitorial belt" + id = "janibelt" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 300) + build_path = /obj/item/weapon/storage/belt/janitor + category = list("initial","Leather and Cloth") + +/datum/design/bandolier + name = "Bandolier belt" + id = "bandolier" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 300) + build_path = /obj/item/weapon/storage/belt/bandolier + category = list("initial","Leather and Cloth") + +/datum/design/s_holster + name = "Shoulder holster" + id = "s_holster" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 400) + build_path = /obj/item/weapon/storage/belt/holster + category = list("initial","Leather and Cloth") + +/datum/design/leather_satchel + name = "Leather satchel" + id = "leather_satchel" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 400) + build_path = /obj/item/weapon/storage/backpack/satchel + category = list("initial","Leather and Cloth") + +/datum/design/leather_jacket + name = "Leather jacket" + id = "leather_jacket" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 500) + build_path = /obj/item/clothing/suit/jacket/leather + category = list("initial","Leather and Cloth") + +/datum/design/leather_overcoat + name = "Leather overcoat" + id = "leather_overcoat" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 1000) + build_path = /obj/item/clothing/suit/jacket/leather/overcoat + category = list("initial","Leather and Cloth") + +/datum/design/rice_hat + name = "Rice hat" + id = "rice_hat" + build_type = BIOGENERATOR + materials = list(MAT_BIOMASS = 300) + build_path = /obj/item/clothing/head/rice_hat + category = list("initial","Leather and Cloth") diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index e599fc862c2..70141a7e14d 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -287,6 +287,16 @@ build_path = /obj/item/weapon/implantcase category = list("Medical Designs") +/datum/design/implant_sadtrombone + name = "Sad Trombone Implant Case" + desc = "Makes death amusing." + id = "implant_trombone" + req_tech = list("materials" = 2, "biotech" = 3, "programming" = 2) + build_type = PROTOLATHE + materials = list(MAT_GLASS = 500, MAT_BANANIUM = 500) + build_path = /obj/item/weapon/implantcase/sad_trombone + category = list("Medical Designs") + /datum/design/implant_freedom name = "Freedom Implant Case" desc = "A glass case containing an implant." diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index e51445ce616..4a186f05f22 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -341,6 +341,9 @@ won't update every console in existence) but it's more of a hassle to do. Also, var/datum/design/being_built = files.known_designs[href_list["build"]] var/amount = text2num(href_list["amount"]) + if(being_built.make_reagents.len) + return 0 + if(!linked_lathe || !being_built || !amount) updateUsrDialog() return @@ -682,6 +685,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(b_type & PROTOLATHE) dat += "Protolathe
" if(b_type & AUTOLATHE) dat += "Autolathe
" if(b_type & MECHFAB) dat += "Exosuit Fabricator
" + if(b_type & BIOGENERATOR) dat += "Biogenerator
" dat += "Required Materials:
" var/all_mats = d_disk.blueprint.materials + d_disk.blueprint.reagents for(var/M in all_mats) diff --git a/code/modules/research/research.dm b/code/modules/research/research.dm index 13b165cb61c..e96df1dca9f 100644 --- a/code/modules/research/research.dm +++ b/code/modules/research/research.dm @@ -148,6 +148,22 @@ research holder datum. return ..() +//Biogenerator files +/datum/research/biogenerator/New() + for(var/T in (subtypesof(/datum/tech))) + possible_tech += new T(src) + for(var/path in subtypesof(/datum/design)) + var/datum/design/D = new path(src) + possible_designs += D + if((D.build_type & BIOGENERATOR) && ("initial" in D.category)) + AddDesign2Known(D) + +/datum/research/biogenerator/AddDesign2Known(datum/design/D) + if(!(D.build_type & BIOGENERATOR)) + return + ..() + + /*************************************************************** ** Technology Datums ** ** Includes all the various technoliges and what they make. ** diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 90749a39bc0..6d254521789 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -184,7 +184,7 @@ user << "You offer the sentience potion to [SM]..." being_used = 1 - var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [SM.name]?", ROLE_ALIEN, null, ROLE_ALIEN, 50) + var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [SM.name]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm var/mob/dead/observer/theghost = null if(candidates.len) theghost = pick(candidates) diff --git a/code/modules/spells/spell_types/devil.dm b/code/modules/spells/spell_types/devil.dm index 87e1d2fcd24..cd00b67776b 100644 --- a/code/modules/spells/spell_types/devil.dm +++ b/code/modules/spells/spell_types/devil.dm @@ -23,9 +23,11 @@ pitchfork = new pitchfork_type C.put_in_hands(pitchfork) -/obj/effect/proc_holder/spell/targeted/summon_pitchfork/Del() +/obj/effect/proc_holder/spell/targeted/summon_pitchfork/Destroy() if(pitchfork) qdel(pitchfork) + pitchfork = null + return ..() /obj/effect/proc_holder/spell/targeted/summon_pitchfork/greater pitchfork_type = /obj/item/weapon/twohanded/pitchfork/demonic/greater @@ -108,12 +110,17 @@ if(istype(user)) if(istype(user.loc, /obj/effect/dummy/slaughter/)) var/continuing = 0 - for(var/mob/living/C in orange(2, get_turf(user.loc))) - if (C.mind && C.mind.soulOwner == C.mind) - continuing = 1 - break + if(istype(get_area(user), /area/shuttle/)) // Can always phase in in a shuttle. + continuing = 1 + else + for(var/mob/living/C in orange(2, get_turf(user.loc))) //Can also phase in when nearby a potential buyer. + if (C.mind && C.mind.soulOwner == C.mind) + continuing = 1 + break if(continuing) - addtimer(user,"infernalphasein",150,TRUE) + user << "You are now phasing in." + if(do_mob(user,user,150)) + user.infernalphasein() else user << "You can only re-appear near a potential signer." revert_cast() @@ -122,21 +129,22 @@ user.notransform = 1 user.fakefire() src << "You begin to phase back into sinful flames." - addtimer(user, "infernalphaseout",150,TRUE,get_turf(user)) + if(do_mob(user,user,150)) + user.infernalphaseout() + else + user << "You must remain still while exiting." + user.ExtinguishMob() start_recharge() return revert_cast() -/mob/living/proc/infernalphaseout(var/turf/mobloc) - if(get_turf(src) != mobloc) - src << "You must remain still while exiting." - return +/mob/living/proc/infernalphaseout() dust_animation() spawn_dust() src.visible_message("[src] disappears in a flashfire!") playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1) - var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,mobloc) + var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,loc) src.ExtinguishMob() if(buckled) buckled.unbuckle_mob(src,force=1) diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index 82952e7b157..09a02d973cf 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -5,6 +5,7 @@ force = 3 throwforce = 3 icon_state = "" + layer = BELOW_MOB_LAYER //so it isn't hidden behind objects when on the floor var/mob/living/carbon/human/owner = null var/status = ORGAN_ORGANIC var/body_zone //"chest", "l_arm", etc , used for def_zone @@ -38,6 +39,8 @@ if(burn_dam > 0) user << "This limb has [burn_dam > 30 ? "severe" : "minor"] burns." +/obj/item/bodypart/blob_act() + take_damage(max_damage) /obj/item/bodypart/Destroy() if(owner) diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index a8fd5059658..16c742fc6fd 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -4,7 +4,6 @@ max_damage = 200 body_zone = "head" body_part = HEAD - layer = ABOVE_MOB_LAYER //so it isn't hidden behind some objects when on the floor w_class = 4 //Quite a hefty load slowdown = 1 //Balancing measure throw_range = 2 //No head bowling diff --git a/code/modules/uplink/uplink.dm b/code/modules/uplink/uplink.dm index 20156b750b4..a1b9bf984ad 100644 --- a/code/modules/uplink/uplink.dm +++ b/code/modules/uplink/uplink.dm @@ -27,6 +27,28 @@ var/global/list/uplinks = list() uplinks -= src return ..() +/obj/item/device/uplink/attackby(obj/item/I, mob/user, params) + for(var/item in subtypesof(/datum/uplink_item)) + var/datum/uplink_item/UI = item + var/path = null + if(initial(UI.refund_path)) + path = initial(UI.refund_path) + else + path = initial(UI.item) + var/cost = 0 + if(initial(UI.refund_amount)) + cost = initial(UI.refund_amount) + else + cost = initial(UI.cost) + var/refundable = initial(UI.refundable) + if(I.type == path && refundable && I.check_uplink_validity()) + telecrystals += cost + spent_telecrystals -= cost + user << "[I] refunded." + qdel(I) + return + ..() + /obj/item/device/uplink/interact(mob/user) active = TRUE ui_interact(user) @@ -89,18 +111,7 @@ var/global/list/uplinks = list() // Refund certain items by hitting the uplink with it. /obj/item/device/radio/uplink/attackby(obj/item/I, mob/user, params) - for(var/item in subtypesof(/datum/uplink_item)) - var/datum/uplink_item/UI = item - var/path = initial(UI.item) - var/cost = initial(UI.cost) - var/refundable = initial(UI.refundable) - if(I.type == path && refundable) - hidden_uplink.telecrystals += cost - hidden_uplink.spent_telecrystals -= cost - user << "[I] refunded." - qdel(I) - return - ..() + return hidden_uplink.attackby(I, user, params) // A collection of pre-set uplinks, for admin spawns. /obj/item/device/radio/uplink/New() diff --git a/code/modules/uplink/uplink_item.dm b/code/modules/uplink/uplink_item.dm index 1f212b7b602..db0d86a9863 100644 --- a/code/modules/uplink/uplink_item.dm +++ b/code/modules/uplink/uplink_item.dm @@ -44,7 +44,9 @@ var/list/uplink_items = list() // Global list so we only initialize this once. var/category = "item category" var/desc = "item description" var/item = null // Path to the item to spawn. + var/refund_path = null // Alternative path for refunds, in case the item purchased isn't what is actually refunded (ie: holoparasites). var/cost = 0 + var/refund_amount = 0 // specified refund amount in case there needs to be a TC penalty for refunds. var/refundable = FALSE var/surplus = 100 // Chance of being included in the surplus crate. var/list/include_modes = list() // Game modes to allow this item in. diff --git a/code/modules/vehicles/scooter.dm b/code/modules/vehicles/scooter.dm index 3e0e50bdf07..64223336da1 100644 --- a/code/modules/vehicles/scooter.dm +++ b/code/modules/vehicles/scooter.dm @@ -44,7 +44,7 @@ if(M.get_num_legs() < 2) vehicle_move_delay ++ if(M.get_num_arms() <= 0) - if(buckled_mobs.len)//to prevent the message displaying twice due to unbuckling + if(has_buckled_mobs())//to prevent the message displaying twice due to unbuckling M << "Your limbless body flops off \the [src]." unbuckle_mob(M) diff --git a/config/game_options.txt b/config/game_options.txt index 696eb46c1f8..798460b4c1b 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -96,6 +96,8 @@ PROBABILITY RAGINMAGES 2 PROBABILITY MONKEY 0 PROBABILITY METEOR 0 PROBABILITY EXTENDED 0 +PROBABILITY DEVIL 0 +PROBABILITY DEVIL_AGENTS 0 ## You probably want to keep sandbox off by default for secret and random. PROBABILITY SANDBOX 0 diff --git a/html/changelog.html b/html/changelog.html index aa1c2db4ae8..66adece3046 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,129 @@ -->
+

05 August 2016

+

Arctophylax updated:

+
    +
  • The Emergency Medical and Winter Wonderland Holodeck programs work once again.
  • +
+

Cruix updated:

+
    +
  • RCDs can no longer place multiple grilles on the same tile.
  • +
  • RCDs will no longer use all their ammo if you try to build a wall on the same turf multiple times.
  • +
  • RCDs will now inform their user if they do not have enough ammo to complete an operation.
  • +
+

Incoming5643 updated:

+
    +
  • Parrots have been made more robust.
  • +
+

Joan updated:

+
    +
  • Clockwork Constructs, including anima fragments, marauders, and reclaimers, can now communicate over the Hierophant Network.
  • +
  • Plasma cutters(normal, advanced, and mech) now have double range in low pressure areas, but slightly lower range in high pressure areas.
  • +
  • Vitality Matrices will consume dead non-servant mobs to gain a large amount of Vitality. This doesn't work on mobs that did not have a mind at some point.
  • +
+

Lordpidey and PKPenguin321 updated:

+
    +
  • Recent studies have revealed that fly amanita can give you a huge trip.
  • +
+

Lzimann updated:

+
    +
  • Holy water no longers makes you confused.
  • +
+

ModernViolence updated:

+
    +
  • Photocopier fixes: proper sprites for not empty copies; removing originals now does not delete them
  • +
+

PKPenguin321 updated:

+
    +
  • Chef, do your station a favor and make a home run baseball burger (TM)
  • +
+

Robustin updated:

+
    +
  • The initial supply talisman can now be used to create runed metal, 5 per use
  • +
  • The void torch is now available from the altar, use it to transport any item instantly to any cultist! It appears alongside the veil shifter as part of the "Veil Walker" set.
  • +
  • Cult floors no longer appear on mesons!
  • +
  • Flagellant's Robes now increases damage taken by 50%, down from 100%
  • +
  • Veil Shifter has 4 uses, up from 2
  • +
  • Shuttle curse now delays shuttle 3 minutes, up from 2.5 minutes
  • +
  • Cult forges, archives, and airlocks have had their cost reduced by 1 runed metal each
  • +
+

Shadowlight213 updated:

+
    +
  • You will now receive an achievement for winning a pulse rifle at the arcade.
  • +
+

TheCarlSaganExpress updated:

+
    +
  • Added lighting effects to the welder.
  • +
+ +

02 August 2016

+

CoreOverload updated:

+
    +
  • Pockets in coats!
  • +
+ +

01 August 2016

+

Bawhoppen updated:

+
    +
  • Added crowns. Make them from gold. Cap gets a fancy one.
  • +
+

Fox McCloud updated:

+
    +
  • Adds in generic uplink refund system that potentially allows for even regular traitors to refund uplink items
  • +
+

Joan updated:

+
    +
  • Soul Vessels can now be used on unconscious or dead humans to extract their consciousness, much like a soulstone.
  • +
  • Soul Vessels no longer automatically ping ghosts when created, though they can still be used in-hand to ping ghosts.
  • +
  • Soul Vessels can now communicate over the Hierophant Network
  • +
  • Xenobiology golems enslaved to someone will become convertable if their enslaver is converted to the enslaving antag type; this applies to gang and both cult types.
  • +
+

oranges updated:

+
    +
  • Reverted toolboxes fitting in backpacks due to being incorrectly merged
  • +
+ +

31 July 2016

+

Arctophylax updated:

+
    +
  • Birdboat's atmospheric tanks now function normally again.
  • +
  • Birdboat's TEG is now orientated to match the pipe layout.
  • +
+

Bawhoppen updated:

+
    +
  • toolboxes fit in backpacks
  • +
+

Gun Hog updated:

+
    +
  • In an effort to reduce the demoralizing effects that accompany the death of a crew member, Nanotrasen has provided the prototype designs for the Sad Trombone implant. It can be fabricated at your station's protolathe, if you manage to secure the ever elusive Bananium ore.
  • +
+

Joan updated:

+
    +
  • Megafauna will now seek and consume corpses of enemies to heal or otherwise.
  • +
  • Toolboxes are slightly more robust.
  • +
  • Vanguard now only stuns for 25% of absorbed stuns, from 50%.
  • +
+

Kor updated:

+
    +
  • Hostile mobs will now attack turrets.
  • +
+

Robustin updated:

+
    +
  • Amber ERT Commanders no longer have thermal goggles
  • +
+

lordpidey updated:

+
    +
  • Added Devil agent gamemode, where multiple devils are each trying to buy more souls than the next in line.
  • +
  • If you've already sold your soul, you can sell it again to a different devil. You can even go back and forth for INFINITE POWER.
  • +
+ +

30 July 2016

+

astralenigma updated:

+
    +
  • Admins can now turn people into red god.
  • +
+

28 July 2016

Cruix updated:

    @@ -1158,127 +1281,6 @@
  • The cloning pod now sounds robotic on the radio.
  • For extra observer drama, ghosts can now visibly see the countdown of syndicate bombs, nuclear devices, cloning pods, gang dominators and AI doomsday devices.
- -

02 June 2016

-

Joan updated:

-
    -
  • Closed false walls will block air.
  • -
-

Lati updated:

-
    -
  • R&D required levels and origin tech levels have been rebalanced
  • -
  • Overall, items buildable in R&D have lower tech levels and items in other departments have their tech levels raised. Remember to use science goggles to see tech levels of items!
  • -
  • There are now level gates at high levels. R&D scientists will need help from others to get past these level gates.
  • -
  • Other departments such as hydroponics and genetics will be important to R&D's progress now and xenobio, mining and cargo are more important than before
  • -
  • Efficiency upgrades are back in R&D machines and tweaked to be less powerful in autolathes
  • -
  • Reliability has been removed from all items
  • -
  • Most bugs in R&D machines should be fixed
  • -
-

PKPenguin321 & Nienhaus updated:

-
    -
  • Letterman jackets are now available from the ClothesMate.
  • -
-

Quiltyquilty updated:

-
    -
  • The bar has seen a redesign.
  • -
-

coiax updated:

-
    -
  • Clone pods now notify the medical channel on a successful clone. They also notify the medical channel if the clone dies or is horribly mutilated; but not if it is ejected early by authorised medical personnel.
  • -
  • Cloning pods now are more capable of cloning humanoid species that do not breathe.
  • -
  • You can only be damaged once by a shuttle's arrival. It is still unpleasant to be in the path of one though; try to avoid it.
  • -
  • Adds Asteroid emergency shuttle to shuttle templates. It is a very oddly shaped one though, it might not be compatible with all stations.
  • -
  • The Chaplain soulshard can only turn a body into a shade once. A released shade can still be reabsorbed by the stone to heal it.
  • -
  • The shuttle manipulator now has a Fast Travel button, for those admins that really want a shuttle to get to where its going FAST.
  • -
- -

01 June 2016

-

coiax updated:

-
    -
  • Added a mirror to the beach biodome. Beach Bums, rejoyce!
  • -
-

pudl updated:

-
    -
  • The brig infirmary has received a redesign.
  • -
- -

31 May 2016

-

CoreOverload updated:

-
    -
  • Cleanbot software was updated to version 1.2, improving pathfinding and adding two new cleaning options: "Clean Trash" and "Exterminate Pests".
  • -
  • New cleaning options are still experimental and disabled by default.
  • -
-

Kiazusho updated:

-
    -
  • Changeling organic suit and chitin armor can be toggled off once again.
  • -
-

Kor updated:

-
    -
  • The Japanese Animes button is back,
  • -
  • The chaplain has three new weapons: The possessed blade, the extra-dimensional blade, and the nautical energy sword. The former has a new power, the latter two are normal sword reskins.
  • -
  • The chapel mass driver has been buffed.
  • -
-

coiax updated:

-
    -
  • Zombies can no longer be butchered
  • -
  • If you encounter an infectious zombie, be cautious, its claws will infect you, and on death you will rise with them. If you manage to kill the beast, you can remove the corruption from its brain via surgery, or just chop off the head to stop it coming back.
  • -
  • Adds some stock computers and lavaland to Birdboat Station.
  • -
  • Free Golem scientists have proved that as beings made out of stone, golems are immune to all electrical discharges, including the tesla.
  • -
  • Nuclear bombs are now points of interest. Never miss a borg steal a nuke from the syndicate shuttle again!
  • -
  • Alt-clicking a spraycan toggles the cap.
  • -
- -

30 May 2016

-

coiax updated:

-
    -
  • A new Shuttle Manipulator verb has been added for quick access to probably the best and most mostly bugfree feature on /tg/.
  • -
  • Spectral sword is now a point of interest for ghosts.
  • -
  • Clicking the spectral sword action now orbits the sword, instead of just teleporting to its location.
  • -
  • Gang tags can again be sprayed over.
  • -
  • Fixes bug where the wisp was unable to be recalled to the lantern.
  • -
-

xxalpha updated:

-
    -
  • Engineering, CE and Atmos hardsuits no longer have in-built jetpacks.
  • -
- -

29 May 2016

-

GunHog updated:

-
    -
  • The CE, RD, and CMO have been issued megaphones.
  • -
-

Paprika, Crystalwarrior, Korphaeron and Bawhoppen updated:

-
    -
  • Pixel projectiles. This is easier to see than explain, so go fire a weapon.
  • -
-

Xhuis updated:

-
    -
  • Ratvar and Nar-Sie now actively seek each other out if they both exist.
  • -
  • Celestial gateway animations have been twweaked.
  • -
  • Ratvar now has a new sound and message upon spawning.
  • -
  • Ratvar now only moves one tile at a time.
  • -
  • The celestial gateway now takes an unreasonably long amount of time.
  • -
  • God clashing is now much more likely to work properly.
  • -
  • Function Call now works as intended.
  • -
  • Break Will now works as intended.
  • -
  • Holy water now properly deconverts servants of Ratvar.
  • -
  • Deconverted servants of Ratvar are no longer considered servants.
  • -
-

pudl updated:

-
    -
  • Chemicals should now have color, instead of just being pink.
  • -
- -

27 May 2016

-

coiax updated:

-
    -
  • Gatling gun removed from R&D for pressing ceremonial reasons.
  • -
-

phil235 updated:

-
    -
  • Pull and Grab are merged together. Pulling stays unchanged. Using an empty hand with grab intent on a mob will pull them. Using an empty hand with grab intent on a mob that you're already pulling will try to upgrade your grip to aggressive grab>neck grab>kill grab. Aggressive grabs no longer stun you, but they act exactly like a handcuff, preventing you from using your hands until you escape the grip. You can break free from the grip by trying to move or using the resist button.
  • -
  • Someone pulling a restrained mob now swap position with them instead of getting blocked by the mob, unable to even push them.
  • -
GoonStation 13 Development Team diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index a8d4c827c2a..77ccf1466d9 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -6398,3 +6398,94 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. Warranty void if used in combat. incoming5643: - tweak: viscerator grenades are now more generous with viscerators spawned +2016-07-30: + astralenigma: + - bugfix: Admins can now turn people into red god. +2016-07-31: + Arctophylax: + - bugfix: Birdboat's atmospheric tanks now function normally again. + - bugfix: Birdboat's TEG is now orientated to match the pipe layout. + Bawhoppen: + - tweak: toolboxes fit in backpacks + Gun Hog: + - rscadd: In an effort to reduce the demoralizing effects that accompany the death + of a crew member, Nanotrasen has provided the prototype designs for the Sad + Trombone implant. It can be fabricated at your station's protolathe, if you + manage to secure the ever elusive Bananium ore. + Joan: + - rscadd: Megafauna will now seek and consume corpses of enemies to heal or otherwise. + - tweak: Toolboxes are slightly more robust. + - tweak: Vanguard now only stuns for 25% of absorbed stuns, from 50%. + Kor: + - rscadd: Hostile mobs will now attack turrets. + Robustin: + - rscdel: Amber ERT Commanders no longer have thermal goggles + lordpidey: + - rscadd: Added Devil agent gamemode, where multiple devils are each trying to buy + more souls than the next in line. + - rscadd: If you've already sold your soul, you can sell it again to a different + devil. You can even go back and forth for INFINITE POWER. +2016-08-01: + Bawhoppen: + - rscadd: Added crowns. Make them from gold. Cap gets a fancy one. + Fox McCloud: + - rscadd: Adds in generic uplink refund system that potentially allows for even + regular traitors to refund uplink items + Joan: + - rscadd: Soul Vessels can now be used on unconscious or dead humans to extract + their consciousness, much like a soulstone. + - tweak: Soul Vessels no longer automatically ping ghosts when created, though they + can still be used in-hand to ping ghosts. + - rscadd: Soul Vessels can now communicate over the Hierophant Network + - experiment: Xenobiology golems enslaved to someone will become convertable if + their enslaver is converted to the enslaving antag type; this applies to gang + and both cult types. + oranges: + - rscdel: Reverted toolboxes fitting in backpacks due to being incorrectly merged +2016-08-02: + CoreOverload: + - rscadd: Pockets in coats! +2016-08-05: + Arctophylax: + - bugfix: The Emergency Medical and Winter Wonderland Holodeck programs work once + again. + Cruix: + - bugfix: RCDs can no longer place multiple grilles on the same tile. + - bugfix: RCDs will no longer use all their ammo if you try to build a wall on the + same turf multiple times. + - tweak: RCDs will now inform their user if they do not have enough ammo to complete + an operation. + Incoming5643: + - rscadd: Parrots have been made more robust. + Joan: + - rscadd: Clockwork Constructs, including anima fragments, marauders, and reclaimers, + can now communicate over the Hierophant Network. + - rscadd: Plasma cutters(normal, advanced, and mech) now have double range in low + pressure areas, but slightly lower range in high pressure areas. + - rscadd: Vitality Matrices will consume dead non-servant mobs to gain a large amount + of Vitality. This doesn't work on mobs that did not have a mind at some point. + Lordpidey and PKPenguin321: + - rscadd: Recent studies have revealed that fly amanita can give you a huge trip. + Lzimann: + - tweak: Holy water no longers makes you confused. + ModernViolence: + - bugfix: 'Photocopier fixes: proper sprites for not empty copies; removing originals + now does not delete them' + PKPenguin321: + - rscadd: Chef, do your station a favor and make a home run baseball burger (TM) + Robustin: + - rscadd: The initial supply talisman can now be used to create runed metal, 5 per + use + - rscadd: The void torch is now available from the altar, use it to transport any + item instantly to any cultist! It appears alongside the veil shifter as part + of the "Veil Walker" set. + - rscadd: Cult floors no longer appear on mesons! + - tweak: Flagellant's Robes now increases damage taken by 50%, down from 100% + - tweak: Veil Shifter has 4 uses, up from 2 + - tweak: Shuttle curse now delays shuttle 3 minutes, up from 2.5 minutes + - tweak: Cult forges, archives, and airlocks have had their cost reduced by 1 runed + metal each + Shadowlight213: + - rscadd: You will now receive an achievement for winning a pulse rifle at the arcade. + TheCarlSaganExpress: + - rscadd: Added lighting effects to the welder. diff --git a/html/changelogs/AutoChangeLog-pr-19538.yml b/html/changelogs/AutoChangeLog-pr-19538.yml deleted file mode 100644 index d2871020acd..00000000000 --- a/html/changelogs/AutoChangeLog-pr-19538.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "astralenigma" -delete-after: True -changes: - - bugfix: "Admins can now turn people into red god." diff --git a/html/changelogs/AutoChangeLog-pr-19689.yml b/html/changelogs/AutoChangeLog-pr-19689.yml new file mode 100644 index 00000000000..187e26af3e7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-19689.yml @@ -0,0 +1,4 @@ +author: "Joan" +delete-after: True +changes: + - tweak: "Barrier runes will now block air while active." diff --git a/html/changelogs/AutoChangeLog-pr-19699.yml b/html/changelogs/AutoChangeLog-pr-19699.yml new file mode 100644 index 00000000000..eea3c038a88 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-19699.yml @@ -0,0 +1,4 @@ +author: "Joan" +delete-after: True +changes: + - rscadd: "Trying to use sleeping carp against the colossus will now anger it." diff --git a/html/changelogs/AutoChangeLog-pr-19712.yml b/html/changelogs/AutoChangeLog-pr-19712.yml new file mode 100644 index 00000000000..c02e028baef --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-19712.yml @@ -0,0 +1,4 @@ +author: "Arctophylax" +delete-after: True +changes: + - bugfix: "You can unbuckle mobs from meat spikes by clicking on the spike once again." diff --git a/icons/mob/alienqueen.dmi b/icons/mob/alienqueen.dmi index dfe9c7fa619..488368dbf19 100644 Binary files a/icons/mob/alienqueen.dmi and b/icons/mob/alienqueen.dmi differ diff --git a/icons/mob/broadMobs.dmi b/icons/mob/broadMobs.dmi new file mode 100644 index 00000000000..1aad8a1e302 Binary files /dev/null and b/icons/mob/broadMobs.dmi differ diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi index f68b23f4ba2..9966a7913d2 100644 Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 88a70a45f82..ef46ca2181d 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/lavaland/96x96megafauna.dmi b/icons/mob/lavaland/96x96megafauna.dmi index fab005c7167..e13419532df 100644 Binary files a/icons/mob/lavaland/96x96megafauna.dmi and b/icons/mob/lavaland/96x96megafauna.dmi differ diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi index aab1b6d478c..5ad8fccd2e2 100644 Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index 99c91e4ea0c..4efdf2e78f6 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi index 60d5aa34bf5..9a98ffa9df8 100644 Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ diff --git a/icons/obj/food/burgerbread.dmi b/icons/obj/food/burgerbread.dmi index b7e1165b674..843a6cd508b 100644 Binary files a/icons/obj/food/burgerbread.dmi and b/icons/obj/food/burgerbread.dmi differ diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi index 8fa90258c6f..2d62ed154d4 100644 Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi index 12f0a9ab281..fb49e6d364c 100644 Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index 4de812785b1..f6b8fdb5f35 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/icons/turf/walls/shuttle_wall.dmi b/icons/turf/walls/shuttle_wall.dmi index 63a2010e344..91ffab3407a 100644 Binary files a/icons/turf/walls/shuttle_wall.dmi and b/icons/turf/walls/shuttle_wall.dmi differ diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm index f0d121f97dc..b99addac573 100644 --- a/interface/stylesheet.dm +++ b/interface/stylesheet.dm @@ -70,6 +70,7 @@ h1.alert, h2.alert {color: #000000;} .cultitalic {color: #960000; font-style: italic;} .cultlarge {color: #960000; font-weight: bold; font-size: 3;} .narsie {color: #960000; font-weight: bold; font-size: 15;} +.colossus {color: #7F282A; font-size: 5;} .purple {color: #5e2d79;} .holoparasite {color: #35333a;} .holoparasitebold {color: #35333a; font-weight: bold;} diff --git a/tgstation.dme b/tgstation.dme index 0f984328612..139d11d51c3 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -90,6 +90,7 @@ #include "code\_globalvars\lists\mobs.dm" #include "code\_globalvars\lists\names.dm" #include "code\_globalvars\lists\objects.dm" +#include "code\_globalvars\lists\poll_ignore.dm" #include "code\_onclick\_defines.dm" #include "code\_onclick\adjacent.dm" #include "code\_onclick\ai.dm" @@ -194,6 +195,7 @@ #include "code\datums\diseases\fluspanish.dm" #include "code\datums\diseases\gbs.dm" #include "code\datums\diseases\magnitis.dm" +#include "code\datums\diseases\parrotpossession.dm" #include "code\datums\diseases\pierrot_throat.dm" #include "code\datums\diseases\retrovirus.dm" #include "code\datums\diseases\rhumba_beat.dm" @@ -342,7 +344,9 @@ #include "code\game\gamemodes\devil\devil.dm" #include "code\game\gamemodes\devil\devil_game_mode.dm" #include "code\game\gamemodes\devil\devilinfo.dm" +#include "code\game\gamemodes\devil\game_mode.dm" #include "code\game\gamemodes\devil\objectives.dm" +#include "code\game\gamemodes\devil\devil agent\devil_agent.dm" #include "code\game\gamemodes\devil\imp\imp.dm" #include "code\game\gamemodes\devil\true_devil\_true_devil.dm" #include "code\game\gamemodes\devil\true_devil\inventory.dm" @@ -1048,6 +1052,7 @@ #include "code\modules\clothing\under\shorts.dm" #include "code\modules\clothing\under\syndicate.dm" #include "code\modules\clothing\under\ties.dm" +#include "code\modules\clothing\under\trek.dm" #include "code\modules\clothing\under\jobs\civilian.dm" #include "code\modules\clothing\under\jobs\engineering.dm" #include "code\modules\clothing\under\jobs\medsci.dm" @@ -1632,6 +1637,7 @@ #include "code\modules\procedural_mapping\mapGeneratorModules\nature.dm" #include "code\modules\procedural_mapping\mapGenerators\asteroid.dm" #include "code\modules\procedural_mapping\mapGenerators\cellular.dm" +#include "code\modules\procedural_mapping\mapGenerators\cult.dm" #include "code\modules\procedural_mapping\mapGenerators\lava_river.dm" #include "code\modules\procedural_mapping\mapGenerators\nature.dm" #include "code\modules\procedural_mapping\mapGenerators\shuttle.dm" @@ -1730,6 +1736,7 @@ #include "code\modules\research\stock_parts.dm" #include "code\modules\research\designs\AI_module_designs.dm" #include "code\modules\research\designs\autolathe_designs.dm" +#include "code\modules\research\designs\biogenerator_designs.dm" #include "code\modules\research\designs\comp_board_designs.dm" #include "code\modules\research\designs\machine_designs.dm" #include "code\modules\research\designs\mecha_designs.dm" diff --git a/tools/mapmerge/README.md b/tools/mapmerge/README.md index 78993824965..d8d696d8939 100644 --- a/tools/mapmerge/README.md +++ b/tools/mapmerge/README.md @@ -1,3 +1,4 @@ +#Map Merger# Before any change to a map, it is good to use the Map Merger tools. In a nutshell, it rewrites the map to minimize differences between different versions of the map (DreamMakers map editor rewrites a lot of the tile keys). This makes the git diff between different map changes much smaller. More recently a new way of laying out the map was invented by Remie, called TGM, this helps to further reduce conflicts in the map files. This is good for a few reasons @@ -9,29 +10,28 @@ This is good for a few reasons However - to do all this is going to require you to put some elbow grease into understanding the map merger tool. -If you have difficulty using these tools, ask for help in [[Community|#coderbus]] +If you have difficulty using these tools, ask for help in #coderbus +#Using the tools# -'''1. Install Python 3.5 or greater''' +##1. Install Python 3.5 or greater## If you don't have Python already installed it can be downloaded from: https://www.python.org/downloads/ - make sure you grab the latest python 3, again, it must be 3.5 or greater +##2. PATH Python## +This step is mostly applicable to windows users, you must make sure you ask the windows installer to add python to your path, [like shown in this example screenshot](https://file.house/DA6H.png) -'''2. PATH Python''' -This step is mostly applicable to windows users, you must make sure you ask the windows installer to add python to your path. - -This image shows the correct setting to ensure is set https://file.house/DA6H.png - -'''3. Prepare Maps''' +If you have already installed python you may need to manually add it to your path as indicated in [this guide](http://superuser.com/questions/143119/how-to-add-python-to-the-windows-path) +##3. Prepare Maps## Run "Prepare Maps.bat" in the tools/mapmerge/ directory. - -'''4. Edit your map''' +##4. Edit your map## Make your changes to the map here. Remember to save them! - -'''5. Clean map''' -Run "Run Map Merge - TGM.bat" in the tools/mapmerge/ directory. - -'''7. Check differences''' +##5. Clean map## +Run "Run Map Merge - TGM.bat" in the tools/mapmerge/ directory. +##7. Check differences## Use your git application of choice to look at the differences between revisions of your code and commit the result. +##8. Commit## +Your map is now ready to be committed, rejoice and wait for conflicts. -'''8. Commit''' -Your map is now ready to be committed, rejoice and wait for conflicts. - +#Common pitfalls# +Open the map in dreameditor before committing the results of the mapmerger - this can cause dreameditor to resave the map back to +dmm, if you're having issues with your map getting stuck in dmm mode, try comitting and pushing the mapmerger changes before +reopening in dreameditor.