diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index dcd2c47cb2..919915b820 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -515,10 +515,13 @@ /turf/closed/wall, /area/security/main) "abq" = ( -/turf/closed/wall, +/turf/closed/wall/r_wall, /area/crew_quarters/heads/hos) "abr" = ( /obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/preopen{ + id = "hos" + }, /turf/open/floor/plating, /area/crew_quarters/heads/hos) "abs" = ( @@ -846,8 +849,13 @@ }, /obj/structure/table/wood, /obj/item/reagent_containers/food/drinks/bottle/vodka/badminka, -/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass, -/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass, +/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass{ + pixel_x = -5; + pixel_y = 5 + }, +/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass{ + pixel_x = -5 + }, /turf/open/floor/carpet, /area/crew_quarters/heads/hos) "abX" = ( @@ -1449,6 +1457,9 @@ "adm" = ( /obj/structure/disposalpipe/segment, /obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/preopen{ + id = "hos" + }, /turf/open/floor/plating, /area/crew_quarters/heads/hos) "adn" = ( @@ -1674,6 +1685,11 @@ /obj/structure/cable{ icon_state = "4-8" }, +/obj/machinery/button/door{ + id = "hos"; + name = "HoS Office Shutters"; + pixel_y = -25; + }, /turf/open/floor/carpet, /area/crew_quarters/heads/hos) "adN" = ( @@ -2053,6 +2069,9 @@ "aex" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/preopen{ + id = "hos" + }, /turf/open/floor/plating, /area/crew_quarters/heads/hos) "aey" = ( @@ -56882,12 +56901,6 @@ /obj/item/pen, /turf/open/floor/plasteel/white, /area/science/circuit) -"ium" = ( -/mob/living/simple_animal/bot/cleanbot{ - name = "C.L.E.A.N." - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) "izv" = ( /obj/machinery/vending/clothing, /obj/machinery/light/small{ @@ -57122,6 +57135,12 @@ }, /turf/open/floor/plating, /area/construction/mining/aux_base) +"lKX" = ( +/mob/living/simple_animal/bot/cleanbot{ + name = "C.L.E.A.N." + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "lMg" = ( /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -88468,7 +88487,7 @@ aaa aaf aaf aaa -abp +adR abP aco acO @@ -88982,7 +89001,7 @@ aaa aaa aaf aaa -abp +adR abO acq acq @@ -89496,15 +89515,15 @@ aaa aaa aaa aaf -abp +adR abR abP abP abP abP -abp -abp -abp +adR +adR +adR agA afU ahF @@ -94188,7 +94207,7 @@ blm bmL boi bpw -ium +lKX bsx btX bvj diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index f4b388daff..fc8e7dda2f 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -266,6 +266,15 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE GLOBAL_LIST_INIT(pda_styles, list(MONO, VT, ORBITRON, SHARE)) +//pda icon reskins +#define PDA_SKIN_CLASSIC "Classic" +#define PDA_SKIN_ALT "Holographic" +#define PDA_SKIN_RUGGED "Rugged" +#define PDA_SKIN_MODERN "Modern" + +GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_SKIN_ALT = 'icons/obj/pda_alt.dmi', + PDA_SKIN_RUGGED = 'icons/obj/pda_rugged.dmi', PDA_SKIN_MODERN = 'icons/obj/pda_modern.dmi')) + //Color Defines #define OOC_COLOR "#002eb8" #define AOOC_COLOR "#b8002e" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index b42cbb8f00..d490a76611 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -112,6 +112,8 @@ #define TRAIT_PARALYSIS_R_ARM "para-r-arm" #define TRAIT_PARALYSIS_L_LEG "para-l-leg" #define TRAIT_PARALYSIS_R_LEG "para-r-leg" +#define TRAIT_STRONG_GRABBER "strong_grabber" +#define TRAIT_CALCIUM_HEALER "calcium_healer" //non-mob traits #define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 51c814a5f9..9eb5400c52 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -170,7 +170,7 @@ "balls_amount" = 2, "balls_sack_size" = BALLS_SACK_SIZE_DEF, "balls_size" = BALLS_SIZE_DEF, - "balls_shape" = "Pair", + "balls_shape" = "Single", "balls_cum_rate" = CUM_RATE, "balls_cum_mult" = CUM_RATE_MULT, "balls_efficiency" = CUM_EFFICIENCY, diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm index cf7a7f192c..96f04cd403 100644 --- a/code/_globalvars/lists/maintenance_loot.dm +++ b/code/_globalvars/lists/maintenance_loot.dm @@ -44,6 +44,7 @@ GLOBAL_LIST_INIT(maintenance_loot, list( /obj/item/flashlight = 4, /obj/item/flashlight/pen = 1, /obj/item/flashlight/glowstick/random = 4, + /obj/effect/spawner/lootdrop/mre = 3, /obj/item/multitool = 2, /obj/item/radio/off = 2, /obj/item/t_scanner = 5, diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm index fa0ecf117d..e7b2ae6cbe 100644 --- a/code/_globalvars/misc.dm +++ b/code/_globalvars/misc.dm @@ -18,3 +18,12 @@ GLOBAL_LIST_EMPTY(powernets) GLOBAL_VAR_INIT(bsa_unlock, FALSE) //BSA unlocked by head ID swipes GLOBAL_LIST_EMPTY(player_details) // ckey -> /datum/player_details + +// All religion stuff +GLOBAL_VAR(religion) +GLOBAL_VAR(deity) +GLOBAL_VAR(bible_name) +GLOBAL_VAR(bible_icon_state) +GLOBAL_VAR(bible_item_state) +GLOBAL_VAR(holy_weapon_type) +GLOBAL_VAR(holy_armor_type) \ No newline at end of file diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 0c01468712..7a495b95e7 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -23,6 +23,9 @@ return next_click = world.time + 1 + if(!can_interact_with(A)) + return + if(multicam_on) var/turf/T = get_turf(A) if(T) @@ -60,7 +63,6 @@ controlled_mech.click_action(A, src, params) //Override AI normal click behavior. return - return if(modifiers["shift"]) ShiftClickOn(A) return diff --git a/code/controllers/subsystem/religion.dm b/code/controllers/subsystem/religion.dm deleted file mode 100644 index 1c3cd76da4..0000000000 --- a/code/controllers/subsystem/religion.dm +++ /dev/null @@ -1,11 +0,0 @@ -SUBSYSTEM_DEF(religion) - name = "Religion" - flags = SS_NO_FIRE|SS_NO_INIT - - var/religion - var/deity - var/bible_name - var/bible_icon_state - var/bible_item_state - var/holy_weapon_type - var/holy_armor_type diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index 06857c0f55..b2b03fb56b 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -117,6 +117,16 @@ description = "I'm missing my family heirloom...\n" mood_change = -4 +/datum/mood_event/loud_gong + description = "That loud gong noise really hurt my ears!\n" + mood_change = -3 + timeout = 1200 + +/datum/mood_event/spooked + description = "The rattling of those bones...It still haunts me.\n" + mood_change = -4 + timeout = 2400 + //These are unused so far but I want to remember them to use them later /datum/mood_event/cloned_corpse description = "I recently saw my own corpse...\n" diff --git a/code/datums/wires/microwave.dm b/code/datums/wires/microwave.dm new file mode 100644 index 0000000000..8c74abfa46 --- /dev/null +++ b/code/datums/wires/microwave.dm @@ -0,0 +1,27 @@ +/datum/wires/microwave + holder_type = /obj/machinery/microwave + proper_name = "Microwave" + +/datum/wires/microwave/New(atom/holder) + wires = list( + WIRE_ACTIVATE + ) + ..() + +/datum/wires/microwave/interactable(mob/user) + . = FALSE + var/obj/machinery/microwave/M = holder + if(M.panel_open) + . = TRUE + +/datum/wires/microwave/on_pulse(wire) + var/obj/machinery/microwave/M = holder + switch(wire) + if(WIRE_ACTIVATE) + M.cook() + +/datum/wires/microwave/on_cut(wire, mend) + var/obj/machinery/microwave/M = holder + switch(wire) + if(WIRE_ACTIVATE) + M.wire_disabled = !mend diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index 53aebc53dc..45a3b59661 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -35,15 +35,14 @@ /obj/item/pda/clear, /obj/item/pda/syndicate, /obj/item/pda/chameleon, - /obj/item/pda/chameleon/broken) + /obj/item/pda/chameleon/broken, + /obj/item/pda/lieutenant) - for(var/P in typesof(/obj/item/pda) - blocked) - var/obj/item/pda/D = new P - - //D.name = "PDA Style [colorlist.len+1]" //Gotta set the name, otherwise it all comes up as "PDA" - D.name = D.icon_state //PDAs don't have unique names, but using the sprite names works. - - src.colorlist += D + for(var/A in typesof(/obj/item/pda) - blocked) + var/obj/item/pda/P = A + var/PDA_name = initial(P.name) + colorlist += PDA_name + colorlist[PDA_name] = list(initial(P.icon_state), initial(P.desc), initial(P.overlays_offsets), initial(P.overlays_icons)) /obj/machinery/pdapainter/Destroy() QDEL_NULL(storedpda) @@ -108,22 +107,20 @@ if(.) return - if(storedpda) - var/obj/item/pda/P - P = input(user, "Select your color!", "PDA Painting") as null|anything in colorlist - if(!P) - return - if(!in_range(src, user)) - return - if(!storedpda)//is the pda still there? - return - storedpda.icon_state = P.icon_state - storedpda.desc = P.desc - ejectpda() - - else + if(!storedpda) to_chat(user, "[src] is empty.") - + return + var/choice = input(user, "Select the new skin!", "PDA Painting") as null|anything in colorlist + if(!choice || !storedpda || !in_range(src, user)) + return + var/list/P = colorlist[choice] + storedpda.icon_state = P[1] + storedpda.desc = P[2] + storedpda.overlays_offsets = P[3] + storedpda.overlays_icons = P[4] + storedpda.set_new_overlays() + storedpda.update_icon() + ejectpda() /obj/machinery/pdapainter/verb/ejectpda() set name = "Eject PDA" diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 9b5aa96b0b..b0e4c699d7 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -168,9 +168,11 @@ Class Procs: update_icon() updateUsrDialog() -/obj/machinery/proc/dropContents() +/obj/machinery/proc/dropContents(list/subset = null) var/turf/T = get_turf(src) for(var/atom/movable/A in contents) + if(subset && !(A in subset)) + continue A.forceMove(T) if(isliving(A)) var/mob/living/L = A diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 7f2fef18ac..8d0cfb95e8 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -40,7 +40,6 @@ /obj/item/toy/toy_xeno = ARCADE_WEIGHT_TRICK, /obj/item/toy/windupToolbox = ARCADE_WEIGHT_TRICK, - /obj/item/twohanded/dualsaber/toy = ARCADE_WEIGHT_RARE, /mob/living/simple_animal/bot/secbot/grievous/toy = ARCADE_WEIGHT_RARE, /obj/item/clothing/mask/facehugger/toy = ARCADE_WEIGHT_RARE, /obj/item/gun/ballistic/automatic/toy/pistol/unrestricted = ARCADE_WEIGHT_TRICK, @@ -82,13 +81,17 @@ // If it's a generic arcade machine, pick a random arcade // circuit board for it and make the new machine if(!circuit) - var/choice = pick(subtypesof(/obj/item/circuitboard/computer/arcade)) - var/obj/item/circuitboard/CB = new choice() + var/list/gameodds = list(/obj/item/circuitboard/computer/arcade/battle = 33, + /obj/item/circuitboard/computer/arcade/orion_trail = 33, + /obj/item/circuitboard/computer/arcade/minesweeper = 33, + /obj/item/circuitboard/computer/arcade/amputation = 2) + var/thegame = pickweight(gameodds) + var/obj/item/circuitboard/CB = new thegame() new CB.build_path(loc, CB) return INITIALIZE_HINT_QDEL Reset() -/obj/machinery/computer/arcade/proc/prizevend(mob/user) +/obj/machinery/computer/arcade/proc/prizevend(mob/user, list/rarity_classes) SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "arcade", /datum/mood_event/arcade) if(prob(1) && prob(1) && prob(1)) //Proper 1 in a million @@ -96,7 +99,14 @@ SSmedals.UnlockMedal(MEDAL_PULSE, usr.client) if(!contents.len) - var/prizeselect = pickweight(prizes) + var/list/toy_raffle + if(rarity_classes) + for(var/A in prizes) + if(prizes[A] in rarity_classes) + LAZYSET(toy_raffle, A, prizes[A]) + if(!toy_raffle) + toy_raffle = prizes + var/prizeselect = pickweight(toy_raffle) new prizeselect(src) var/atom/movable/prize = pick(contents) @@ -121,1022 +131,3 @@ empprize = pickweight(prizes) new empprize(loc) explosion(loc, -1, 0, 1+num_of_prizes, flame_range = 1+num_of_prizes) - - -// ** BATTLE ** // - - -/obj/machinery/computer/arcade/battle - name = "arcade machine" - desc = "Does not support Pinball." - icon_state = "arcade" - circuit = /obj/item/circuitboard/computer/arcade/battle - var/enemy_name = "Space Villain" - var/temp = "Winners don't use space drugs" //Temporary message, for attack messages, etc - var/player_hp = 30 //Player health/attack points - var/player_mp = 10 - var/enemy_hp = 45 //Enemy health/attack points - var/enemy_mp = 20 - var/gameover = FALSE - var/blocked = FALSE //Player cannot attack/heal while set - var/turtle = 0 - - var/turn_speed = 5 //Measured in deciseconds. - -/obj/machinery/computer/arcade/battle/Reset() - var/name_action - var/name_part1 - var/name_part2 - - name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ", "Ban ") - - name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ") - name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn", "Bloopers") - - enemy_name = replacetext((name_part1 + name_part2), "the ", "") - name = (name_action + name_part1 + name_part2) - -/obj/machinery/computer/arcade/battle/ui_interact(mob/user) - . = ..() - var/dat = "Close" - dat += "

[enemy_name]

" - - dat += "

[temp]

" - dat += "
Health: [player_hp] | Magic: [player_mp] | Enemy Health: [enemy_hp]
" - - if (gameover) - dat += "
New Game" - else - dat += "
Attack | " - dat += "Heal | " - dat += "Recharge Power" - - dat += "
" - var/datum/browser/popup = new(user, "arcade", "Space Villain 2000") - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - popup.open() - -/obj/machinery/computer/arcade/battle/Topic(href, href_list) - if(..()) - return - - if (!blocked && !gameover) - if (href_list["attack"]) - blocked = TRUE - var/attackamt = rand(2,6) - temp = "You attack for [attackamt] damage!" - playsound(loc, 'sound/arcade/hit.ogg', 50, 1, extrarange = -3, falloff = 10) - updateUsrDialog() - if(turtle > 0) - turtle-- - - sleep(turn_speed) - enemy_hp -= attackamt - arcade_action(usr) - - else if (href_list["heal"]) - blocked = TRUE - var/pointamt = rand(1,3) - var/healamt = rand(6,8) - temp = "You use [pointamt] magic to heal for [healamt] damage!" - playsound(loc, 'sound/arcade/heal.ogg', 50, 1, extrarange = -3, falloff = 10) - updateUsrDialog() - turtle++ - - sleep(turn_speed) - player_mp -= pointamt - player_hp += healamt - blocked = TRUE - updateUsrDialog() - arcade_action(usr) - - else if (href_list["charge"]) - blocked = TRUE - var/chargeamt = rand(4,7) - temp = "You regain [chargeamt] points" - playsound(loc, 'sound/arcade/mana.ogg', 50, 1, extrarange = -3, falloff = 10) - player_mp += chargeamt - if(turtle > 0) - turtle-- - - updateUsrDialog() - sleep(turn_speed) - arcade_action(usr) - - if (href_list["close"]) - usr.unset_machine() - usr << browse(null, "window=arcade") - - else if (href_list["newgame"]) //Reset everything - temp = "New Round" - player_hp = initial(player_hp) - player_mp = initial(player_mp) - enemy_hp = initial(enemy_hp) - enemy_mp = initial(enemy_mp) - gameover = FALSE - turtle = 0 - - if(obj_flags & EMAGGED) - Reset() - obj_flags &= ~EMAGGED - - add_fingerprint(usr) - updateUsrDialog() - return - -/obj/machinery/computer/arcade/battle/proc/arcade_action(mob/user) - if ((enemy_mp <= 0) || (enemy_hp <= 0)) - if(!gameover) - gameover = TRUE - temp = "[enemy_name] has fallen! Rejoice!" - playsound(loc, 'sound/arcade/win.ogg', 50, 1, extrarange = -3, falloff = 10) - - if(obj_flags & EMAGGED) - new /obj/effect/spawner/newbomb/timer/syndicate(loc) - new /obj/item/clothing/head/collectable/petehat(loc) - message_admins("[ADMIN_LOOKUPFLW(usr)] has outbombed Cuban Pete and been awarded a bomb.") - log_game("[key_name(usr)] has outbombed Cuban Pete and been awarded a bomb.") - Reset() - obj_flags &= ~EMAGGED - else - prizevend(user) - SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("win", (obj_flags & EMAGGED ? "emagged":"normal"))) - - - else if ((obj_flags & EMAGGED) && (turtle >= 4)) - var/boomamt = rand(5,10) - temp = "[enemy_name] throws a bomb, exploding you for [boomamt] damage!" - playsound(loc, 'sound/arcade/boom.ogg', 50, 1, extrarange = -3, falloff = 10) - player_hp -= boomamt - - else if ((enemy_mp <= 5) && (prob(70))) - var/stealamt = rand(2,3) - temp = "[enemy_name] steals [stealamt] of your power!" - playsound(loc, 'sound/arcade/steal.ogg', 50, 1, extrarange = -3, falloff = 10) - player_mp -= stealamt - updateUsrDialog() - - if (player_mp <= 0) - gameover = TRUE - sleep(turn_speed) - temp = "You have been drained! GAME OVER" - playsound(loc, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff = 10) - if(obj_flags & EMAGGED) - usr.gib() - SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "mana", (obj_flags & EMAGGED ? "emagged":"normal"))) - - else if ((enemy_hp <= 10) && (enemy_mp > 4)) - temp = "[enemy_name] heals for 4 health!" - playsound(loc, 'sound/arcade/heal.ogg', 50, 1, extrarange = -3, falloff = 10) - enemy_hp += 4 - enemy_mp -= 4 - - else - var/attackamt = rand(3,6) - temp = "[enemy_name] attacks for [attackamt] damage!" - playsound(loc, 'sound/arcade/hit.ogg', 50, 1, extrarange = -3, falloff = 10) - player_hp -= attackamt - - if ((player_mp <= 0) || (player_hp <= 0)) - gameover = TRUE - temp = "You have been crushed! GAME OVER" - playsound(loc, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff = 10) - if(obj_flags & EMAGGED) - usr.gib() - SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (obj_flags & EMAGGED ? "emagged":"normal"))) - - blocked = FALSE - return - - -/obj/machinery/computer/arcade/battle/emag_act(mob/user) - if(obj_flags & EMAGGED) - return - to_chat(user, "A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!") - temp = "If you die in the game, you die for real!" - player_hp = 30 - player_mp = 10 - enemy_hp = 45 - enemy_mp = 20 - gameover = FALSE - blocked = FALSE - - obj_flags |= EMAGGED - - enemy_name = "Cuban Pete" - name = "Outbomb Cuban Pete" - - - updateUsrDialog() - - - -// *** THE ORION TRAIL ** // - -#define ORION_TRAIL_WINTURN 9 - -//Orion Trail Events -#define ORION_TRAIL_RAIDERS "Raiders" -#define ORION_TRAIL_FLUX "Interstellar Flux" -#define ORION_TRAIL_ILLNESS "Illness" -#define ORION_TRAIL_BREAKDOWN "Breakdown" -#define ORION_TRAIL_LING "Changelings?" -#define ORION_TRAIL_LING_ATTACK "Changeling Ambush" -#define ORION_TRAIL_MALFUNCTION "Malfunction" -#define ORION_TRAIL_COLLISION "Collision" -#define ORION_TRAIL_SPACEPORT "Spaceport" -#define ORION_TRAIL_BLACKHOLE "BlackHole" - -#define ORION_STATUS_START 1 -#define ORION_STATUS_NORMAL 2 -#define ORION_STATUS_GAMEOVER 3 -#define ORION_STATUS_MARKET 4 - -/obj/machinery/computer/arcade/orion_trail - name = "The Orion Trail" - desc = "Learn how our ancestors got to Orion, and have fun in the process!" - icon_state = "arcade" - circuit = /obj/item/circuitboard/computer/arcade/orion_trail - var/busy = FALSE //prevent clickspam that allowed people to ~speedrun~ the game. - var/engine = 0 - var/hull = 0 - var/electronics = 0 - var/food = 80 - var/fuel = 60 - var/turns = 4 - var/alive = 4 - var/eventdat = null - var/event = null - var/list/settlers = list("Harry","Larry","Bob") - var/list/events = list(ORION_TRAIL_RAIDERS = 3, - ORION_TRAIL_FLUX = 1, - ORION_TRAIL_ILLNESS = 3, - ORION_TRAIL_BREAKDOWN = 2, - ORION_TRAIL_LING = 3, - ORION_TRAIL_MALFUNCTION = 2, - ORION_TRAIL_COLLISION = 1, - ORION_TRAIL_SPACEPORT = 2 - ) - var/list/stops = list() - var/list/stopblurbs = list() - var/lings_aboard = 0 - var/spaceport_raided = 0 - var/spaceport_freebie = 0 - var/last_spaceport_action = "" - var/gameStatus = ORION_STATUS_START - var/canContinueEvent = 0 - -/obj/machinery/computer/arcade/orion_trail/kobayashi - name = "Kobayashi Maru control computer" - desc = "A test for cadets" - icon = 'icons/obj/machines/particle_accelerator.dmi' - icon_state = "control_boxp" - events = list("Raiders" = 3, "Interstellar Flux" = 1, "Illness" = 3, "Breakdown" = 2, "Malfunction" = 2, "Collision" = 1, "Spaceport" = 2) - prizes = list(/obj/item/paper/fluff/holodeck/trek_diploma = 1) - settlers = list("Kirk","Worf","Gene") - -/obj/machinery/computer/arcade/orion_trail/Reset() - // Sets up the main trail - stops = list("Pluto","Asteroid Belt","Proxima Centauri","Dead Space","Rigel Prime","Tau Ceti Beta","Black Hole","Space Outpost Beta-9","Orion Prime") - stopblurbs = list( - "Pluto, long since occupied with long-range sensors and scanners, stands ready to, and indeed continues to probe the far reaches of the galaxy.", - "At the edge of the Sol system lies a treacherous asteroid belt. Many have been crushed by stray asteroids and misguided judgement.", - "The nearest star system to Sol, in ages past it stood as a reminder of the boundaries of sub-light travel, now a low-population sanctuary for adventurers and traders.", - "This region of space is particularly devoid of matter. Such low-density pockets are known to exist, but the vastness of it is astounding.", - "Rigel Prime, the center of the Rigel system, burns hot, basking its planetary bodies in warmth and radiation.", - "Tau Ceti Beta has recently become a waypoint for colonists headed towards Orion. There are many ships and makeshift stations in the vicinity.", - "Sensors indicate that a black hole's gravitational field is affecting the region of space we were headed through. We could stay of course, but risk of being overcome by its gravity, or we could change course to go around, which will take longer.", - "You have come into range of the first man-made structure in this region of space. It has been constructed not by travellers from Sol, but by colonists from Orion. It stands as a monument to the colonists' success.", - "You have made it to Orion! Congratulations! Your crew is one of the few to start a new foothold for mankind!" - ) - -/obj/machinery/computer/arcade/orion_trail/proc/newgame() - // Set names of settlers in crew - settlers = list() - for(var/i = 1; i <= 3; i++) - add_crewmember() - add_crewmember("[usr]") - // Re-set items to defaults - engine = 1 - hull = 1 - electronics = 1 - food = 80 - fuel = 60 - alive = 4 - turns = 1 - event = null - gameStatus = ORION_STATUS_NORMAL - lings_aboard = 0 - - //spaceport junk - spaceport_raided = 0 - spaceport_freebie = 0 - last_spaceport_action = "" - -/obj/machinery/computer/arcade/orion_trail/ui_interact(mob/user) - . = ..() - if(fuel <= 0 || food <=0 || settlers.len == 0) - gameStatus = ORION_STATUS_GAMEOVER - event = null - var/dat = "" - if(gameStatus == ORION_STATUS_GAMEOVER) - dat = "

Game Over

" - dat += "Like many before you, your crew never made it to Orion, lost to space...
Forever." - if(!settlers.len) - dat += "
Your entire crew died, and your ship joins the fleet of ghost-ships littering the galaxy." - else - if(food <= 0) - dat += "
You ran out of food and starved." - if(obj_flags & EMAGGED) - user.nutrition = 0 //yeah you pretty hongry - to_chat(user, "Your body instantly contracts to that of one who has not eaten in months. Agonizing cramps seize you as you fall to the floor.") - if(fuel <= 0) - dat += "
You ran out of fuel, and drift, slowly, into a star." - if(obj_flags & EMAGGED) - var/mob/living/M = user - M.adjust_fire_stacks(5) - M.IgniteMob() //flew into a star, so you're on fire - to_chat(user, "You feel an immense wave of heat emanate from the arcade machine. Your skin bursts into flames.") - - if(obj_flags & EMAGGED) - to_chat(user, "You're never going to make it to Orion...") - user.death() - obj_flags &= ~EMAGGED //removes the emagged status after you lose - gameStatus = ORION_STATUS_START - name = "The Orion Trail" - desc = "Learn how our ancestors got to Orion, and have fun in the process!" - - dat += "

May They Rest In Peace

" - else if(event) - dat = eventdat - else if(gameStatus == ORION_STATUS_NORMAL) - var/title = stops[turns] - var/subtext = stopblurbs[turns] - dat = "

[title]

" - dat += "[subtext]" - dat += "

Crew:

" - dat += english_list(settlers) - dat += "
Food: [food] | Fuel: [fuel]" - dat += "
Engine Parts: [engine] | Hull Panels: [hull] | Electronics: [electronics]" - if(turns == 7) - dat += "

Go Around Continue

" - else - dat += "

Continue

" - dat += "

Kill a Crewmember

" - dat += "

Close

" - else - dat = "

The Orion Trail

" - dat += "

Experience the journey of your ancestors!



" - dat += "
New Game
" - dat += "

Close

" - var/datum/browser/popup = new(user, "arcade", "The Orion Trail",400,700) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - popup.open() - return - -/obj/machinery/computer/arcade/orion_trail/Topic(href, href_list) - if(..()) - return - if(href_list["close"]) - usr.unset_machine() - usr << browse(null, "window=arcade") - - if(busy) - return - busy = TRUE - - if (href_list["continue"]) //Continue your travels - if(gameStatus == ORION_STATUS_NORMAL && !event && turns != 7) - if(turns >= ORION_TRAIL_WINTURN) - win(usr) - else - food -= (alive+lings_aboard)*2 - fuel -= 5 - if(turns == 2 && prob(30)) - event = ORION_TRAIL_COLLISION - event() - else if(prob(75)) - event = pickweight(events) - if(lings_aboard) - if(event == ORION_TRAIL_LING || prob(55)) - event = ORION_TRAIL_LING_ATTACK - event() - turns += 1 - if(obj_flags & EMAGGED) - var/mob/living/carbon/M = usr //for some vars - switch(event) - if(ORION_TRAIL_RAIDERS) - if(prob(50)) - to_chat(usr, "You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?") - M.hallucination += 30 - else - to_chat(usr, "Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there...") - M.take_bodypart_damage(30) - playsound(loc, 'sound/weapons/genhit2.ogg', 100, 1) - if(ORION_TRAIL_ILLNESS) - var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS - if(severity == 1) - to_chat(M, "You suddenly feel slightly nauseated." ) - if(severity == 2) - to_chat(usr, "You suddenly feel extremely nauseated and hunch over until it passes.") - M.Stun(60) - if(severity >= 3) //you didn't pray hard enough - to_chat(M, "An overpowering wave of nausea consumes over you. You hunch over, your stomach's contents preparing for a spectacular exit.") - M.Stun(100) - sleep(30) - M.vomit(10, distance = 5) - if(ORION_TRAIL_FLUX) - if(prob(75)) - M.Knockdown(60) - say("A sudden gust of powerful wind slams [M] into the floor!") - M.take_bodypart_damage(25) - playsound(loc, 'sound/weapons/genhit.ogg', 100, 1) - else - to_chat(M, "A violent gale blows past you, and you barely manage to stay standing!") - if(ORION_TRAIL_COLLISION) //by far the most damaging event - if(prob(90)) - playsound(loc, 'sound/effects/bang.ogg', 100, 1) - var/turf/open/floor/F - for(F in orange(1, src)) - F.ScrapeAway() - say("Something slams into the floor around [src], exposing it to space!") - if(hull) - sleep(10) - say("A new floor suddenly appears around [src]. What the hell?") - playsound(loc, 'sound/weapons/genhit.ogg', 100, 1) - var/turf/open/space/T - for(T in orange(1, src)) - T.PlaceOnTop(/turf/open/floor/plating) - else - say("Something slams into the floor around [src] - luckily, it didn't get through!") - playsound(loc, 'sound/effects/bang.ogg', 50, 1) - if(ORION_TRAIL_MALFUNCTION) - playsound(loc, 'sound/effects/empulse.ogg', 50, 1) - visible_message("[src] malfunctions, randomizing in-game stats!") - var/oldfood = food - var/oldfuel = fuel - food = rand(10,80) / rand(1,2) - fuel = rand(10,60) / rand(1,2) - if(electronics) - sleep(10) - if(oldfuel > fuel && oldfood > food) - audible_message("[src] lets out a somehow reassuring chime.") - else if(oldfuel < fuel || oldfood < food) - audible_message("[src] lets out a somehow ominous chime.") - food = oldfood - fuel = oldfuel - playsound(loc, 'sound/machines/chime.ogg', 50, 1) - - else if(href_list["newgame"]) //Reset everything - if(gameStatus == ORION_STATUS_START) - newgame() - else if(href_list["menu"]) //back to the main menu - if(gameStatus == ORION_STATUS_GAMEOVER) - gameStatus = ORION_STATUS_START - event = null - food = 80 - fuel = 60 - settlers = list("Harry","Larry","Bob") - else if(href_list["slow"]) //slow down - if(event == ORION_TRAIL_FLUX) - food -= (alive+lings_aboard)*2 - fuel -= 5 - event = null - else if(href_list["pastblack"]) //slow down - if(turns == 7) - food -= ((alive+lings_aboard)*2)*3 - fuel -= 15 - turns += 1 - event = null - else if(href_list["useengine"]) //use parts - if(event == ORION_TRAIL_BREAKDOWN) - engine = max(0, --engine) - event = null - else if(href_list["useelec"]) //use parts - if(event == ORION_TRAIL_MALFUNCTION) - electronics = max(0, --electronics) - event = null - else if(href_list["usehull"]) //use parts - if(event == ORION_TRAIL_COLLISION) - hull = max(0, --hull) - event = null - else if(href_list["wait"]) //wait 3 days - if(event == ORION_TRAIL_BREAKDOWN || event == ORION_TRAIL_MALFUNCTION || event == ORION_TRAIL_COLLISION) - food -= ((alive+lings_aboard)*2)*3 - event = null - else if(href_list["keepspeed"]) //keep speed - if(event == ORION_TRAIL_FLUX) - if(prob(75)) - event = "Breakdown" - event() - else - event = null - else if(href_list["blackhole"]) //keep speed past a black hole - if(turns == 7) - if(prob(75)) - event = ORION_TRAIL_BLACKHOLE - event() - if(obj_flags & EMAGGED) - playsound(loc, 'sound/effects/supermatter.ogg', 100, 1) - say("A miniature black hole suddenly appears in front of [src], devouring [usr] alive!") - if(isliving(usr)) - var/mob/living/L = usr - L.Stun(200, ignore_canstun = TRUE) //you can't run :^) - var/S = new /obj/singularity/academy(usr.loc) - addtimer(CALLBACK(src, /atom/movable/proc/say, "[S] winks out, just as suddenly as it appeared."), 50) - QDEL_IN(S, 50) - else - event = null - turns += 1 - else if(href_list["holedeath"]) - if(event == ORION_TRAIL_BLACKHOLE) - gameStatus = ORION_STATUS_GAMEOVER - event = null - else if(href_list["eventclose"]) //end an event - if(canContinueEvent) - event = null - - else if(href_list["killcrew"]) //shoot a crewmember - if(gameStatus == ORION_STATUS_NORMAL || event == ORION_TRAIL_LING) - var/sheriff = remove_crewmember() //I shot the sheriff - playsound(loc,'sound/weapons/gunshot.ogg', 100, 1) - - if(settlers.len == 0 || alive == 0) - say("The last crewmember [sheriff], shot themselves, GAME OVER!") - if(obj_flags & EMAGGED) - usr.death(0) - obj_flags &= EMAGGED - gameStatus = ORION_STATUS_GAMEOVER - event = null - else if(obj_flags & EMAGGED) - if(usr.name == sheriff) - say("The crew of the ship chose to kill [usr.name]!") - usr.death(0) - - if(event == ORION_TRAIL_LING) //only ends the ORION_TRAIL_LING event, since you can do this action in multiple places - event = null - - //Spaceport specific interactions - //they get a header because most of them don't reset event (because it's a shop, you leave when you want to) - //they also call event() again, to regen the eventdata, which is kind of odd but necessary - else if(href_list["buycrew"]) //buy a crewmember - if(gameStatus == ORION_STATUS_MARKET) - if(!spaceport_raided && food >= 10 && fuel >= 10) - var/bought = add_crewmember() - last_spaceport_action = "You hired [bought] as a new crewmember." - fuel -= 10 - food -= 10 - event() - - else if(href_list["sellcrew"]) //sell a crewmember - if(gameStatus == ORION_STATUS_MARKET) - if(!spaceport_raided && settlers.len > 1) - var/sold = remove_crewmember() - last_spaceport_action = "You sold your crewmember, [sold]!" - fuel += 7 - food += 7 - event() - - else if(href_list["leave_spaceport"]) - if(gameStatus == ORION_STATUS_MARKET) - event = null - gameStatus = ORION_STATUS_NORMAL - spaceport_raided = 0 - spaceport_freebie = 0 - last_spaceport_action = "" - - else if(href_list["raid_spaceport"]) - if(gameStatus == ORION_STATUS_MARKET) - if(!spaceport_raided) - var/success = min(15 * alive,100) //default crew (4) have a 60% chance - spaceport_raided = 1 - - var/FU = 0 - var/FO = 0 - if(prob(success)) - FU = rand(5,15) - FO = rand(5,15) - last_spaceport_action = "You successfully raided the spaceport! You gained [FU] Fuel and [FO] Food! (+[FU]FU,+[FO]FO)" - else - FU = rand(-5,-15) - FO = rand(-5,-15) - last_spaceport_action = "You failed to raid the spaceport! You lost [FU*-1] Fuel and [FO*-1] Food in your scramble to escape! ([FU]FU,[FO]FO)" - - //your chance of lose a crewmember is 1/2 your chance of success - //this makes higher % failures hurt more, don't get cocky space cowboy! - if(prob(success*5)) - var/lost_crew = remove_crewmember() - last_spaceport_action = "You failed to raid the spaceport! You lost [FU*-1] Fuel and [FO*-1] Food, AND [lost_crew] in your scramble to escape! ([FU]FI,[FO]FO,-Crew)" - if(obj_flags & EMAGGED) - say("WEEWOO! WEEWOO! Spaceport security en route!") - playsound(src, 'sound/items/weeoo1.ogg', 100, FALSE) - for(var/i, i<=3, i++) - var/mob/living/simple_animal/hostile/syndicate/ranged/smg/orion/O = new/mob/living/simple_animal/hostile/syndicate/ranged/smg/orion(get_turf(src)) - O.target = usr - - - fuel += FU - food += FO - event() - - else if(href_list["buyparts"]) - if(gameStatus == ORION_STATUS_MARKET) - if(!spaceport_raided && fuel > 5) - switch(text2num(href_list["buyparts"])) - if(1) //Engine Parts - engine++ - last_spaceport_action = "Bought Engine Parts" - if(2) //Hull Plates - hull++ - last_spaceport_action = "Bought Hull Plates" - if(3) //Spare Electronics - electronics++ - last_spaceport_action = "Bought Spare Electronics" - fuel -= 5 //they all cost 5 - event() - - else if(href_list["trade"]) - if(gameStatus == ORION_STATUS_MARKET) - if(!spaceport_raided) - switch(text2num(href_list["trade"])) - if(1) //Fuel - if(fuel > 5) - fuel -= 5 - food += 5 - last_spaceport_action = "Traded Fuel for Food" - event() - if(2) //Food - if(food > 5) - fuel += 5 - food -= 5 - last_spaceport_action = "Traded Food for Fuel" - event() - - add_fingerprint(usr) - updateUsrDialog() - busy = FALSE - return - - -/obj/machinery/computer/arcade/orion_trail/proc/event() - eventdat = "

[event]

" - canContinueEvent = 0 - switch(event) - if(ORION_TRAIL_RAIDERS) - eventdat += "Raiders have come aboard your ship!" - if(prob(50)) - var/sfood = rand(1,10) - var/sfuel = rand(1,10) - food -= sfood - fuel -= sfuel - eventdat += "
They have stolen [sfood] Food and [sfuel] Fuel." - else if(prob(10)) - var/deadname = remove_crewmember() - eventdat += "
[deadname] tried to fight back, but was killed." - else - eventdat += "
Fortunately, you fended them off without any trouble." - eventdat += "

Continue

" - eventdat += "

Close

" - canContinueEvent = 1 - - if(ORION_TRAIL_FLUX) - eventdat += "This region of space is highly turbulent.
If we go slowly we may avoid more damage, but if we keep our speed we won't waste supplies." - eventdat += "
What will you do?" - eventdat += "

Slow Down Continue

" - eventdat += "

Close

" - - if(ORION_TRAIL_ILLNESS) - eventdat += "A deadly illness has been contracted!" - var/deadname = remove_crewmember() - eventdat += "
[deadname] was killed by the disease." - eventdat += "

Continue

" - eventdat += "

Close

" - canContinueEvent = 1 - - if(ORION_TRAIL_BREAKDOWN) - eventdat += "Oh no! The engine has broken down!" - eventdat += "
You can repair it with an engine part, or you can make repairs for 3 days." - if(engine >= 1) - eventdat += "

Use PartWait

" - else - eventdat += "

Wait

" - eventdat += "

Close

" - - if(ORION_TRAIL_MALFUNCTION) - eventdat += "The ship's systems are malfunctioning!" - eventdat += "
You can replace the broken electronics with spares, or you can spend 3 days troubleshooting the AI." - if(electronics >= 1) - eventdat += "

Use PartWait

" - else - eventdat += "

Wait

" - eventdat += "

Close

" - - if(ORION_TRAIL_COLLISION) - eventdat += "Something hit us! Looks like there's some hull damage." - if(prob(25)) - var/sfood = rand(5,15) - var/sfuel = rand(5,15) - food -= sfood - fuel -= sfuel - eventdat += "
[sfood] Food and [sfuel] Fuel was vented out into space." - if(prob(10)) - var/deadname = remove_crewmember() - eventdat += "
[deadname] was killed by rapid depressurization." - eventdat += "
You can repair the damage with hull plates, or you can spend the next 3 days welding scrap together." - if(hull >= 1) - eventdat += "

Use PartWait

" - else - eventdat += "

Wait

" - eventdat += "

Close

" - - if(ORION_TRAIL_BLACKHOLE) - eventdat += "You were swept away into the black hole." - eventdat += "

Oh...

" - eventdat += "

Close

" - settlers = list() - - if(ORION_TRAIL_LING) - eventdat += "Strange reports warn of changelings infiltrating crews on trips to Orion..." - if(settlers.len <= 2) - eventdat += "
Your crew's chance of reaching Orion is so slim the changelings likely avoided your ship..." - eventdat += "

Continue

" - eventdat += "

Close

" - if(prob(10)) // "likely", I didn't say it was guaranteed! - lings_aboard = min(++lings_aboard,2) - else - if(lings_aboard) //less likely to stack lings - if(prob(20)) - lings_aboard = min(++lings_aboard,2) - else if(prob(70)) - lings_aboard = min(++lings_aboard,2) - - eventdat += "

Kill a Crewmember

" - eventdat += "

Risk it

" - eventdat += "

Close

" - canContinueEvent = 1 - - if(ORION_TRAIL_LING_ATTACK) - if(lings_aboard <= 0) //shouldn't trigger, but hey. - eventdat += "Haha, fooled you, there are no changelings on board!" - eventdat += "
(You should report this to a coder :S)" - else - var/ling1 = remove_crewmember() - var/ling2 = "" - if(lings_aboard >= 2) - ling2 = remove_crewmember() - - eventdat += "Changelings among your crew suddenly burst from hiding and attack!" - if(ling2) - eventdat += "
[ling1] and [ling2]'s arms twist and contort into grotesque blades!" - else - eventdat += "
[ling1]'s arm twists and contorts into a grotesque blade!" - - var/chance2attack = alive*20 - if(prob(chance2attack)) - var/chancetokill = 30*lings_aboard-(5*alive) //eg: 30*2-(10) = 50%, 2 lings, 2 crew is 50% chance - if(prob(chancetokill)) - var/deadguy = remove_crewmember() - var/murder_text = pick("The changeling[ling2 ? "s" : ""] bring[ling2 ? "" : "s"] down [deadguy] and disembowel[ling2 ? "" : "s"] them in a spray of gore!", \ - "[ling2 ? pick(ling1, ling2) : ling1] corners [deadguy] and impales them through the stomach!", \ - "[ling2 ? pick(ling1, ling2) : ling1] decapitates [deadguy] in a single cleaving arc!") - eventdat += "
[murder_text]" - else - eventdat += "

You valiantly fight off the changeling[ling2 ? "s":""]!" - if(ling2) - food += 30 - lings_aboard = max(0,lings_aboard-2) - else - food += 15 - lings_aboard = max(0,--lings_aboard) - eventdat += "
Well, it's perfectly good food...\ -
You cut the changeling[ling2 ? "s" : ""] into meat, gaining [ling2 ? "30" : "15"] Food!" - else - eventdat += "

[pick("Sensing unfavorable odds", "After a failed attack", "Suddenly breaking nerve")], \ - the changeling[ling2 ? "s":""] vanish[ling2 ? "" : "es"] into space through the airlocks! You're safe... for now." - if(ling2) - lings_aboard = max(0,lings_aboard-2) - else - lings_aboard = max(0,--lings_aboard) - - eventdat += "

Continue

" - eventdat += "

Close

" - canContinueEvent = 1 - - - if(ORION_TRAIL_SPACEPORT) - gameStatus = ORION_STATUS_MARKET - if(spaceport_raided) - eventdat += "The spaceport is on high alert! You've been barred from docking by the local authorities after your failed raid." - if(last_spaceport_action) - eventdat += "
Last Spaceport Action: [last_spaceport_action]" - eventdat += "

Depart Spaceport

" - eventdat += "

Close

" - else - eventdat += "Your jump into the sector yields a spaceport - a lucky find!" - eventdat += "
This spaceport is home to travellers who failed to reach Orion, but managed to find a different home..." - eventdat += "
Trading terms: FU = Fuel, FO = Food" - if(last_spaceport_action) - eventdat += "
Last action: [last_spaceport_action]" - eventdat += "

Crew:

" - eventdat += english_list(settlers) - eventdat += "
Food: [food] | Fuel: [fuel]" - eventdat += "
Engine Parts: [engine] | Hull Panels: [hull] | Electronics: [electronics]" - - - //If your crew is pathetic you can get freebies (provided you haven't already gotten one from this port) - if(!spaceport_freebie && (fuel < 20 || food < 20)) - spaceport_freebie++ - var/FU = 10 - var/FO = 10 - var/freecrew = 0 - if(prob(30)) - FU = 25 - FO = 25 - - if(prob(10)) - add_crewmember() - freecrew++ - - eventdat += "
The traders of the spaceport take pity on you, and generously give you some free supplies! (+[FU]FU, +[FO]FO)" - if(freecrew) - eventdat += "
You also gain a new crewmember!" - - fuel += FU - food += FO - - //CREW INTERACTIONS - eventdat += "

Crew Management:

" - - //Buy crew - if(food >= 10 && fuel >= 10) - eventdat += "

Hire a New Crewmember (-10FU, -10FO)

" - else - eventdat += "

You cannot afford a new crewmember.

" - - //Sell crew - if(settlers.len > 1) - eventdat += "

Sell Crew for Fuel and Food (+7FU, +7FO)

" - else - eventdat += "

You have no other crew to sell.

" - - //BUY/SELL STUFF - eventdat += "

Spare Parts:

" - - //Engine parts - if(fuel > 5) - eventdat += "

Buy Engine Parts (-5FU)

" - else - eventdat += "

You cannot afford engine parts." - - //Hull plates - if(fuel > 5) - eventdat += "

Buy Hull Plates (-5FU)

" - else - eventdat += "

You cannot afford hull plates." - - //Electronics - if(fuel > 5) - eventdat += "

Buy Spare Electronics (-5FU)

" - else - eventdat += "

You cannot afford spare electronics." - - //Trade - if(fuel > 5) - eventdat += "

Trade Fuel for Food (-5FU,+5FO)

" - else - eventdat += "

You don't have 5FU to trade. 5) - eventdat += "

Trade Food for Fuel (+5FU,-5FO)

" - else - eventdat += "

You don't have 5FO to trade.You override the cheat code menu and skip to Cheat #[rand(1, 50)]: Realism Mode.") - name = "The Orion Trail: Realism Edition" - desc = "Learn how our ancestors got to Orion, and try not to die in the process!" - newgame() - obj_flags |= EMAGGED - -/mob/living/simple_animal/hostile/syndicate/ranged/smg/orion - name = "spaceport security" - desc = "Premier corporate security forces for all spaceports found along the Orion Trail." - faction = list("orion") - loot = list() - del_on_death = TRUE - -/obj/item/orion_ship - name = "model settler ship" - desc = "A model spaceship, it looks like those used back in the day when travelling to Orion! It even has a miniature FX-293 reactor, which was renowned for its instability and tendency to explode..." - icon = 'icons/obj/toy.dmi' - icon_state = "ship" - w_class = WEIGHT_CLASS_SMALL - var/active = 0 //if the ship is on - -/obj/item/orion_ship/examine(mob/user) - ..() - if(!(in_range(user, src))) - return - if(!active) - to_chat(user, "There's a little switch on the bottom. It's flipped down.") - else - to_chat(user, "There's a little switch on the bottom. It's flipped up.") - -/obj/item/orion_ship/attack_self(mob/user) //Minibomb-level explosion. Should probably be more because of how hard it is to survive the machine! Also, just over a 5-second fuse - if(active) - return - - message_admins("[ADMIN_LOOKUPFLW(usr)] primed an explosive Orion ship for detonation at [AREACOORD(usr)].") - log_game("[key_name(usr)] primed an explosive Orion ship for detonation at [AREACOORD(usr)].") - - to_chat(user, "You flip the switch on the underside of [src].") - active = 1 - visible_message("[src] softly beeps and whirs to life!") - playsound(loc, 'sound/machines/defib_SaftyOn.ogg', 25, 1) - say("This is ship ID #[rand(1,1000)] to Orion Port Authority. We're coming in for landing, over.") - sleep(20) - visible_message("[src] begins to vibrate...") - say("Uh, Port? Having some issues with our reactor, could you check it out? Over.") - sleep(30) - say("Oh, God! Code Eight! CODE EIGHT! IT'S GONNA BL-") - playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, 1) - sleep(3.6) - visible_message("[src] explodes!") - explosion(loc, 2,4,8, flame_range = 16) - qdel(src) - - -#undef ORION_TRAIL_WINTURN -#undef ORION_TRAIL_RAIDERS -#undef ORION_TRAIL_FLUX -#undef ORION_TRAIL_ILLNESS -#undef ORION_TRAIL_BREAKDOWN -#undef ORION_TRAIL_LING -#undef ORION_TRAIL_LING_ATTACK -#undef ORION_TRAIL_MALFUNCTION -#undef ORION_TRAIL_COLLISION -#undef ORION_TRAIL_SPACEPORT -#undef ORION_TRAIL_BLACKHOLE - -#undef ORION_STATUS_START -#undef ORION_STATUS_NORMAL -#undef ORION_STATUS_GAMEOVER -#undef ORION_STATUS_MARKET diff --git a/code/game/machinery/computer/arcade/battle.dm b/code/game/machinery/computer/arcade/battle.dm new file mode 100644 index 0000000000..ded9cf95f6 --- /dev/null +++ b/code/game/machinery/computer/arcade/battle.dm @@ -0,0 +1,206 @@ +// ** BATTLE ** // + + +/obj/machinery/computer/arcade/battle + name = "arcade machine" + desc = "Does not support Pinball." + icon_state = "arcade" + circuit = /obj/item/circuitboard/computer/arcade/battle + var/enemy_name = "Space Villain" + var/temp = "Winners don't use space drugs" //Temporary message, for attack messages, etc + var/player_hp = 30 //Player health/attack points + var/player_mp = 10 + var/enemy_hp = 45 //Enemy health/attack points + var/enemy_mp = 20 + var/gameover = FALSE + var/blocked = FALSE //Player cannot attack/heal while set + var/turtle = 0 + + var/turn_speed = 5 //Measured in deciseconds. + +/obj/machinery/computer/arcade/battle/Reset() + var/name_action + var/name_part1 + var/name_part2 + + name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ", "Ban ") + + name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ") + name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn", "Bloopers") + + enemy_name = replacetext((name_part1 + name_part2), "the ", "") + name = (name_action + name_part1 + name_part2) + +/obj/machinery/computer/arcade/battle/ui_interact(mob/user) + . = ..() + var/dat = "Close" + dat += "

[enemy_name]

" + + dat += "

[temp]

" + dat += "
Health: [player_hp] | Magic: [player_mp] | Enemy Health: [enemy_hp]
" + + if (gameover) + dat += "
New Game" + else + dat += "
Attack | " + dat += "Heal | " + dat += "Recharge Power" + + dat += "
" + var/datum/browser/popup = new(user, "arcade", "Space Villain 2000") + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) + popup.open() + +/obj/machinery/computer/arcade/battle/Topic(href, href_list) + if(..()) + return + + if (!blocked && !gameover) + if (href_list["attack"]) + blocked = TRUE + var/attackamt = rand(2,6) + temp = "You attack for [attackamt] damage!" + playsound(loc, 'sound/arcade/hit.ogg', 50, 1, extrarange = -3, falloff = 10) + updateUsrDialog() + if(turtle > 0) + turtle-- + + sleep(turn_speed) + enemy_hp -= attackamt + arcade_action(usr) + + else if (href_list["heal"]) + blocked = TRUE + var/pointamt = rand(1,3) + var/healamt = rand(6,8) + temp = "You use [pointamt] magic to heal for [healamt] damage!" + playsound(loc, 'sound/arcade/heal.ogg', 50, 1, extrarange = -3, falloff = 10) + updateUsrDialog() + turtle++ + + sleep(turn_speed) + player_mp -= pointamt + player_hp += healamt + blocked = TRUE + updateUsrDialog() + arcade_action(usr) + + else if (href_list["charge"]) + blocked = TRUE + var/chargeamt = rand(4,7) + temp = "You regain [chargeamt] points" + playsound(loc, 'sound/arcade/mana.ogg', 50, 1, extrarange = -3, falloff = 10) + player_mp += chargeamt + if(turtle > 0) + turtle-- + + updateUsrDialog() + sleep(turn_speed) + arcade_action(usr) + + if (href_list["close"]) + usr.unset_machine() + usr << browse(null, "window=arcade") + + else if (href_list["newgame"]) //Reset everything + temp = "New Round" + player_hp = initial(player_hp) + player_mp = initial(player_mp) + enemy_hp = initial(enemy_hp) + enemy_mp = initial(enemy_mp) + gameover = FALSE + turtle = 0 + + if(obj_flags & EMAGGED) + Reset() + obj_flags &= ~EMAGGED + + add_fingerprint(usr) + updateUsrDialog() + return + +/obj/machinery/computer/arcade/battle/proc/arcade_action(mob/user) + if ((enemy_mp <= 0) || (enemy_hp <= 0)) + if(!gameover) + gameover = TRUE + temp = "[enemy_name] has fallen! Rejoice!" + playsound(loc, 'sound/arcade/win.ogg', 50, 1, extrarange = -3, falloff = 10) + + if(obj_flags & EMAGGED) + new /obj/effect/spawner/newbomb/timer/syndicate(loc) + new /obj/item/clothing/head/collectable/petehat(loc) + message_admins("[ADMIN_LOOKUPFLW(usr)] has outbombed Cuban Pete and been awarded a bomb.") + log_game("[key_name(usr)] has outbombed Cuban Pete and been awarded a bomb.") + Reset() + obj_flags &= ~EMAGGED + else + prizevend(user) + SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("win", (obj_flags & EMAGGED ? "emagged":"normal"))) + + + else if ((obj_flags & EMAGGED) && (turtle >= 4)) + var/boomamt = rand(5,10) + temp = "[enemy_name] throws a bomb, exploding you for [boomamt] damage!" + playsound(loc, 'sound/arcade/boom.ogg', 50, 1, extrarange = -3, falloff = 10) + player_hp -= boomamt + + else if ((enemy_mp <= 5) && (prob(70))) + var/stealamt = rand(2,3) + temp = "[enemy_name] steals [stealamt] of your power!" + playsound(loc, 'sound/arcade/steal.ogg', 50, 1, extrarange = -3, falloff = 10) + player_mp -= stealamt + updateUsrDialog() + + if (player_mp <= 0) + gameover = TRUE + sleep(turn_speed) + temp = "You have been drained! GAME OVER" + playsound(loc, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff = 10) + if(obj_flags & EMAGGED) + usr.gib() + SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "mana", (obj_flags & EMAGGED ? "emagged":"normal"))) + + else if ((enemy_hp <= 10) && (enemy_mp > 4)) + temp = "[enemy_name] heals for 4 health!" + playsound(loc, 'sound/arcade/heal.ogg', 50, 1, extrarange = -3, falloff = 10) + enemy_hp += 4 + enemy_mp -= 4 + + else + var/attackamt = rand(3,6) + temp = "[enemy_name] attacks for [attackamt] damage!" + playsound(loc, 'sound/arcade/hit.ogg', 50, 1, extrarange = -3, falloff = 10) + player_hp -= attackamt + + if ((player_mp <= 0) || (player_hp <= 0)) + gameover = TRUE + temp = "You have been crushed! GAME OVER" + playsound(loc, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff = 10) + if(obj_flags & EMAGGED) + usr.gib() + SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (obj_flags & EMAGGED ? "emagged":"normal"))) + + blocked = FALSE + return + + +/obj/machinery/computer/arcade/battle/emag_act(mob/user) + if(obj_flags & EMAGGED) + return + to_chat(user, "A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!") + temp = "If you die in the game, you die for real!" + player_hp = 30 + player_mp = 10 + enemy_hp = 45 + enemy_mp = 20 + gameover = FALSE + blocked = FALSE + + obj_flags |= EMAGGED + + enemy_name = "Cuban Pete" + name = "Outbomb Cuban Pete" + + + updateUsrDialog() diff --git a/code/game/machinery/computer/arcade/minesweeper.dm b/code/game/machinery/computer/arcade/minesweeper.dm new file mode 100644 index 0000000000..fe69860f76 --- /dev/null +++ b/code/game/machinery/computer/arcade/minesweeper.dm @@ -0,0 +1,390 @@ +#define MINESWEEPER_GAME_MAIN_MENU 0 +#define MINESWEEPER_GAME_PLAYING 1 +#define MINESWEEPER_GAME_LOST 2 +#define MINESWEEPER_GAME_WON 3 +#define MINESWEEPERIMG(what) {""} //Basically bypassing asset.icon_tag() + +/obj/machinery/computer/arcade/minesweeper + name = "Minesweeper" + desc = "An arcade machine that generates grids. It seems that the machine sparks and screeches when a grid is generated, as if it cannot cope with the intensity of generating the grid." + icon_state = "arcade" + circuit = /obj/item/circuitboard/computer/arcade/minesweeper + var/area + var/difficulty = "" //To show what difficulty you are playing + var/flag_text = "" + var/flagging = FALSE + var/game_status = MINESWEEPER_GAME_MAIN_MENU + var/mine_limit = 0 + var/mine_placed = 0 + var/mine_sound = TRUE //So it doesn't get repeated when multiple mines are exposed + var/randomcolour = 1 + var/randomnumber = 1 //Random emagged game iteration number to be displayed, put here so it is persistent across one individual arcade machine + var/safe_squares_revealed + var/saved_web = "" //To display the web if you click on the arcade + var/win_condition + var/rows = 1 + var/columns = 1 + var/table[31][51] //Make the board boys, 30x50 board + var/spark_spam = FALSE + +/obj/machinery/computer/arcade/minesweeper/interact(mob/user) + var/emagged = CHECK_BITFIELD(obj_flags, EMAGGED) + var/dat + if(game_status == MINESWEEPER_GAME_MAIN_MENU) + dat += "Minesweeper
Minesweeper[emagged ? " EXTREME EDITION: Iteration #[randomnumber]" : ""]
" //Different colour mix for every random number made + dat += " [emagged ? "Explode in the game, explode in real life" : "Reveal all the squares without hitting a mine"]!
What difficulty do you want to play?



Easy (9x9 board, 10 mines)
Intermediate (16x16 board, 40 mines)
Hard (16x30 board, 99 mines)
Custom" + else + dat = saved_web + user = usr + + var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/simple/minesweeper) + assets.send(user) + + user << browse(dat,"window=minesweeper,size=400x500") + add_fingerprint(user) + + . = ..() + +/obj/machinery/computer/arcade/minesweeper/proc/reset_spark_spam() + spark_spam = FALSE + +/obj/machinery/computer/arcade/minesweeper/Topic(href, href_list) + . = ..() + if(.) + return + + var/exploding_hell = FALSE //For emagged failures + var/reset_board = FALSE + var/mob/living/user = usr //To identify who the hell is using this window, this should also make things like aliens and monkeys able to use the machine!! + var/web_difficulty_menu = " Reveal all the squares without hitting a mine!
What difficulty do you want to play?



Easy (9x9 board, 10 mines)
Intermediate (16x16 board, 40 mines)
Hard (16x30 board, 99 mines)
Custom" + var/web = "Minesweeper
Minesweeper
" + var/static_web = "Minesweeper
Minesweeper
" //When we need to revert to the main menu we set web as this + web = static_web + + if(CHECK_BITFIELD(obj_flags, EMAGGED)) + web = "Minesweeper
Minesweeper EXTREME EDITION: Iteration #[randomnumber]
" //Different colour mix for every random number made + if(!spark_spam) + do_sparks(5, 1, src) + spark_spam = TRUE + addtimer(CALLBACK(src, .proc/reset_spark_spam), 30) + + + var/startup_sound = CHECK_BITFIELD(obj_flags, EMAGGED) ? 'sound/arcade/minesweeper_emag2.ogg' : 'sound/arcade/minesweeper_startup.ogg' + + if(href_list["Main_Menu"]) + game_status = MINESWEEPER_GAME_MAIN_MENU + mine_limit = 0 + rows = 0 + columns = 0 + mine_placed = 0 + if(href_list["Easy"]) + playsound(loc, startup_sound, 50, 0, extrarange = -3, falloff = 10) + flag_text = "OFF" + game_status = MINESWEEPER_GAME_PLAYING + reset_board = TRUE + difficulty = "Easy" + rows = 10 //9x9 board + columns = 10 + mine_limit = 10 + if(href_list["Intermediate"]) + playsound(loc, startup_sound, 50, 0, extrarange = -3, falloff = 10) + flag_text = "OFF" + game_status = MINESWEEPER_GAME_PLAYING + reset_board = TRUE + difficulty = "Intermediate" + rows = 17 //16x16 board + columns = 17 + mine_limit = 40 + if(href_list["Hard"]) + playsound(loc, startup_sound, 50, 0, extrarange = -3, falloff = 10) + flag_text = "OFF" + game_status = MINESWEEPER_GAME_PLAYING + reset_board = TRUE + difficulty = "Hard" + rows = 17 //16x30 board + columns = 31 + mine_limit = 99 + if(href_list["Custom"]) + if(custom_generation(usr)) + flag_text = "OFF" + game_status = MINESWEEPER_GAME_PLAYING + reset_board = TRUE + difficulty = "Custom" + playsound(loc, startup_sound, 50, 0, extrarange = -3, falloff = 10) + if(href_list["Flag"]) + playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, 0, extrarange = -3, falloff = 10) + if(!flagging) + flagging = TRUE + flag_text = "ON" + else + flagging = FALSE + flag_text = "OFF" + + if(game_status == MINESWEEPER_GAME_MAIN_MENU) + if(CHECK_BITFIELD(obj_flags, EMAGGED)) + playsound(loc, 'sound/arcade/minesweeper_emag2.ogg', 50, 0, extrarange = -3, falloff = 10) + web += "Explode in the game, explode in real life!
What difficulty do you want to play?



Easy (9x9 board, 10 mines)
Intermediate (16x16 board, 40 mines)
Hard (16x30 board, 99 mines)
Custom" + else + playsound(loc, 'sound/arcade/minesweeper_startup.ogg', 50, 0, extrarange = -3, falloff = 10) + web += web_difficulty_menu + + if(game_status == MINESWEEPER_GAME_PLAYING) + mine_sound = TRUE + + area = (rows-1)*(columns-1) + + if(reset_board) + mine_placed = 0 + var/reset_everything = TRUE + make_mines(reset_everything) + + safe_squares_revealed = 0 + win_condition = area-mine_placed + + if(game_status != MINESWEEPER_GAME_MAIN_MENU) + for(var/y1=1;y1= 0) //Check that it's not already revealed, and stop flag removal if we're out of flag mode + table[y1][x1] += 10 + if(table[y1][x1] != 10) + playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, 0, extrarange = -3, falloff = 10) + else + if(game_status != MINESWEEPER_GAME_LOST && game_status != MINESWEEPER_GAME_WON) + game_status = MINESWEEPER_GAME_LOST + if(CHECK_BITFIELD(obj_flags, EMAGGED) && !exploding_hell) + exploding_hell = TRUE + explode_EVERYTHING() + if(mine_sound) + switch(rand(1,3)) //Play every time a mine is hit + if(1) + playsound(loc, 'sound/arcade/minesweeper_explosion1.ogg', 50, 0, extrarange = -3, falloff = 10) + if(2) + playsound(loc, 'sound/arcade/minesweeper_explosion2.ogg', 50, 0, extrarange = -3, falloff = 10) + if(3) + playsound(loc, 'sound/arcade/minesweeper_explosion3.ogg', 50, 0, extrarange = -3, falloff = 10) + mine_sound = FALSE + else + playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, 0, extrarange = -3, falloff = 10) + if(table[y1][x1] >= 0) //Check that it's not already flagged + table[y1][x1] -= 10 + else if(table[y1][x1] < 0) //If flagged, remove the flag + table[y1][x1] += 10 + if(href_list["same_board"]) //Reset the board... kinda + if(game_status != MINESWEEPER_GAME_PLAYING) + game_status = MINESWEEPER_GAME_PLAYING + if(table[y1][x1] >= 10) //If revealed, become unrevealed! + playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) + table[y1][x1] -= 10 + if(table[y1][x1] > 10 && !reset_board) + safe_squares_revealed += 1 + var/y2 = y1 + var/x2 = x1 + work_squares(y2, x2) //Work squares while in this loop so there's less load + reset_board = FALSE + + web += "" //Start setting up the html table + web += "" + for(var/y1=1;y1= win_condition && game_status == MINESWEEPER_GAME_PLAYING) + game_status = MINESWEEPER_GAME_WON + if(rows < 10 || columns < 10) //If less than easy difficulty + playsound(loc, 'sound/arcade/minesweeper_winfail.ogg', 50, 0, extrarange = -3, falloff = 10) + say("You cleared the board of all mines, but you picked too small of a board! Try again with at least a 9x9 board!") + else + playsound(loc, 'sound/arcade/minesweeper_win.ogg', 50, 0, extrarange = -3, falloff = 10) + say("You cleared the board of all mines! Congratulations!") + if(CHECK_BITFIELD(obj_flags, EMAGGED)) + var/itemname + switch(rand(1,3)) + if(1) + itemname = "a syndicate bomb beacon" + new /obj/item/sbeacondrop/bomb(loc) + if(2) + itemname = "a grenade launcher" + new /obj/item/gun/ballistic/revolver/grenadelauncher/unrestricted(loc) + new /obj/item/ammo_casing/a40mm(loc) + new /obj/item/ammo_casing/a40mm(loc) + new /obj/item/ammo_casing/a40mm(loc) + if(3) + itemname = "two bags of c4" + new /obj/item/storage/backpack/duffelbag/syndie/c4(loc) + new /obj/item/storage/backpack/duffelbag/syndie/x4(loc) + message_admins("[key_name_admin(user)] won emagged Minesweeper and got [itemname]!") + visible_message("[src] dispenses [itemname]!", "You hear a chime and a clunk.") + DISABLE_BITFIELD(obj_flags, EMAGGED) + else + var/dope_prizes = (area >= 480) ? list(ARCADE_WEIGHT_RARE) : (area >= 256) ? list(ARCADE_WEIGHT_RARE, ARCADE_WEIGHT_TRICK) : null + prizevend(user, dope_prizes) + + if(game_status == MINESWEEPER_GAME_WON) + web += "[(rows < 10 || columns < 10) ? "You won, but your board was too small! Pick a bigger board next time!" : "Congratulations, you have won!"]
Want to play again?
Easy (9x9 board, 10 mines)
Intermediate (16x16 board, 40 mines)
Hard (16x30 board, 99 mines)
Custom

Play on the same board
Return to Main Menu
" + + if(game_status == MINESWEEPER_GAME_LOST) + web += "You have lost!
Try again?
Easy (9x9 board, 10 mines)
Intermediate (16x16 board, 40 mines)
Hard (16x30 board, 99 mines)
Custom

Play on the same board
Return to Main Menu
" + + if(game_status == MINESWEEPER_GAME_PLAYING) + web += "Return to Main Menu
" + web += "
Difficulty: [difficulty]
Mines: [mine_placed]
Rows: [rows-1]
Columns: [columns-1]
Flagging mode: [flag_text]
" + + web += "" + var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/minesweeper) + saved_web = sheet.css_tag() + saved_web += web + updateDialog() + return + +/obj/machinery/computer/arcade/minesweeper/emag_act(mob/user) + if(CHECK_BITFIELD(obj_flags, EMAGGED)) + return + desc = "An arcade machine that generates grids. It's clunking and sparking everywhere, almost as if threatening to explode at any moment!" + do_sparks(5, 1, src) + randomnumber = rand(1,255) + randomcolour = rgb(randomnumber,randomnumber/2,randomnumber/3) + ENABLE_BITFIELD(obj_flags, EMAGGED) + if(game_status == MINESWEEPER_GAME_MAIN_MENU) + to_chat(user, "An ominous tune plays from the arcade's speakers!") + playsound(user, 'sound/arcade/minesweeper_emag1.ogg', 100, 0, extrarange = 3, falloff = 10) + else //Can't let you do that, star fox! + to_chat(user, "The machine buzzes and sparks... the game has been reset!") + playsound(user, 'sound/machines/buzz-sigh.ogg', 100, 0, extrarange = 3, falloff = 10) //Loud buzz + game_status = MINESWEEPER_GAME_MAIN_MENU + +/obj/machinery/computer/arcade/minesweeper/proc/custom_generation(mob/user) + playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) //Entered into the menu so ping sound + var/new_rows = input(user, "How many rows do you want? (Minimum: 4, Maximum: 30)", "Minesweeper Rows") as null|num + if(!new_rows || !user.canUseTopic(src, !issilicon(user))) + return FALSE + new_rows = CLAMP(new_rows + 1, 4, 30) + playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) + var/new_columns = input(user, "How many columns do you want? (Minimum: 4, Maximum: 50)", "Minesweeper Squares") as null|num + if(!new_columns || !user.canUseTopic(src, !issilicon(user))) + return FALSE + new_columns = CLAMP(new_columns + 1, 4, 50) + playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) + var/grid_area = (new_rows - 1) * (new_columns - 1) + var/lower_limit = round(grid_area*0.156) + var/upper_limit = round(grid_area*0.85) + var/new_mine_limit = input(user, "How many mines do you want? (Minimum: [lower_limit], Maximum: [upper_limit])", "Minesweeper Mines") as null|num + if(!new_mine_limit || !user.canUseTopic(src, !issilicon(user))) + return FALSE + playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) + rows = new_rows + columns = new_columns + mine_limit = CLAMP(new_mine_limit, lower_limit, upper_limit) + return TRUE + +/obj/machinery/computer/arcade/minesweeper/proc/make_mines(var/reset_everything) + if(mine_placed < mine_limit) + for(var/y1=1;y1 0 && x3 > 0) + y2 = y3 + x2 = x3 + if(table[y2][x2] == 1) + for(y3=y2-1;y3= rows || y3 < 1) + continue + for(x3=x2-1;x3= columns || x3 < 1) + continue + if(table[y3][x3] == 0) + table[y2][x2] += 1 + if(table[y2][x2] == 11) + for(y3=y2-1;y3= rows || y3 < 1) + continue + for(x3=x2-1;x3= columns || x3 < 1) + continue + if(table[y3][x3] > 0 && table[y3][x3] < 10) + table[y3][x3] += 10 + work_squares(y3, x3) //Refresh so we check everything we might be missing + +/obj/machinery/computer/arcade/minesweeper/proc/explode_EVERYTHING() + var/mob/living/user = usr + to_chat(user, "You feel a great sense of dread wash over you, as if you just unleashed armageddon upon yourself!") + var/row_limit = rows-1 + var/column_limit = columns-1 + var/mine_limit_v2 = mine_limit + if(rows > 11) + row_limit = 10 + if(columns > 11) + column_limit = 10 + if(mine_limit > (rows*columns) * 0.25) + mine_limit_v2 = 24 + message_admins("[key_name_admin(user)] failed an emagged Minesweeper arcade and has unleashed an explosion armageddon of size [row_limit],[column_limit] around [ADMIN_LOOKUPFLW(user.loc)]!") + if(mine_limit_v2 < 10) + explosion(loc, 2, 5, 10, 15) //Thought you could survive by putting as few mines as possible, huh?? + else + explosion(loc, 1, 3, rand(1,5), rand(1,10)) + for(var/y69=y-row_limit;y69coward!\"" + icon_state = "arcade" + circuit = /obj/item/circuitboard/computer/arcade/amputation + +/obj/machinery/computer/arcade/amputation/attack_hand(mob/user) + if(!iscarbon(user)) + return + var/mob/living/carbon/c_user = user + if(!c_user.get_bodypart(BODY_ZONE_L_ARM) && !c_user.get_bodypart(BODY_ZONE_R_ARM)) + return + to_chat(c_user, "You move your hand towards the machine, and begin to hesitate as a bloodied guillotine emerges from inside of it...") + if(do_after(c_user, 50, target = src)) + to_chat(c_user, "The guillotine drops on your arm, and the machine sucks it in!") + playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) + var/which_hand = BODY_ZONE_L_ARM + if(!(c_user.active_hand_index % 2)) + which_hand = BODY_ZONE_R_ARM + var/obj/item/bodypart/chopchop = c_user.get_bodypart(which_hand) + chopchop.dismember() + qdel(chopchop) + playsound(loc, 'sound/arcade/win.ogg', 50, 1, extrarange = -3, falloff = 10) + for(var/i=1; i<=rand(3,5); i++) + prizevend(user) + else + to_chat(c_user, "You (wisely) decide against putting your hand in the machine.") \ No newline at end of file diff --git a/code/game/machinery/computer/arcade/orion_trail.dm b/code/game/machinery/computer/arcade/orion_trail.dm new file mode 100644 index 0000000000..12941dea35 --- /dev/null +++ b/code/game/machinery/computer/arcade/orion_trail.dm @@ -0,0 +1,809 @@ + + +// *** THE ORION TRAIL ** // + +#define ORION_TRAIL_WINTURN 9 + +//Orion Trail Events +#define ORION_TRAIL_RAIDERS "Raiders" +#define ORION_TRAIL_FLUX "Interstellar Flux" +#define ORION_TRAIL_ILLNESS "Illness" +#define ORION_TRAIL_BREAKDOWN "Breakdown" +#define ORION_TRAIL_LING "Changelings?" +#define ORION_TRAIL_LING_ATTACK "Changeling Ambush" +#define ORION_TRAIL_MALFUNCTION "Malfunction" +#define ORION_TRAIL_COLLISION "Collision" +#define ORION_TRAIL_SPACEPORT "Spaceport" +#define ORION_TRAIL_BLACKHOLE "BlackHole" + +#define ORION_STATUS_START 1 +#define ORION_STATUS_NORMAL 2 +#define ORION_STATUS_GAMEOVER 3 +#define ORION_STATUS_MARKET 4 + +/obj/machinery/computer/arcade/orion_trail + name = "The Orion Trail" + desc = "Learn how our ancestors got to Orion, and have fun in the process!" + icon_state = "arcade" + circuit = /obj/item/circuitboard/computer/arcade/orion_trail + var/busy = FALSE //prevent clickspam that allowed people to ~speedrun~ the game. + var/engine = 0 + var/hull = 0 + var/electronics = 0 + var/food = 80 + var/fuel = 60 + var/turns = 4 + var/alive = 4 + var/eventdat = null + var/event = null + var/list/settlers = list("Harry","Larry","Bob") + var/list/events = list(ORION_TRAIL_RAIDERS = 3, + ORION_TRAIL_FLUX = 1, + ORION_TRAIL_ILLNESS = 3, + ORION_TRAIL_BREAKDOWN = 2, + ORION_TRAIL_LING = 3, + ORION_TRAIL_MALFUNCTION = 2, + ORION_TRAIL_COLLISION = 1, + ORION_TRAIL_SPACEPORT = 2 + ) + var/list/stops = list() + var/list/stopblurbs = list() + var/lings_aboard = 0 + var/spaceport_raided = 0 + var/spaceport_freebie = 0 + var/last_spaceport_action = "" + var/gameStatus = ORION_STATUS_START + var/canContinueEvent = 0 + +/obj/machinery/computer/arcade/orion_trail/kobayashi + name = "Kobayashi Maru control computer" + desc = "A test for cadets" + icon = 'icons/obj/machines/particle_accelerator.dmi' + icon_state = "control_boxp" + events = list("Raiders" = 3, "Interstellar Flux" = 1, "Illness" = 3, "Breakdown" = 2, "Malfunction" = 2, "Collision" = 1, "Spaceport" = 2) + prizes = list(/obj/item/paper/fluff/holodeck/trek_diploma = 1) + settlers = list("Kirk","Worf","Gene") + +/obj/machinery/computer/arcade/orion_trail/Reset() + // Sets up the main trail + stops = list("Pluto","Asteroid Belt","Proxima Centauri","Dead Space","Rigel Prime","Tau Ceti Beta","Black Hole","Space Outpost Beta-9","Orion Prime") + stopblurbs = list( + "Pluto, long since occupied with long-range sensors and scanners, stands ready to, and indeed continues to probe the far reaches of the galaxy.", + "At the edge of the Sol system lies a treacherous asteroid belt. Many have been crushed by stray asteroids and misguided judgement.", + "The nearest star system to Sol, in ages past it stood as a reminder of the boundaries of sub-light travel, now a low-population sanctuary for adventurers and traders.", + "This region of space is particularly devoid of matter. Such low-density pockets are known to exist, but the vastness of it is astounding.", + "Rigel Prime, the center of the Rigel system, burns hot, basking its planetary bodies in warmth and radiation.", + "Tau Ceti Beta has recently become a waypoint for colonists headed towards Orion. There are many ships and makeshift stations in the vicinity.", + "Sensors indicate that a black hole's gravitational field is affecting the region of space we were headed through. We could stay of course, but risk of being overcome by its gravity, or we could change course to go around, which will take longer.", + "You have come into range of the first man-made structure in this region of space. It has been constructed not by travellers from Sol, but by colonists from Orion. It stands as a monument to the colonists' success.", + "You have made it to Orion! Congratulations! Your crew is one of the few to start a new foothold for mankind!" + ) + +/obj/machinery/computer/arcade/orion_trail/proc/newgame() + // Set names of settlers in crew + settlers = list() + for(var/i = 1; i <= 3; i++) + add_crewmember() + add_crewmember("[usr]") + // Re-set items to defaults + engine = 1 + hull = 1 + electronics = 1 + food = 80 + fuel = 60 + alive = 4 + turns = 1 + event = null + gameStatus = ORION_STATUS_NORMAL + lings_aboard = 0 + + //spaceport junk + spaceport_raided = 0 + spaceport_freebie = 0 + last_spaceport_action = "" + +/obj/machinery/computer/arcade/orion_trail/ui_interact(mob/user) + . = ..() + if(fuel <= 0 || food <=0 || settlers.len == 0) + gameStatus = ORION_STATUS_GAMEOVER + event = null + var/dat = "" + if(gameStatus == ORION_STATUS_GAMEOVER) + dat = "

Game Over

" + dat += "Like many before you, your crew never made it to Orion, lost to space...
Forever." + if(!settlers.len) + dat += "
Your entire crew died, and your ship joins the fleet of ghost-ships littering the galaxy." + else + if(food <= 0) + dat += "
You ran out of food and starved." + if(obj_flags & EMAGGED) + user.nutrition = 0 //yeah you pretty hongry + to_chat(user, "Your body instantly contracts to that of one who has not eaten in months. Agonizing cramps seize you as you fall to the floor.") + if(fuel <= 0) + dat += "
You ran out of fuel, and drift, slowly, into a star." + if(obj_flags & EMAGGED) + var/mob/living/M = user + M.adjust_fire_stacks(5) + M.IgniteMob() //flew into a star, so you're on fire + to_chat(user, "You feel an immense wave of heat emanate from the arcade machine. Your skin bursts into flames.") + + if(obj_flags & EMAGGED) + to_chat(user, "You're never going to make it to Orion...") + user.death() + obj_flags &= ~EMAGGED //removes the emagged status after you lose + gameStatus = ORION_STATUS_START + name = "The Orion Trail" + desc = "Learn how our ancestors got to Orion, and have fun in the process!" + + dat += "

May They Rest In Peace

" + else if(event) + dat = eventdat + else if(gameStatus == ORION_STATUS_NORMAL) + var/title = stops[turns] + var/subtext = stopblurbs[turns] + dat = "

[title]

" + dat += "[subtext]" + dat += "

Crew:

" + dat += english_list(settlers) + dat += "
Food: [food] | Fuel: [fuel]" + dat += "
Engine Parts: [engine] | Hull Panels: [hull] | Electronics: [electronics]" + if(turns == 7) + dat += "

Go Around Continue

" + else + dat += "

Continue

" + dat += "

Kill a Crewmember

" + dat += "

Close

" + else + dat = "

The Orion Trail

" + dat += "

Experience the journey of your ancestors!



" + dat += "
New Game
" + dat += "

Close

" + var/datum/browser/popup = new(user, "arcade", "The Orion Trail",400,700) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) + popup.open() + return + +/obj/machinery/computer/arcade/orion_trail/Topic(href, href_list) + if(..()) + return + if(href_list["close"]) + usr.unset_machine() + usr << browse(null, "window=arcade") + + if(busy) + return + busy = TRUE + + if (href_list["continue"]) //Continue your travels + if(gameStatus == ORION_STATUS_NORMAL && !event && turns != 7) + if(turns >= ORION_TRAIL_WINTURN) + win(usr) + else + food -= (alive+lings_aboard)*2 + fuel -= 5 + if(turns == 2 && prob(30)) + event = ORION_TRAIL_COLLISION + event() + else if(prob(75)) + event = pickweight(events) + if(lings_aboard) + if(event == ORION_TRAIL_LING || prob(55)) + event = ORION_TRAIL_LING_ATTACK + event() + turns += 1 + if(obj_flags & EMAGGED) + var/mob/living/carbon/M = usr //for some vars + switch(event) + if(ORION_TRAIL_RAIDERS) + if(prob(50)) + to_chat(usr, "You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?") + M.hallucination += 30 + else + to_chat(usr, "Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there...") + M.take_bodypart_damage(30) + playsound(loc, 'sound/weapons/genhit2.ogg', 100, 1) + if(ORION_TRAIL_ILLNESS) + var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS + if(severity == 1) + to_chat(M, "You suddenly feel slightly nauseated." ) + if(severity == 2) + to_chat(usr, "You suddenly feel extremely nauseated and hunch over until it passes.") + M.Stun(60) + if(severity >= 3) //you didn't pray hard enough + to_chat(M, "An overpowering wave of nausea consumes over you. You hunch over, your stomach's contents preparing for a spectacular exit.") + M.Stun(100) + sleep(30) + M.vomit(10, distance = 5) + if(ORION_TRAIL_FLUX) + if(prob(75)) + M.Knockdown(60) + say("A sudden gust of powerful wind slams [M] into the floor!") + M.take_bodypart_damage(25) + playsound(loc, 'sound/weapons/genhit.ogg', 100, 1) + else + to_chat(M, "A violent gale blows past you, and you barely manage to stay standing!") + if(ORION_TRAIL_COLLISION) //by far the most damaging event + if(prob(90)) + playsound(loc, 'sound/effects/bang.ogg', 100, 1) + var/turf/open/floor/F + for(F in orange(1, src)) + F.ScrapeAway() + say("Something slams into the floor around [src], exposing it to space!") + if(hull) + sleep(10) + say("A new floor suddenly appears around [src]. What the hell?") + playsound(loc, 'sound/weapons/genhit.ogg', 100, 1) + var/turf/open/space/T + for(T in orange(1, src)) + T.PlaceOnTop(/turf/open/floor/plating) + else + say("Something slams into the floor around [src] - luckily, it didn't get through!") + playsound(loc, 'sound/effects/bang.ogg', 50, 1) + if(ORION_TRAIL_MALFUNCTION) + playsound(loc, 'sound/effects/empulse.ogg', 50, 1) + visible_message("[src] malfunctions, randomizing in-game stats!") + var/oldfood = food + var/oldfuel = fuel + food = rand(10,80) / rand(1,2) + fuel = rand(10,60) / rand(1,2) + if(electronics) + sleep(10) + if(oldfuel > fuel && oldfood > food) + audible_message("[src] lets out a somehow reassuring chime.") + else if(oldfuel < fuel || oldfood < food) + audible_message("[src] lets out a somehow ominous chime.") + food = oldfood + fuel = oldfuel + playsound(loc, 'sound/machines/chime.ogg', 50, 1) + + else if(href_list["newgame"]) //Reset everything + if(gameStatus == ORION_STATUS_START) + newgame() + else if(href_list["menu"]) //back to the main menu + if(gameStatus == ORION_STATUS_GAMEOVER) + gameStatus = ORION_STATUS_START + event = null + food = 80 + fuel = 60 + settlers = list("Harry","Larry","Bob") + else if(href_list["slow"]) //slow down + if(event == ORION_TRAIL_FLUX) + food -= (alive+lings_aboard)*2 + fuel -= 5 + event = null + else if(href_list["pastblack"]) //slow down + if(turns == 7) + food -= ((alive+lings_aboard)*2)*3 + fuel -= 15 + turns += 1 + event = null + else if(href_list["useengine"]) //use parts + if(event == ORION_TRAIL_BREAKDOWN) + engine = max(0, --engine) + event = null + else if(href_list["useelec"]) //use parts + if(event == ORION_TRAIL_MALFUNCTION) + electronics = max(0, --electronics) + event = null + else if(href_list["usehull"]) //use parts + if(event == ORION_TRAIL_COLLISION) + hull = max(0, --hull) + event = null + else if(href_list["wait"]) //wait 3 days + if(event == ORION_TRAIL_BREAKDOWN || event == ORION_TRAIL_MALFUNCTION || event == ORION_TRAIL_COLLISION) + food -= ((alive+lings_aboard)*2)*3 + event = null + else if(href_list["keepspeed"]) //keep speed + if(event == ORION_TRAIL_FLUX) + if(prob(75)) + event = "Breakdown" + event() + else + event = null + else if(href_list["blackhole"]) //keep speed past a black hole + if(turns == 7) + if(prob(75)) + event = ORION_TRAIL_BLACKHOLE + event() + if(obj_flags & EMAGGED) + playsound(loc, 'sound/effects/supermatter.ogg', 100, 1) + say("A miniature black hole suddenly appears in front of [src], devouring [usr] alive!") + if(isliving(usr)) + var/mob/living/L = usr + L.Stun(200, ignore_canstun = TRUE) //you can't run :^) + var/S = new /obj/singularity/academy(usr.loc) + addtimer(CALLBACK(src, /atom/movable/proc/say, "[S] winks out, just as suddenly as it appeared."), 50) + QDEL_IN(S, 50) + else + event = null + turns += 1 + else if(href_list["holedeath"]) + if(event == ORION_TRAIL_BLACKHOLE) + gameStatus = ORION_STATUS_GAMEOVER + event = null + else if(href_list["eventclose"]) //end an event + if(canContinueEvent) + event = null + + else if(href_list["killcrew"]) //shoot a crewmember + if(gameStatus == ORION_STATUS_NORMAL || event == ORION_TRAIL_LING) + var/sheriff = remove_crewmember() //I shot the sheriff + playsound(loc,'sound/weapons/gunshot.ogg', 100, 1) + + if(settlers.len == 0 || alive == 0) + say("The last crewmember [sheriff], shot themselves, GAME OVER!") + if(obj_flags & EMAGGED) + usr.death(0) + obj_flags &= EMAGGED + gameStatus = ORION_STATUS_GAMEOVER + event = null + else if(obj_flags & EMAGGED) + if(usr.name == sheriff) + say("The crew of the ship chose to kill [usr.name]!") + usr.death(0) + + if(event == ORION_TRAIL_LING) //only ends the ORION_TRAIL_LING event, since you can do this action in multiple places + event = null + + //Spaceport specific interactions + //they get a header because most of them don't reset event (because it's a shop, you leave when you want to) + //they also call event() again, to regen the eventdata, which is kind of odd but necessary + else if(href_list["buycrew"]) //buy a crewmember + if(gameStatus == ORION_STATUS_MARKET) + if(!spaceport_raided && food >= 10 && fuel >= 10) + var/bought = add_crewmember() + last_spaceport_action = "You hired [bought] as a new crewmember." + fuel -= 10 + food -= 10 + event() + + else if(href_list["sellcrew"]) //sell a crewmember + if(gameStatus == ORION_STATUS_MARKET) + if(!spaceport_raided && settlers.len > 1) + var/sold = remove_crewmember() + last_spaceport_action = "You sold your crewmember, [sold]!" + fuel += 7 + food += 7 + event() + + else if(href_list["leave_spaceport"]) + if(gameStatus == ORION_STATUS_MARKET) + event = null + gameStatus = ORION_STATUS_NORMAL + spaceport_raided = 0 + spaceport_freebie = 0 + last_spaceport_action = "" + + else if(href_list["raid_spaceport"]) + if(gameStatus == ORION_STATUS_MARKET) + if(!spaceport_raided) + var/success = min(15 * alive,100) //default crew (4) have a 60% chance + spaceport_raided = 1 + + var/FU = 0 + var/FO = 0 + if(prob(success)) + FU = rand(5,15) + FO = rand(5,15) + last_spaceport_action = "You successfully raided the spaceport! You gained [FU] Fuel and [FO] Food! (+[FU]FU,+[FO]FO)" + else + FU = rand(-5,-15) + FO = rand(-5,-15) + last_spaceport_action = "You failed to raid the spaceport! You lost [FU*-1] Fuel and [FO*-1] Food in your scramble to escape! ([FU]FU,[FO]FO)" + + //your chance of lose a crewmember is 1/2 your chance of success + //this makes higher % failures hurt more, don't get cocky space cowboy! + if(prob(success*5)) + var/lost_crew = remove_crewmember() + last_spaceport_action = "You failed to raid the spaceport! You lost [FU*-1] Fuel and [FO*-1] Food, AND [lost_crew] in your scramble to escape! ([FU]FI,[FO]FO,-Crew)" + if(obj_flags & EMAGGED) + say("WEEWOO! WEEWOO! Spaceport security en route!") + playsound(src, 'sound/items/weeoo1.ogg', 100, FALSE) + for(var/i, i<=3, i++) + var/mob/living/simple_animal/hostile/syndicate/ranged/smg/orion/O = new/mob/living/simple_animal/hostile/syndicate/ranged/smg/orion(get_turf(src)) + O.target = usr + + + fuel += FU + food += FO + event() + + else if(href_list["buyparts"]) + if(gameStatus == ORION_STATUS_MARKET) + if(!spaceport_raided && fuel > 5) + switch(text2num(href_list["buyparts"])) + if(1) //Engine Parts + engine++ + last_spaceport_action = "Bought Engine Parts" + if(2) //Hull Plates + hull++ + last_spaceport_action = "Bought Hull Plates" + if(3) //Spare Electronics + electronics++ + last_spaceport_action = "Bought Spare Electronics" + fuel -= 5 //they all cost 5 + event() + + else if(href_list["trade"]) + if(gameStatus == ORION_STATUS_MARKET) + if(!spaceport_raided) + switch(text2num(href_list["trade"])) + if(1) //Fuel + if(fuel > 5) + fuel -= 5 + food += 5 + last_spaceport_action = "Traded Fuel for Food" + event() + if(2) //Food + if(food > 5) + fuel += 5 + food -= 5 + last_spaceport_action = "Traded Food for Fuel" + event() + + add_fingerprint(usr) + updateUsrDialog() + busy = FALSE + return + + +/obj/machinery/computer/arcade/orion_trail/proc/event() + eventdat = "

[event]

" + canContinueEvent = 0 + switch(event) + if(ORION_TRAIL_RAIDERS) + eventdat += "Raiders have come aboard your ship!" + if(prob(50)) + var/sfood = rand(1,10) + var/sfuel = rand(1,10) + food -= sfood + fuel -= sfuel + eventdat += "
They have stolen [sfood] Food and [sfuel] Fuel." + else if(prob(10)) + var/deadname = remove_crewmember() + eventdat += "
[deadname] tried to fight back, but was killed." + else + eventdat += "
Fortunately, you fended them off without any trouble." + eventdat += "

Continue

" + eventdat += "

Close

" + canContinueEvent = 1 + + if(ORION_TRAIL_FLUX) + eventdat += "This region of space is highly turbulent.
If we go slowly we may avoid more damage, but if we keep our speed we won't waste supplies." + eventdat += "
What will you do?" + eventdat += "

Slow Down Continue

" + eventdat += "

Close

" + + if(ORION_TRAIL_ILLNESS) + eventdat += "A deadly illness has been contracted!" + var/deadname = remove_crewmember() + eventdat += "
[deadname] was killed by the disease." + eventdat += "

Continue

" + eventdat += "

Close

" + canContinueEvent = 1 + + if(ORION_TRAIL_BREAKDOWN) + eventdat += "Oh no! The engine has broken down!" + eventdat += "
You can repair it with an engine part, or you can make repairs for 3 days." + if(engine >= 1) + eventdat += "

Use PartWait

" + else + eventdat += "

Wait

" + eventdat += "

Close

" + + if(ORION_TRAIL_MALFUNCTION) + eventdat += "The ship's systems are malfunctioning!" + eventdat += "
You can replace the broken electronics with spares, or you can spend 3 days troubleshooting the AI." + if(electronics >= 1) + eventdat += "

Use PartWait

" + else + eventdat += "

Wait

" + eventdat += "

Close

" + + if(ORION_TRAIL_COLLISION) + eventdat += "Something hit us! Looks like there's some hull damage." + if(prob(25)) + var/sfood = rand(5,15) + var/sfuel = rand(5,15) + food -= sfood + fuel -= sfuel + eventdat += "
[sfood] Food and [sfuel] Fuel was vented out into space." + if(prob(10)) + var/deadname = remove_crewmember() + eventdat += "
[deadname] was killed by rapid depressurization." + eventdat += "
You can repair the damage with hull plates, or you can spend the next 3 days welding scrap together." + if(hull >= 1) + eventdat += "

Use PartWait

" + else + eventdat += "

Wait

" + eventdat += "

Close

" + + if(ORION_TRAIL_BLACKHOLE) + eventdat += "You were swept away into the black hole." + eventdat += "

Oh...

" + eventdat += "

Close

" + settlers = list() + + if(ORION_TRAIL_LING) + eventdat += "Strange reports warn of changelings infiltrating crews on trips to Orion..." + if(settlers.len <= 2) + eventdat += "
Your crew's chance of reaching Orion is so slim the changelings likely avoided your ship..." + eventdat += "

Continue

" + eventdat += "

Close

" + if(prob(10)) // "likely", I didn't say it was guaranteed! + lings_aboard = min(++lings_aboard,2) + else + if(lings_aboard) //less likely to stack lings + if(prob(20)) + lings_aboard = min(++lings_aboard,2) + else if(prob(70)) + lings_aboard = min(++lings_aboard,2) + + eventdat += "

Kill a Crewmember

" + eventdat += "

Risk it

" + eventdat += "

Close

" + canContinueEvent = 1 + + if(ORION_TRAIL_LING_ATTACK) + if(lings_aboard <= 0) //shouldn't trigger, but hey. + eventdat += "Haha, fooled you, there are no changelings on board!" + eventdat += "
(You should report this to a coder :S)" + else + var/ling1 = remove_crewmember() + var/ling2 = "" + if(lings_aboard >= 2) + ling2 = remove_crewmember() + + eventdat += "Changelings among your crew suddenly burst from hiding and attack!" + if(ling2) + eventdat += "
[ling1] and [ling2]'s arms twist and contort into grotesque blades!" + else + eventdat += "
[ling1]'s arm twists and contorts into a grotesque blade!" + + var/chance2attack = alive*20 + if(prob(chance2attack)) + var/chancetokill = 30*lings_aboard-(5*alive) //eg: 30*2-(10) = 50%, 2 lings, 2 crew is 50% chance + if(prob(chancetokill)) + var/deadguy = remove_crewmember() + var/murder_text = pick("The changeling[ling2 ? "s" : ""] bring[ling2 ? "" : "s"] down [deadguy] and disembowel[ling2 ? "" : "s"] them in a spray of gore!", \ + "[ling2 ? pick(ling1, ling2) : ling1] corners [deadguy] and impales them through the stomach!", \ + "[ling2 ? pick(ling1, ling2) : ling1] decapitates [deadguy] in a single cleaving arc!") + eventdat += "
[murder_text]" + else + eventdat += "

You valiantly fight off the changeling[ling2 ? "s":""]!" + if(ling2) + food += 30 + lings_aboard = max(0,lings_aboard-2) + else + food += 15 + lings_aboard = max(0,--lings_aboard) + eventdat += "
Well, it's perfectly good food...\ +
You cut the changeling[ling2 ? "s" : ""] into meat, gaining [ling2 ? "30" : "15"] Food!" + else + eventdat += "

[pick("Sensing unfavorable odds", "After a failed attack", "Suddenly breaking nerve")], \ + the changeling[ling2 ? "s":""] vanish[ling2 ? "" : "es"] into space through the airlocks! You're safe... for now." + if(ling2) + lings_aboard = max(0,lings_aboard-2) + else + lings_aboard = max(0,--lings_aboard) + + eventdat += "

Continue

" + eventdat += "

Close

" + canContinueEvent = 1 + + + if(ORION_TRAIL_SPACEPORT) + gameStatus = ORION_STATUS_MARKET + if(spaceport_raided) + eventdat += "The spaceport is on high alert! You've been barred from docking by the local authorities after your failed raid." + if(last_spaceport_action) + eventdat += "
Last Spaceport Action: [last_spaceport_action]" + eventdat += "

Depart Spaceport

" + eventdat += "

Close

" + else + eventdat += "Your jump into the sector yields a spaceport - a lucky find!" + eventdat += "
This spaceport is home to travellers who failed to reach Orion, but managed to find a different home..." + eventdat += "
Trading terms: FU = Fuel, FO = Food" + if(last_spaceport_action) + eventdat += "
Last action: [last_spaceport_action]" + eventdat += "

Crew:

" + eventdat += english_list(settlers) + eventdat += "
Food: [food] | Fuel: [fuel]" + eventdat += "
Engine Parts: [engine] | Hull Panels: [hull] | Electronics: [electronics]" + + + //If your crew is pathetic you can get freebies (provided you haven't already gotten one from this port) + if(!spaceport_freebie && (fuel < 20 || food < 20)) + spaceport_freebie++ + var/FU = 10 + var/FO = 10 + var/freecrew = 0 + if(prob(30)) + FU = 25 + FO = 25 + + if(prob(10)) + add_crewmember() + freecrew++ + + eventdat += "
The traders of the spaceport take pity on you, and generously give you some free supplies! (+[FU]FU, +[FO]FO)" + if(freecrew) + eventdat += "
You also gain a new crewmember!" + + fuel += FU + food += FO + + //CREW INTERACTIONS + eventdat += "

Crew Management:

" + + //Buy crew + if(food >= 10 && fuel >= 10) + eventdat += "

Hire a New Crewmember (-10FU, -10FO)

" + else + eventdat += "

You cannot afford a new crewmember.

" + + //Sell crew + if(settlers.len > 1) + eventdat += "

Sell Crew for Fuel and Food (+7FU, +7FO)

" + else + eventdat += "

You have no other crew to sell.

" + + //BUY/SELL STUFF + eventdat += "

Spare Parts:

" + + //Engine parts + if(fuel > 5) + eventdat += "

Buy Engine Parts (-5FU)

" + else + eventdat += "

You cannot afford engine parts." + + //Hull plates + if(fuel > 5) + eventdat += "

Buy Hull Plates (-5FU)

" + else + eventdat += "

You cannot afford hull plates." + + //Electronics + if(fuel > 5) + eventdat += "

Buy Spare Electronics (-5FU)

" + else + eventdat += "

You cannot afford spare electronics." + + //Trade + if(fuel > 5) + eventdat += "

Trade Fuel for Food (-5FU,+5FO)

" + else + eventdat += "

You don't have 5FU to trade. 5) + eventdat += "

Trade Food for Fuel (+5FU,-5FO)

" + else + eventdat += "

You don't have 5FO to trade.You override the cheat code menu and skip to Cheat #[rand(1, 50)]: Realism Mode.") + name = "The Orion Trail: Realism Edition" + desc = "Learn how our ancestors got to Orion, and try not to die in the process!" + newgame() + obj_flags |= EMAGGED + +/mob/living/simple_animal/hostile/syndicate/ranged/smg/orion + name = "spaceport security" + desc = "Premier corporate security forces for all spaceports found along the Orion Trail." + faction = list("orion") + loot = list() + del_on_death = TRUE + +/obj/item/orion_ship + name = "model settler ship" + desc = "A model spaceship, it looks like those used back in the day when travelling to Orion! It even has a miniature FX-293 reactor, which was renowned for its instability and tendency to explode..." + icon = 'icons/obj/toy.dmi' + icon_state = "ship" + w_class = WEIGHT_CLASS_SMALL + var/active = 0 //if the ship is on + +/obj/item/orion_ship/examine(mob/user) + ..() + if(!(in_range(user, src))) + return + if(!active) + to_chat(user, "There's a little switch on the bottom. It's flipped down.") + else + to_chat(user, "There's a little switch on the bottom. It's flipped up.") + +/obj/item/orion_ship/attack_self(mob/user) //Minibomb-level explosion. Should probably be more because of how hard it is to survive the machine! Also, just over a 5-second fuse + if(active) + return + + message_admins("[ADMIN_LOOKUPFLW(usr)] primed an explosive Orion ship for detonation at [AREACOORD(usr)].") + log_game("[key_name(usr)] primed an explosive Orion ship for detonation at [AREACOORD(usr)].") + + to_chat(user, "You flip the switch on the underside of [src].") + active = 1 + visible_message("[src] softly beeps and whirs to life!") + playsound(loc, 'sound/machines/defib_SaftyOn.ogg', 25, 1) + say("This is ship ID #[rand(1,1000)] to Orion Port Authority. We're coming in for landing, over.") + sleep(20) + visible_message("[src] begins to vibrate...") + say("Uh, Port? Having some issues with our reactor, could you check it out? Over.") + sleep(30) + say("Oh, God! Code Eight! CODE EIGHT! IT'S GONNA BL-") + playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, 1) + sleep(3.6) + visible_message("[src] explodes!") + explosion(loc, 2,4,8, flame_range = 16) + qdel(src) + +#undef ORION_TRAIL_WINTURN +#undef ORION_TRAIL_RAIDERS +#undef ORION_TRAIL_FLUX +#undef ORION_TRAIL_ILLNESS +#undef ORION_TRAIL_BREAKDOWN +#undef ORION_TRAIL_LING +#undef ORION_TRAIL_LING_ATTACK +#undef ORION_TRAIL_MALFUNCTION +#undef ORION_TRAIL_COLLISION +#undef ORION_TRAIL_SPACEPORT +#undef ORION_TRAIL_BLACKHOLE + +#undef ORION_STATUS_START +#undef ORION_STATUS_NORMAL +#undef ORION_STATUS_GAMEOVER +#undef ORION_STATUS_MARKET diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index 4a77274d23..0e543a3642 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -214,6 +214,20 @@ /obj/item/aiModule/core/full/damaged ) +/obj/effect/spawner/lootdrop/mre + name = "random MRE" + icon = 'icons/obj/storage.dmi' + icon_state = "mre" + +/obj/effect/spawner/lootdrop/mre/Initialize() + for(var/A in subtypesof(/obj/item/storage/box/mre)) + var/obj/item/storage/box/mre/M = A + var/our_chance = initial(M.spawner_chance) + if(our_chance) + LAZYSET(loot, M, our_chance) + return ..() + + // Tech storage circuit board spawners // For these, make sure that lootcount equals the number of list items diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 3fbbab087f..2af7be2564 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -686,7 +686,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) ..() /obj/item/proc/microwave_act(obj/machinery/microwave/M) - if(M && M.dirty < 100) + if(istype(M) && M.dirty < 100) M.dirty++ /obj/item/proc/on_mob_death(mob/living/L, gibbed) diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index d64f5b57b8..000c52ae43 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -707,9 +707,9 @@ CIGARETTE PACKETS ARE IN FANCY.DM item_state = null w_class = WEIGHT_CLASS_TINY var/chem_volume = 100 - var/vapetime = 0 //this so it won't puff out clouds every tick - var/screw = 0 // kinky - var/super = 0 //for the fattest vapes dude. + var/vapetime = FALSE //this so it won't puff out clouds every tick + var/screw = FALSE // kinky + var/super = FALSE //for the fattest vapes dude. /obj/item/clothing/mask/vape/suicide_act(mob/user) user.visible_message("[user] is puffin hard on dat vape, [user.p_they()] trying to join the vape life on a whole notha plane!")//it doesn't give you cancer, it is cancer @@ -718,7 +718,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/vape/Initialize(mapload, param_color) . = ..() - DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT) + create_reagents(chem_volume, NO_REACT) // so it doesn't react until you light it reagents.add_reagent("nicotine", 50) if(!icon_state) if(!param_color) @@ -727,52 +727,48 @@ CIGARETTE PACKETS ARE IN FANCY.DM item_state = "[param_color]_vape" /obj/item/clothing/mask/vape/attackby(obj/item/O, mob/user, params) - if(O.is_drainable()) - if(reagents.total_volume < chem_volume) - if(O.reagents.total_volume > 0) - O.reagents.trans_to(src,25) - to_chat(user, "You add the contents of [O] to [src].") - else - to_chat(user, "[O] is empty!") - else - to_chat(user, "[src] can't hold anymore reagents!") - - if(istype(O, /obj/item/screwdriver)) + if(O.tool_behaviour == TOOL_SCREWDRIVER) if(!screw) - screw = 1 + screw = TRUE to_chat(user, "You open the cap on [src].") - if(super) + ENABLE_BITFIELD(reagents.reagents_holder_flags, OPENCONTAINER) + if(obj_flags & EMAGGED) + add_overlay("vapeopen_high") + else if(super) add_overlay("vapeopen_med") else add_overlay("vapeopen_low") else - screw = 0 + screw = FALSE to_chat(user, "You close the cap on [src].") + DISABLE_BITFIELD(reagents.reagents_holder_flags, OPENCONTAINER) cut_overlays() - if(istype(O, /obj/item/multitool)) + if(O.tool_behaviour == TOOL_MULTITOOL) if(screw && !(obj_flags & EMAGGED))//also kinky if(!super) cut_overlays() - super = 1 + super = TRUE to_chat(user, "You increase the voltage of [src].") add_overlay("vapeopen_med") else cut_overlays() - super = 0 + super = FALSE to_chat(user, "You decrease the voltage of [src].") add_overlay("vapeopen_low") if(screw && (obj_flags & EMAGGED)) to_chat(user, "[src] can't be modified!") + else + ..() /obj/item/clothing/mask/vape/emag_act(mob/user)// I WON'T REGRET WRITTING THIS, SURLY. if(screw) if(!(obj_flags & EMAGGED)) cut_overlays() obj_flags |= EMAGGED - super = 0 + super = FALSE to_chat(user, "You maximize the voltage of [src].") add_overlay("vapeopen_high") var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread //for effect diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index 26f00c730e..a1ee62e2eb 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -123,6 +123,14 @@ name = "Orion Trail (Computer Board)" build_path = /obj/machinery/computer/arcade/orion_trail +/obj/item/circuitboard/computer/arcade/minesweeper + name = "Minesweeper (Computer Board)" + build_path = /obj/machinery/computer/arcade/minesweeper + +/obj/item/circuitboard/computer/arcade/amputation + name = "Mediborg's Amputation Adventure (Computer Board)" + build_path = /obj/machinery/computer/arcade/amputation + /obj/item/circuitboard/computer/turbine_control name = "Turbine control (Computer Board)" build_path = /obj/machinery/computer/turbine_computer diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 5d4984b321..79c90b2a2f 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -10,6 +10,15 @@ GLOBAL_LIST_EMPTY(PDAs) #define PDA_SCANNER_HALOGEN 4 #define PDA_SCANNER_GAS 5 #define PDA_SPAM_DELAY 2 MINUTES +#define PDA_STANDARD_OVERLAYS list("pda-r", "blank", "id_overlay", "insert_overlay", "light_overlay", "pai_overlay") + +//pda icon overlays list defines +#define PDA_OVERLAY_ALERT 1 +#define PDA_OVERLAY_SCREEN 2 +#define PDA_OVERLAY_ID 3 +#define PDA_OVERLAY_ITEM 4 +#define PDA_OVERLAY_LIGHT 5 +#define PDA_OVERLAY_PAI 6 /obj/item/pda name = "\improper PDA" @@ -31,7 +40,8 @@ GLOBAL_LIST_EMPTY(PDAs) var/default_cartridge = 0 // Access level defined by cartridge var/obj/item/cartridge/cartridge = null //current cartridge var/mode = 0 //Controls what menu the PDA will display. 0 is hub; the rest are either built in or based on cartridge. - var/icon_alert = "pda-r" //Icon to be overlayed for message alerts. Taken from the pda icon file. + var/list/overlays_icons = list('icons/obj/pda_alt.dmi' = list("pda-r", "screen_default", "id_overlay", "insert_overlay", "light_overlay", "pai_overlay")) + var/current_overlays = PDA_STANDARD_OVERLAYS var/font_index = 0 //This int tells DM which font is currently selected and lets DM know when the last font has been selected so that it can cycle back to the first font when "toggle font" is pressed again. var/font_mode = "font-family:monospace;" //The currently selected font. var/background_color = "#808000" //The currently selected background color. @@ -78,7 +88,9 @@ GLOBAL_LIST_EMPTY(PDAs) var/list/contained_item = list(/obj/item/pen, /obj/item/toy/crayon, /obj/item/lipstick, /obj/item/flashlight/pen, /obj/item/clothing/mask/cigarette) var/obj/item/inserted_item //Used for pen, crayon, and lipstick insertion or removal. Same as above. - var/overlays_x_offset = 0 //x offset to use for certain overlays + var/list/overlays_offsets // offsets to use for certain overlays + var/overlays_x_offset = 0 + var/overlays_y_offset = 0 var/underline_flag = TRUE //flag for underline @@ -91,15 +103,13 @@ GLOBAL_LIST_EMPTY(PDAs) return BRUTELOSS /obj/item/pda/examine(mob/user) - ..() - if(!id && !inserted_item) - return - - if(id) - to_chat(user, "Alt-click to remove the id.") - + . = ..() + var/dat = id ? "Alt-click to remove the id." : "" if(inserted_item && (!isturf(loc))) - to_chat(user, "Ctrl-click to remove [inserted_item].") + dat += "\nCtrl-click to remove [inserted_item]." + if(LAZYLEN(GLOB.pda_reskins)) + dat += "\nCtrl-shift-click it to reskin it." + to_chat(user, dat) /obj/item/pda/Initialize() . = ..() @@ -115,28 +125,71 @@ GLOBAL_LIST_EMPTY(PDAs) inserted_item = new /obj/item/pen(src) update_icon() +/obj/item/pda/CtrlShiftClick(mob/living/user) + . = ..() + if(GLOB.pda_reskins && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY)) + reskin_obj(user) + +/obj/item/pda/reskin_obj(mob/M) + if(!LAZYLEN(GLOB.pda_reskins)) + return + var/dat = "Reskin options for [name]:" + for(var/V in GLOB.pda_reskins) + var/output = icon2html(GLOB.pda_reskins[V], M, icon_state) + dat += "\n[V]: [output]" + to_chat(M, dat) + + var/choice = input(M, "Choose the a reskin for [src]","Reskin Object") as null|anything in GLOB.pda_reskins + var/new_icon = GLOB.pda_reskins[choice] + if(QDELETED(src) || isnull(new_icon) || new_icon == icon || M.incapacitated() || !in_range(M,src)) + return + icon = new_icon + set_new_overlays() + update_icon() + to_chat(M, "[src] is now skinned as '[choice]'.") + +/obj/item/pda/proc/set_new_overlays() + if(!overlays_offsets || !(icon in overlays_offsets)) + overlays_x_offset = 0 + overlays_y_offset = 0 + else + var/list/new_offsets = overlays_offsets[icon] + if(new_offsets) + overlays_x_offset = new_offsets[1] + overlays_y_offset = new_offsets[2] + if(!(icon in overlays_icons)) + current_overlays = PDA_STANDARD_OVERLAYS + return + current_overlays = overlays_icons[icon] + /obj/item/pda/equipped(mob/user, slot) . = ..() - if(!equipped) - if(user.client) - background_color = user.client.prefs.pda_color - switch(user.client.prefs.pda_style) - if(MONO) - font_index = MODE_MONO - font_mode = FONT_MONO - if(SHARE) - font_index = MODE_SHARE - font_mode = FONT_SHARE - if(ORBITRON) - font_index = MODE_ORBITRON - font_mode = FONT_ORBITRON - if(VT) - font_index = MODE_VT - font_mode = FONT_VT - else - font_index = MODE_MONO - font_mode = FONT_MONO - equipped = TRUE + if(equipped) + return + if(user.client) + background_color = user.client.prefs.pda_color + switch(user.client.prefs.pda_style) + if(MONO) + font_index = MODE_MONO + font_mode = FONT_MONO + if(SHARE) + font_index = MODE_SHARE + font_mode = FONT_SHARE + if(ORBITRON) + font_index = MODE_ORBITRON + font_mode = FONT_ORBITRON + if(VT) + font_index = MODE_VT + font_mode = FONT_VT + else + font_index = MODE_MONO + font_mode = FONT_MONO + var/pref_skin = GLOB.pda_reskins[user.client.prefs.pda_skin] + if(icon != pref_skin) + icon = pref_skin + set_new_overlays() + update_icon() + equipped = TRUE /obj/item/pda/proc/update_label() name = "PDA-[owner] ([ownjob])" //Name generalisation @@ -150,26 +203,23 @@ GLOBAL_LIST_EMPTY(PDAs) /obj/item/pda/GetID() return id -/obj/item/pda/update_icon() +/obj/item/pda/update_icon(alert = FALSE) cut_overlays() + add_overlay(alert ? current_overlays[PDA_OVERLAY_ALERT] : current_overlays[PDA_OVERLAY_SCREEN]) var/mutable_appearance/overlay = new() overlay.pixel_x = overlays_x_offset if(id) - overlay.icon_state = "id_overlay" + overlay.icon_state = current_overlays[PDA_OVERLAY_ID] add_overlay(new /mutable_appearance(overlay)) if(inserted_item) - overlay.icon_state = "insert_overlay" + overlay.icon_state = current_overlays[PDA_OVERLAY_ITEM] add_overlay(new /mutable_appearance(overlay)) if(fon) - overlay.icon_state = "light_overlay" + overlay.icon_state = current_overlays[PDA_OVERLAY_LIGHT] add_overlay(new /mutable_appearance(overlay)) if(pai) - if(pai.pai) - overlay.icon_state = "pai_overlay" - add_overlay(new /mutable_appearance(overlay)) - else - overlay.icon_state = "pai_off_overlay" - add_overlay(new /mutable_appearance(overlay)) + overlay.icon_state = "[current_overlays[PDA_OVERLAY_PAI]][pai.pai ? "" : "_off"]" + add_overlay(new /mutable_appearance(overlay)) /obj/item/pda/MouseDrop(mob/over, src_location, over_location) var/mob/M = usr @@ -740,8 +790,7 @@ GLOBAL_LIST_EMPTY(PDAs) to_chat(L, "[icon2html(src)] Message from [hrefstart][signal.data["name"]] ([signal.data["job"]])[hrefend], [signal.format_message()] (Reply)") - update_icon() - add_overlay(icon_alert) + update_icon(TRUE) /obj/item/pda/proc/send_to_all(mob/living/U) if (last_everyone && world.time < last_everyone + PDA_SPAM_DELAY) @@ -1080,4 +1129,11 @@ GLOBAL_LIST_EMPTY(PDAs) #undef PDA_SCANNER_HALOGEN #undef PDA_SCANNER_GAS #undef PDA_SPAM_DELAY +#undef PDA_STANDARD_OVERLAYS +#undef PDA_OVERLAY_ALERT +#undef PDA_OVERLAY_SCREEN +#undef PDA_OVERLAY_ID +#undef PDA_OVERLAY_ITEM +#undef PDA_OVERLAY_LIGHT +#undef PDA_OVERLAY_PAI \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/PDA_types.dm b/code/game/objects/items/devices/PDA/PDA_types.dm index 80d8cb5963..54b82d8e07 100644 --- a/code/game/objects/items/devices/PDA/PDA_types.dm +++ b/code/game/objects/items/devices/PDA/PDA_types.dm @@ -124,6 +124,16 @@ icon_state = "pda-captain" detonatable = FALSE +/obj/item/pda/lieutenant + name = "lieutenant PDA" + default_cartridge = /obj/item/cartridge/captain + inserted_item = /obj/item/pen/fountain/captain + icon_state = "pda-lieutenant" + ttone = "bwoink" + detonatable = FALSE + hidden = TRUE + note = "Congratulations, you have chosen the Thinktronic 5230-2 Personal Data Assistant Prestige Edition! To help with navigation, we have provided the following definitions. North: Fore. South: Aft. West: Port. East: Starboard. Quarter is either side of aft." + /obj/item/pda/cargo name = "cargo technician PDA" default_cartridge = /obj/item/cartridge/quartermaster @@ -171,25 +181,29 @@ /obj/item/pda/curator name = "curator PDA" icon_state = "pda-library" - icon_alert = "pda-r-library" + overlays_icons = list('icons/obj/pda.dmi' = list("pda-r-library","blank","id_overlay","insert_overlay", "light_overlay", "pai_overlay"), + 'icons/obj/pda_alt.dmi' = list("pda-r","screen_default","id_overlay","insert_overlay", "light_overlay", "pai_overlay")) + current_overlays = list("pda-r-library","blank","id_overlay","insert_overlay", "light_overlay", "pai_overlay") default_cartridge = /obj/item/cartridge/curator inserted_item = /obj/item/pen/fountain desc = "A portable microcomputer by Thinktronic Systems, LTD. This model is a WGW-11 series e-reader." - note = "Congratulations, your station has chosen the Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant!" + note = "Congratulations, your station has chosen the Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant! To help with navigation, we have provided the following definitions. North: Fore. South: Aft. West: Port. East: Starboard. Quarter is either side of aft." silent = TRUE //Quiet in the library! + overlays_offsets = list('icons/obj/pda.dmi' = list(-3,0)) overlays_x_offset = -3 /obj/item/pda/clear name = "clear PDA" icon_state = "pda-clear" desc = "A portable microcomputer by Thinktronic Systems, LTD. This model is a special edition with a transparent case." - note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition!" + note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition! To help with navigation, we have provided the following definitions. North: Fore. South: Aft. West: Port. East: Starboard. Quarter is either side of aft." /obj/item/pda/neko name = "neko PDA" icon_state = "pda-neko" - desc = "A portable microcomputer by Thinktronic Systems, LTD. This model is a special edition a feline fine case." - note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Mew Turbo Limited Edition NYA~!" + overlays_icons = list('icons/obj/pda_alt.dmi' = list("pda-r", "screen_neko", "id_overlay", "insert_overlay", "light_overlay", "pai_overlay")) + desc = "A portable microcomputer by Thinktronic Systems, LTD. This model is a special feline edition." + note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Mew Turbo Limited Edition NYA~! To help with navigation, we have provided the following definitions. North: Fore. South: Aft. West: Port. East: Starboard. Quarter is either side of aft." /obj/item/pda/cook name = "cook PDA" diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index d1061a28a4..06aef0a22b 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -58,7 +58,7 @@ item_state = "radio" /obj/item/holybeacon/attack_self(mob/user) - if(user.mind && (user.mind.isholy) && !SSreligion.holy_armor_type) + if(user.mind && (user.mind.isholy) && !GLOB.holy_armor_type) beacon_armor(user) else playsound(src, 'sound/machines/buzz-sigh.ogg', 40, 1) @@ -71,13 +71,13 @@ display_names += list(initial(A.name) = A) var/choice = input(M,"What holy armor kit would you like to order?","Holy Armor Theme") as null|anything in display_names - if(QDELETED(src) || !choice || M.stat || !in_range(M, src) || M.restrained() || !M.canmove || SSreligion.holy_armor_type) + if(QDELETED(src) || !choice || M.stat || !in_range(M, src) || M.restrained() || !M.canmove || GLOB.holy_armor_type) return var/index = display_names.Find(choice) var/A = holy_armor_list[index] - SSreligion.holy_armor_type = A + GLOB.holy_armor_type = A var/holy_armor_box = new A SSblackbox.record_feedback("tally", "chaplain_armor", 1, "[choice]") @@ -245,7 +245,7 @@ reskin_holy_weapon(user) /obj/item/nullrod/proc/reskin_holy_weapon(mob/M) - if(SSreligion.holy_weapon_type) + if(GLOB.holy_weapon_type) return var/obj/item/nullrod/holy_weapon var/list/holy_weapons_list = typesof(/obj/item/nullrod) + list( @@ -264,7 +264,7 @@ var/A = display_names[choice] // This needs to be on a separate var as list member access is not allowed for new holy_weapon = new A - SSreligion.holy_weapon_type = holy_weapon.type + GLOB.holy_weapon_type = holy_weapon.type SSblackbox.record_feedback("tally", "chaplain_weapon", 1, "[choice]") diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 34ae4cb5ef..4217a58f81 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -396,7 +396,7 @@ //TODO bloody overlay /obj/item/stack/microwave_act(obj/machinery/microwave/M) - if(M && M.dirty < 100) + if(istype(M) && M.dirty < 100) M.dirty += amount /* diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index beb62d0ed1..e2d7fdf9d7 100755 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -576,6 +576,8 @@ /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver, /obj/item/ammo_box, + /obj/item/toy/gun, + /obj/item/gun/energy/e_gun/mini )) /obj/item/storage/belt/holster/full/PopulateContents() diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm index c2d5ca50be..830c3aea96 100644 --- a/code/game/objects/items/storage/book.dm +++ b/code/game/objects/items/storage/book.dm @@ -51,7 +51,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", if(!istype(H)) return // If H is the Chaplain, we can set the icon_state of the bible (but only once!) - if(!SSreligion.bible_icon_state && H.job == "Chaplain") + if(!GLOB.bible_icon_state && H.job == "Chaplain") var/dat = "Pick Bible Style

Pick a bible style

" for(var/i in 1 to GLOB.biblestates.len) var/icon/bibleicon = icon('icons/obj/storage.dmi', GLOB.biblestates[i]) @@ -64,7 +64,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", /obj/item/storage/book/bible/Topic(href, href_list) if(!usr.canUseTopic(src)) return - if(href_list["seticon"] && SSreligion && !SSreligion.bible_icon_state) + if(href_list["seticon"] && GLOB && !GLOB.bible_icon_state) var/iconi = text2num(href_list["seticon"]) var/biblename = GLOB.biblenames[iconi] var/obj/item/storage/book/bible/B = locate(href_list["src"]) @@ -76,8 +76,8 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", H.dna.add_mutation(CLOWNMUT) H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), SLOT_WEAR_MASK) - SSreligion.bible_icon_state = B.icon_state - SSreligion.bible_item_state = B.item_state + GLOB.bible_icon_state = B.icon_state + GLOB.bible_item_state = B.item_state SSblackbox.record_feedback("text", "religion_book", 1, "[biblename]") usr << browse(null, "window=editicon") @@ -89,7 +89,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", to_chat(user, "[src.deity_name] refuses to heal this metallic taint!") return 0 - var/heal_amt = 10 + var/heal_amt = 5 var/list/hurt_limbs = H.get_damaged_bodyparts(1, 1) if(hurt_limbs.len) @@ -138,8 +138,8 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", smack = 0 else if(iscarbon(M)) var/mob/living/carbon/C = M - if(!istype(C.head, /obj/item/clothing/head/helmet)) - C.adjustBrainLoss(5, 60) + if(!istype(C.head, /obj/item/clothing/head)) + C.adjustBrainLoss(10, 80) to_chat(C, "You feel dumber.") if(smack) diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm index 43611ee4e1..4ff63ceeac 100644 --- a/code/game/objects/items/storage/boxes.dm +++ b/code/game/objects/items/storage/boxes.dm @@ -1126,3 +1126,73 @@ /obj/item/storage/box/pink icon_state = "box_pink" illustration = null + +/obj/item/storage/box/mre //base MRE type. + name = "Nanotrasen MRE Ration Kit Menu 0" + desc = "A package containing food suspended in an outdated bluespace pocket which lasts for centuries. If you're lucky you may even be able to enjoy the meal without getting food poisoning." + icon_state = "mre" + var/can_expire = TRUE + var/spawner_chance = 2 + var/expiration_date + var/expiration_date_min = 2300 + var/expiration_date_max = 2700 + +/obj/item/storage/box/mre/Initialize() + . = ..() + if(can_expire) + expiration_date = rand(expiration_date_min, expiration_date_max) + desc += "\nAn expiry date is listed on it. It reads: [expiration_date]" + var/spess_current_year = GLOB.year_integer + 540 + if(expiration_date < spess_current_year) + var/gross_risk = min(round(spess_current_year - expiration_date * 0.1), 1) + var/toxic_risk = min(round(spess_current_year - expiration_date * 0.01), 1) + for(var/obj/item/reagent_containers/food/snacks/S in contents) + if(prob(gross_risk)) + ENABLE_BITFIELD(S.foodtype, GROSS) + if(prob(toxic_risk)) + ENABLE_BITFIELD(S.foodtype, TOXIC) + +/obj/item/storage/box/mre/menu1 + name = "\improper Nanotrasen MRE Ration Kit Menu 1" + +/obj/item/storage/box/mre/menu1/safe + desc = "A package containing food suspended in a bluespace pocket capable of lasting till the end of time." + spawner_chance = 0 + can_expire = FALSE + +/obj/item/storage/box/mre/menu1/PopulateContents() + new /obj/item/reagent_containers/food/snacks/breadslice/plain(src) + new /obj/item/reagent_containers/food/snacks/breadslice/creamcheese(src) + new /obj/item/reagent_containers/food/condiment/pack/ketchup(src) + new /obj/item/reagent_containers/food/snacks/chocolatebar(src) + new /obj/item/tank/internals/emergency_oxygen(src) + +/obj/item/storage/box/mre/menu2 + name = "\improper Nanotrasen MRE Ration Kit Menu 2" + +/obj/item/storage/box/mre/menu2/safe + spawner_chance = 0 + desc = "A package containing food suspended in a bluespace pocket capable of lasting till the end of time." + can_expire = FALSE + +/obj/item/storage/box/mre/menu2/PopulateContents() + new /obj/item/reagent_containers/food/snacks/omelette(src) + new /obj/item/reagent_containers/food/snacks/meat/cutlet/plain(src) + new /obj/item/reagent_containers/food/snacks/fries(src) + new /obj/item/reagent_containers/food/snacks/chocolatebar(src) + new /obj/item/tank/internals/emergency_oxygen(src) + +/obj/item/storage/box/mre/menu3 + name = "\improper Nanotrasen MRE Ration Kit Menu 3" + desc = "The holy grail of MREs. This item contains the fabled MRE pizza and a sample of coffee instant type 2. Any NT employee lucky enough to get their hands on one of these is truly blessed." + icon_state = "menu3" + can_expire = FALSE //always fresh, never expired. + spawner_chance = 1 + +/obj/item/storage/box/mre/menu3/PopulateContents() + new /obj/item/reagent_containers/food/snacks/pizzaslice/pepperoni(src) + new /obj/item/reagent_containers/food/snacks/breadslice/plain(src) + new /obj/item/reagent_containers/food/snacks/cheesewedge(src) + new /obj/item/reagent_containers/food/snacks/grown/chili(src) + new /obj/item/reagent_containers/food/drinks/coffee/type2(src) + new /obj/item/tank/internals/emergency_oxygen(src) diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index cf220cb415..e21ce71843 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -183,9 +183,9 @@ slab_type = /obj/item/clockwork/slab/debug fabricator_type = /obj/item/clockwork/replica_fabricator/scarab/debug -/obj/item/storage/toolbox/durasteel - name = "durasteel toolbox" - desc = "A toolbox made out of durasteel. Probably packs a massive punch." +/obj/item/storage/toolbox/plastitanium + name = "plastitanium toolbox" + desc = "A toolbox made out of plastitanium. Probably packs a massive punch." total_mass = 5 icon_state = "blue" item_state = "toolbox_blue" diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index eabd9f1968..274afe15e0 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -636,10 +636,13 @@ var/obj/machinery/computer/holodeck/holo = null // Holodeck cards should not be infinite var/list/cards = list() -/obj/item/toy/cards/deck/New() - ..() +/obj/item/toy/cards/deck/Initialize() + . = ..() + populate_deck() + +/obj/item/toy/cards/deck/proc/populate_deck() icon_state = "deck_[deckstyle]_full" - for(var/i = 2; i <= 10; i++) + for(var/i in 2 to 10) cards += "[i] of Hearts" cards += "[i] of Spades" cards += "[i] of Clubs" @@ -664,6 +667,9 @@ //ATTACK HAND IGNORING PARENT RETURN VALUE //ATTACK HAND NOT CALLING PARENT /obj/item/toy/cards/deck/attack_hand(mob/user) + draw_card(user) + +/obj/item/toy/cards/deck/proc/draw_card(mob/user) if(user.lying) return var/choice = null @@ -778,7 +784,7 @@ /obj/item/toy/cards/cardhand/Topic(href, href_list) if(..()) return - if(usr.stat || !ishuman(usr) || !usr.canmove) + if(usr.stat || !ishuman(usr)) return var/mob/living/carbon/human/cardUser = usr var/O = src @@ -941,7 +947,6 @@ newobj.card_attack_verb = sourceobj.card_attack_verb newobj.attack_verb = newobj.card_attack_verb - /* || Syndicate playing cards, for pretending you're Gambit and playing poker for the nuke disk. || */ diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index c1d381b435..fd6a9f2141 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -18,8 +18,9 @@ var/acid_level = 0 //how much acid is on that obj var/persistence_replacement //have something WAY too amazing to live to the next round? Set a new path here. Overuse of this var will make me upset. - var/current_skin //Has the item been reskinned? + var/current_skin //the item reskin var/list/unique_reskin //List of options to reskin. + var/always_reskinnable = FALSE // Access levels, used in modules\jobs\access.dm var/list/req_access @@ -228,26 +229,26 @@ ..() if(obj_flags & UNIQUE_RENAME) to_chat(user, "Use a pen on it to rename it or change its description.") - if(unique_reskin && !current_skin) + if(unique_reskin && (!current_skin || always_reskinnable)) to_chat(user, "Alt-click it to reskin it.") /obj/AltClick(mob/user) . = ..() - if(unique_reskin && !current_skin && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY)) + if(unique_reskin && (!current_skin || always_reskinnable) && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY)) reskin_obj(user) /obj/proc/reskin_obj(mob/M) if(!LAZYLEN(unique_reskin)) return - to_chat(M, "Reskin options for [name]:") + var/dat = "Reskin options for [name]:\n" for(var/V in unique_reskin) var/output = icon2html(src, M, unique_reskin[V]) - to_chat(M, "[V]: [output]") + dat += "[V]: [output]\n" + to_chat(M, dat) - var/choice = input(M,"Warning, you can only reskin [src] once!","Reskin Object") as null|anything in unique_reskin - if(!QDELETED(src) && choice && !current_skin && !M.incapacitated() && in_range(M,src)) - if(!unique_reskin[choice]) - return - current_skin = choice - icon_state = unique_reskin[choice] - to_chat(M, "[src] is now skinned as '[choice].'") + var/choice = input(M, always_reskinnable ? "Choose the a reskin for [src]" : "Warning, you can only reskin [src] once!","Reskin Object") as null|anything in unique_reskin + if(QDELETED(src) || !choice || (current_skin && !always_reskinnable) || M.incapacitated() || !in_range(M,src) || !unique_reskin[choice] || unique_reskin[choice] == current_skin) + return + current_skin = choice + icon_state = unique_reskin[choice] + to_chat(M, "[src] is now skinned as '[choice]'.") diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index 968c2d1e2f..d5acb66fdd 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -25,8 +25,8 @@ cross.icon_state = "kingyellow" font_color = "blue" prayer_type = "CHAPLAIN PRAYER" - if(SSreligion.deity) - deity = SSreligion.deity + if(GLOB.deity) + deity = GLOB.deity else if(iscultist(usr)) cross.icon_state = "tome" font_color = "red" diff --git a/code/modules/antagonists/changeling/powers/adrenaline.dm b/code/modules/antagonists/changeling/powers/adrenaline.dm index d1088f0025..256d3e89e3 100644 --- a/code/modules/antagonists/changeling/powers/adrenaline.dm +++ b/code/modules/antagonists/changeling/powers/adrenaline.dm @@ -1,8 +1,9 @@ /obj/effect/proc_holder/changeling/adrenaline name = "Adrenaline Sacs" desc = "We evolve additional sacs of adrenaline throughout our body." - helptext = "Removes all stuns instantly and adds a short-term reduction in further stuns. Can be used while unconscious. Continued use poisons the body." + helptext = "Removes all stuns instantly and adds a short-term reduction in further stuns. Can be used while unconscious. Continued use poisons the body. This ability is loud, and might cause our blood to react violently to heat." chemical_cost = 30 + loudness = 2 dna_cost = 2 req_human = 1 req_stat = UNCONSCIOUS @@ -13,4 +14,4 @@ //Recover from stuns. /obj/effect/proc_holder/changeling/adrenaline/sting_action(mob/living/user) user.do_adrenaline(0, FALSE, 70, 0, TRUE, list("epinephrine" = 3, "changelingmeth" = 10, "mannitol" = 10, "regen_jelly" = 10, "changelingadrenaline" = 5), "Energy rushes through us.", 0, 0.75, 0) - return TRUE + return TRUE \ No newline at end of file diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index 7274f73965..8d2e6fcedf 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -68,6 +68,7 @@ GLOB.poi_list |= src LAZYADD(GLOB.mob_spawners[job_description ? job_description : name], src) + /obj/effect/mob_spawn/Destroy() GLOB.poi_list -= src LAZYREMOVE(GLOB.mob_spawners[job_description ? job_description : name], src) @@ -75,6 +76,9 @@ GLOB.mob_spawners -= job_description ? job_description : name return ..() +/obj/effect/mob_spawn/proc/can_latejoin() //If it can be taken from the lobby. + return TRUE + /obj/effect/mob_spawn/proc/special(mob/M) return diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm index 330a31d5bf..bde3021c76 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -1960,6 +1960,17 @@ crate_name = "hydroponics backpack crate" crate_type = /obj/structure/closet/crate/secure +/datum/supply_pack/organic/mre + name = "MRE supply kit (emergency rations)" + desc = "The lights are out. Oxygen's running low. You've run out of food except space weevils. Don't let this be you! Order our NT branded MRE kits today! This pack contains 5 MRE packs with a randomized menu and an oxygen tank." + cost = 2000 + contains = list(/obj/item/storage/box/mre/menu1/safe, + /obj/item/storage/box/mre/menu1/safe, + /obj/item/storage/box/mre/menu2/safe, + /obj/item/storage/box/mre/menu2/safe, + /obj/item/storage/box/mre/menu3) + crate_name = "MRE crate (emergency rations)" + /datum/supply_pack/organic/pizza name = "Pizza Crate" desc = "Best prices on this side of the galaxy. All deliveries are guaranteed to be 99% anomaly-free!" @@ -2252,7 +2263,8 @@ /obj/item/storage/fancy/cigarettes/cigpack_shadyjims, /obj/item/clothing/mask/gas/syndicate, /obj/item/clothing/neck/necklace/dope, - /obj/item/vending_refill/donksoft) + /obj/item/vending_refill/donksoft, + /obj/item/circuitboard/computer/arcade/amputation) crate_name = "crate" /datum/supply_pack/costumes_toys/foamforce diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm index 7c08a3332c..10e98e92b8 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/client/asset_cache.dm @@ -467,6 +467,24 @@ GLOBAL_LIST_EMPTY(asset_datums) "stamp-law" = 'icons/stamp_icons/large_stamp-law.png' ) +/datum/asset/spritesheet/simple/minesweeper + name = "minesweeper" + assets = list( + "1" = 'icons/misc/minesweeper_tiles/one.png', + "2" = 'icons/misc/minesweeper_tiles/two.png', + "3" = 'icons/misc/minesweeper_tiles/three.png', + "4" = 'icons/misc/minesweeper_tiles/four.png', + "5" = 'icons/misc/minesweeper_tiles/five.png', + "6" = 'icons/misc/minesweeper_tiles/six.png', + "7" = 'icons/misc/minesweeper_tiles/seven.png', + "8" = 'icons/misc/minesweeper_tiles/eight.png', + "empty" = 'icons/misc/minesweeper_tiles/empty.png', + "flag" = 'icons/misc/minesweeper_tiles/flag.png', + "hidden" = 'icons/misc/minesweeper_tiles/hidden.png', + "mine" = 'icons/misc/minesweeper_tiles/mine.png', + "minehit" = 'icons/misc/minesweeper_tiles/minehit.png' + ) + /datum/asset/simple/IRV assets = list( "jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js', diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 501e9fc7cc..7a6fdad721 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -59,6 +59,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/preferred_map = null var/pda_style = MONO var/pda_color = "#808000" + var/pda_skin = PDA_SKIN_ALT var/uses_glasses_colour = 0 @@ -685,48 +686,48 @@ GLOBAL_LIST_EMPTY(preferences_datums) else if(pref_species.use_skintones) dat += "Genitals use skintone:[features["genitals_use_skintone"] == TRUE ? "Yes" : "No"]" - dat += "Has Penis:" + dat += "

Penis

" dat += "[features["has_cock"] == TRUE ? "Yes" : "No"]" - if(features["has_cock"] == TRUE) + if(features["has_cock"]) if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Penis Color:" - dat += "   (Skin tone overriding)
" + dat += "Penis Color:
" + dat += "   (Skin tone overriding)
" else - dat += "Penis Color:" + dat += "Penis Color:
" dat += "    Change
" dat += "Penis Shape: [features["cock_shape"]]" dat += "Penis Length: [features["cock_length"]] inch(es)" dat += "Has Testicles:[features["has_balls"] == TRUE ? "Yes" : "No"]" - if(features["has_balls"] == TRUE) + if(features["has_balls"]) if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Testicles Color:" + dat += "Testicles Color:
" dat += "   (Skin tone overriding)
" else - dat += "Testicles Color:" + dat += "Testicles Color:
" dat += "    Change
" dat += "Testicles showing:[features["balls_shape"]]" dat += APPEARANCE_CATEGORY_COLUMN - dat += "Has Vagina:" + dat += "

Vagina

" dat += "[features["has_vag"] == TRUE ? "Yes" : "No"]" if(features["has_vag"]) dat += "Vagina Type: [features["vag_shape"]]" if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Vagina Color:" + dat += "Vagina Color:
" dat += "   (Skin tone overriding)
" else - dat += "Vagina Color:" + dat += "Vagina Color:
" dat += "    Change
" dat += "Has Womb:[features["has_womb"] == TRUE ? "Yes" : "No"]" dat += "" dat += APPEARANCE_CATEGORY_COLUMN - dat += "Has Breasts:" + dat += "

Breasts

" dat += "[features["has_breasts"] == TRUE ? "Yes" : "No"]" if(features["has_breasts"]) if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) - dat += "Color:" + dat += "Color:
" dat += "   (Skin tone overriding)
" else - dat += "Color:" + dat += "Color:
" dat += "    Change
" dat += "Cup Size:[features["breasts_size"]]" dat += "Breast Shape:[features["breasts_shape"]]" @@ -746,6 +747,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "
" dat += "PDA Color:     Change
" dat += "PDA Style: [pda_style]
" + dat += "PDA Reskin: [pda_skin]
" dat += "
" dat += "Ghost Ears: [(chat_toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]
" dat += "Ghost Radio: [(chat_toggles & CHAT_GHOSTRADIO) ? "All Messages":"No Messages"]
" @@ -1986,6 +1988,10 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/pickedPDAColor = input(user, "Choose your PDA Interface color.", "Character Preference",pda_color) as color|null if(pickedPDAColor) pda_color = pickedPDAColor + if("pda_skin") + var/pickedPDASkin = input(user, "Choose your PDA reskin.", "Character Preference", pda_skin) as null|anything in GLOB.pda_reskins + if(pickedPDASkin) + pda_skin = pickedPDASkin else switch(href_list["preference"]) @@ -1996,6 +2002,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) arousable = !arousable if("has_cock") features["has_cock"] = !features["has_cock"] + if(features["has_cock"] == FALSE) + features["has_balls"] = FALSE if("has_balls") features["has_balls"] = !features["has_balls"] if("has_ovi") @@ -2010,6 +2018,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) features["has_breasts"] = !features["has_breasts"] if("has_vag") features["has_vag"] = !features["has_vag"] + if(features["has_vag"] == FALSE) + features["has_womb"] = FALSE if("has_womb") features["has_womb"] = !features["has_womb"] if("exhibitionist") diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 7401a54efc..3c5d547b46 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -108,6 +108,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["tip_delay"] >> tip_delay S["pda_style"] >> pda_style S["pda_color"] >> pda_color + S["pda_skin"] >> pda_skin //citadel code S["arousable"] >> arousable @@ -144,6 +145,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car be_special = SANITIZE_LIST(be_special) pda_style = sanitize_inlist(pda_style, GLOB.pda_styles, initial(pda_style)) pda_color = sanitize_hexcolor(pda_color, 6, 1, initial(pda_color)) + pda_skin = sanitize_inlist(pda_skin, GLOB.pda_reskins, PDA_SKIN_ALT) screenshake = sanitize_integer(screenshake, 0, 800, initial(screenshake)) damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake)) diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm index e4cc477f11..7e7da2839e 100644 --- a/code/modules/clothing/chameleon.dm +++ b/code/modules/clothing/chameleon.dm @@ -226,6 +226,19 @@ CL.flags_cover = initial(PCL.flags_cover) target.icon = initial(picked_item.icon) +/datum/action/item_action/chameleon/change/pda/update_item(obj/item/pda/picked_item) + if(!istype(target, /obj/item/pda)) + return ..() + var/obj/item/pda/P = target + P.name = initial(picked_item.name) + P.desc = initial(picked_item.desc) + P.icon_state = initial(picked_item.icon_state) + P.item_state = initial(picked_item.item_state) + P.item_color = initial(picked_item.item_color) + P.overlays_offsets = initial(picked_item.overlays_offsets) + P.set_new_overlays() + P.update_icon() + /datum/action/item_action/chameleon/change/Trigger() if(!IsAvailable()) return @@ -584,7 +597,7 @@ /obj/item/pda/chameleon name = "PDA" - var/datum/action/item_action/chameleon/change/chameleon_action + var/datum/action/item_action/chameleon/change/pda/chameleon_action /obj/item/pda/chameleon/Initialize() . = ..() diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 67d0252bb2..6e25db1fa6 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -98,7 +98,7 @@ desc = "A pair of snazzy goggles used to protect against chemical spills. Fitted with an analyzer for scanning items and reagents." icon_state = "purple" item_state = "glasses" - scan_reagents = 1 //You can see reagents while wearing science goggles + scan_reagents = TRUE //You can see reagents while wearing science goggles actions_types = list(/datum/action/item_action/toggle_research_scanner) glass_colour_type = /datum/client_colour/glass_colour/purple resistance_flags = ACID_PROOF @@ -202,7 +202,7 @@ /obj/item/clothing/glasses/sunglasses/reagent name = "beer goggles" desc = "A pair of sunglasses outfitted with apparatus to scan reagents." - scan_reagents = 1 + scan_reagents = TRUE /obj/item/clothing/glasses/sunglasses/garb name = "black gar glasses" @@ -377,7 +377,7 @@ item_state = "godeye" vision_flags = SEE_TURFS|SEE_MOBS|SEE_OBJS darkness_view = 8 - scan_reagents = 1 + scan_reagents = TRUE item_flags = NODROP lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE resistance_flags = LAVA_PROOF | FIRE_PROOF diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index d40b5f4e9b..22eac9f5aa 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -445,7 +445,7 @@ flash_protect = 0 armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 75) flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR - scan_reagents = 1 + scan_reagents = TRUE /obj/item/clothing/suit/space/hardsuit/medical icon_state = "hardsuit-medical" @@ -467,7 +467,7 @@ max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 100, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 80) var/obj/machinery/doppler_array/integrated/bomb_radar - scan_reagents = 1 + scan_reagents = TRUE actions_types = list(/datum/action/item_action/toggle_helmet_light, /datum/action/item_action/toggle_research_scanner) /obj/item/clothing/head/helmet/space/hardsuit/rd/Initialize() @@ -626,7 +626,7 @@ item_state = "anc_hardsuit" armor = list("melee" = 10, "bullet" = 5, "laser" = 5, "energy" = 500, "bomb" = 500, "bio" = 500, "rad" = 500, "fire" = 500, "acid" = 500) slowdown = 6 //Slow - allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage, /obj/item/construction/rcd, /obj/item/pipe_dispenser) + allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage, /obj/item/construction/rcd, /obj/item/pipe_dispenser) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ancient/mason max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF @@ -639,7 +639,7 @@ armor = list("melee" = 10, "bullet" = 5, "laser" = 5, "energy" = 500, "bomb" = 500, "bio" = 500, "rad" = 500, "fire" = 500, "acid" = 500) item_color = "ancient" brightness_on = 16 - scan_reagents = 1 + scan_reagents = TRUE flash_protect = 5 //We will not be flash by bombs tint = 1 var/obj/machinery/doppler_array/integrated/bomb_radar diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 5d2d4c115a..eb30488999 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -58,7 +58,8 @@ item_state = "hostrench" flags_inv = 0 strip_delay = 80 - + unique_reskin = list("Coat" = "hostrench", "Cloak" = "trenchcloak") + /obj/item/clothing/suit/armor/vest/warden name = "warden's jacket" desc = "A navy-blue armored jacket with blue shoulder designations and '/Warden/' stitched into one of the chest pockets." diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index 748cf8139d..7b1d8be85e 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -204,6 +204,14 @@ resistance_flags = FREEZE_PROOF isGlass = FALSE +//Used by MREs +/obj/item/reagent_containers/food/drinks/coffee/type2 + name = "\improper Coffee, instant (type 2)" + desc = "Coffee that's been blow dried into a granulated powder. This packet includes self heating water for your nutritional pleasure." + icon = 'icons/obj/food/containers.dmi' + icon_state = "condi_cornoil" + + /obj/item/reagent_containers/food/drinks/ice name = "ice cup" desc = "Careful, cold ice, do not chew." diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm index d3408ca5e5..7eea6fb9ca 100644 --- a/code/modules/food_and_drinks/food/snacks.dm +++ b/code/modules/food_and_drinks/food/snacks.dm @@ -291,19 +291,23 @@ All foods are distributed among various categories. Use common sense. S.reagents.add_reagent(r_id, amount) /obj/item/reagent_containers/food/snacks/microwave_act(obj/machinery/microwave/M) + var/turf/T = get_turf(src) + var/obj/item/result if(cooked_type) - var/obj/item/reagent_containers/food/snacks/S = new cooked_type(get_turf(src)) - if(M) - initialize_cooked_food(S, M.efficiency) + result = new cooked_type(T) + if(istype(M)) + initialize_cooked_food(result, M.efficiency) else - initialize_cooked_food(S, 1) - SSblackbox.record_feedback("tally", "food_made", 1, type) + initialize_cooked_food(result, 1) + SSblackbox.record_feedback("tally", "food_made", 1, result.type) else - new /obj/item/reagent_containers/food/snacks/badrecipe(src) - if(M && M.dirty < 100) + result = new /obj/item/reagent_containers/food/snacks/badrecipe(T) + if(istype(M) && M.dirty < 100) M.dirty++ qdel(src) + return result + /obj/item/reagent_containers/food/snacks/Destroy() if(contents) for(var/atom/movable/something in contents) diff --git a/code/modules/food_and_drinks/food/snacks_pizza.dm b/code/modules/food_and_drinks/food/snacks_pizza.dm index 403636db08..74fd7dda65 100644 --- a/code/modules/food_and_drinks/food/snacks_pizza.dm +++ b/code/modules/food_and_drinks/food/snacks_pizza.dm @@ -225,3 +225,12 @@ filling_color = "#FFFFFF" foodtype = GRAIN | VEGETABLES + +// Used by MREs +/obj/item/reagent_containers/food/snacks/pizzaslice/pepperoni + name = "\improper MRE pepperoni pizza slice" + desc = "A freeze dried, dehydrated slice of bread with tomato sauce, pepperoni and cheese." + icon_state = "meatpizzaslice" + filling_color = "#A52A2A" + tastes = list("cardboard" = 1, "tomato" = 1, "cheese" = 1, "pepperoni" = 2) + foodtype = GRAIN | VEGETABLES | DAIRY | MEAT \ No newline at end of file diff --git a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm index 10ecfd6e20..6fcc5c9cec 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm @@ -12,322 +12,343 @@ pass_flags = PASSTABLE light_color = LIGHT_COLOR_YELLOW light_power = 0.9 + var/wire_disabled = FALSE // is its internal wire cut? var/operating = FALSE // Is it on? - var/dirty = 0 // = {0..100} Does it need cleaning? - var/broken = 0 // ={0,1,2} How broken is it??? - var/max_n_of_items = 10 // whatever fat fuck made this a global var needs to look at themselves in the mirror sometime + var/dirty = 0 // 0 to 100 // Does it need cleaning? + var/dirty_anim_playing = FALSE + var/broken = 0 // 0, 1 or 2 // How broken is it??? + var/max_n_of_items = 10 var/efficiency = 0 var/datum/looping_sound/microwave/soundloop + var/list/ingredients = list() // may only contain /atom/movables -//Microwaving doesn't use recipes, instead it calls the microwave_act of the objects. For food, this creates something based on the food's cooked_type + var/static/radial_examine = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine") + var/static/radial_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject") + var/static/radial_use = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_use") -/******************* -* Initialising -********************/ + // we show the button even if the proc will not work + var/static/list/radial_options = list("eject" = radial_eject, "use" = radial_use) + var/static/list/ai_radial_options = list("eject" = radial_eject, "use" = radial_use, "examine" = radial_examine) /obj/machinery/microwave/Initialize() . = ..() + wires = new /datum/wires/microwave(src) create_reagents(100) soundloop = new(list(src), FALSE) +/obj/machinery/microwave/Destroy() + eject() + if(wires) + QDEL_NULL(wires) + . = ..() + /obj/machinery/microwave/RefreshParts() - var/E - var/max_items = 10 + efficiency = 0 for(var/obj/item/stock_parts/micro_laser/M in component_parts) - E += M.rating + efficiency += M.rating for(var/obj/item/stock_parts/matter_bin/M in component_parts) - max_items = 10 * M.rating - efficiency = E - max_n_of_items = max_items + max_n_of_items = 10 * M.rating + break /obj/machinery/microwave/examine(mob/user) - ..() + . = ..() if(!operating) to_chat(user, "Alt-click [src] to turn it on.") -/******************* -* Item Adding -********************/ + if(!in_range(user, src) && !issilicon(user) && !isobserver(user)) + to_chat(user, "You're too far away to examine [src]'s contents and display!") + return + if(operating) + to_chat(user, "\The [src] is operating.") + return + + if(length(ingredients)) + if(issilicon(user)) + to_chat(user, "\The [src] camera shows:") + else + to_chat(user, "\The [src] contains:") + var/list/items_counts = new + for(var/i in ingredients) + if(istype(i, /obj/item/stack)) + var/obj/item/stack/S = i + items_counts[S.name] += S.amount + else + var/atom/movable/AM = i + items_counts[AM.name]++ + for(var/O in items_counts) + to_chat(user, "- [items_counts[O]]x [O].") + else + to_chat(user, "\The [src] is empty.") + + if(!(stat & (NOPOWER|BROKEN))) + to_chat(user, "The status display reads:") + to_chat(user, "- Capacity: [max_n_of_items] items.") + to_chat(user, "- Cook time reduced by [(efficiency - 1) * 25]%.") + +/obj/machinery/microwave/update_icon() + if(broken) + icon_state = "mwb" + else if(dirty_anim_playing) + icon_state = "mwbloody1" + else if(dirty == 100) + icon_state = "mwbloody" + else if(operating) + icon_state = "mw1" + else if(panel_open) + icon_state = "mw-o" + else + icon_state = "mw" /obj/machinery/microwave/attackby(obj/item/O, mob/user, params) if(operating) return - if(!broken && dirty<100) - if(default_deconstruction_screwdriver(user, "mw-o", "mw", O)) - return - if(default_unfasten_wrench(user, O)) - return - if(default_deconstruction_crowbar(O)) return - if(src.broken > 0) - if(src.broken == 2 && istype(O, /obj/item/wirecutters)) // If it's broken and they're using a screwdriver - user.visible_message( \ - "[user] starts to fix part of the microwave.", \ - "You start to fix part of the microwave..." \ - ) - if (O.use_tool(src, user, 20)) - user.visible_message( \ - "[user] fixes part of the microwave.", \ - "You fix part of the microwave." \ - ) - src.broken = 1 // Fix it a bit - else if(src.broken == 1 && istype(O, /obj/item/weldingtool)) // If it's broken and they're doing the wrench - user.visible_message( \ - "[user] starts to fix part of the microwave.", \ - "You start to fix part of the microwave..." \ - ) - if (O.use_tool(src, user, 20)) - user.visible_message( \ - "[user] fixes the microwave.", \ - "You fix the microwave." \ - ) - src.icon_state = "mw" - src.broken = 0 // Fix it! - src.dirty = 0 // just to be sure - return 0 //to use some fuel + if(dirty < 100) + if(default_deconstruction_screwdriver(user, icon_state, icon_state, O) || default_unfasten_wrench(user, O)) + update_icon() + return + + if(panel_open && is_wire_tool(O)) + wires.interact(user) + return TRUE + + if(broken > 0) + if(broken == 2 && O.tool_behaviour == TOOL_WIRECUTTER) // If it's broken and they're using a screwdriver + user.visible_message("[user] starts to fix part of \the [src].", "You start to fix part of \the [src]...") + if(O.use_tool(src, user, 20)) + user.visible_message("[user] fixes part of \the [src].", "You fix part of \the [src].") + broken = 1 // Fix it a bit + else if(broken == 1 && O.tool_behaviour == TOOL_WELDER) // If it's broken and they're doing the wrench + user.visible_message("[user] starts to fix part of \the [src].", "You start to fix part of \the [src]...") + if(O.use_tool(src, user, 20)) + user.visible_message("[user] fixes \the [src].", "You fix \the [src].") + broken = 0 + update_icon() + return FALSE //to use some fuel else to_chat(user, "It's broken!") - return 1 - else if(istype(O, /obj/item/reagent_containers/spray/)) + return TRUE + return + + if(istype(O, /obj/item/reagent_containers/spray)) var/obj/item/reagent_containers/spray/clean_spray = O - if(clean_spray.reagents.has_reagent("cleaner",clean_spray.amount_per_transfer_from_this)) - clean_spray.reagents.remove_reagent("cleaner",clean_spray.amount_per_transfer_from_this,1) + if(clean_spray.reagents.has_reagent("cleaner", clean_spray.amount_per_transfer_from_this)) + clean_spray.reagents.remove_reagent("cleaner", clean_spray.amount_per_transfer_from_this,1) playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) - user.visible_message( \ - "[user] has cleaned the microwave.", \ - "You clean the microwave." \ - ) - src.dirty = 0 // It's clean! - src.broken = 0 // just to be sure - src.icon_state = "mw" - src.updateUsrDialog() - return 1 // Disables the after-attack so we don't spray the floor/user. + user.visible_message("[user] has cleaned \the [src].", "You clean \the [src].") + dirty = 0 + update_icon() else to_chat(user, "You need more space cleaner!") - return 1 + return TRUE - else if(istype(O, /obj/item/soap/)) // If they're trying to clean it then let them + if(istype(O, /obj/item/soap)) var/obj/item/soap/P = O - user.visible_message( \ - "[user] starts to clean the microwave.", \ - "You start to clean the microwave..." \ - ) - if (do_after(user, P.cleanspeed, target = src)) - user.visible_message( \ - "[user] has cleaned the microwave.", \ - "You clean the microwave." \ - ) - src.dirty = 0 // It's clean! - src.broken = 0 // just to be sure - src.icon_state = "mw" + user.visible_message("[user] starts to clean \the [src].", "You start to clean \the [src]...") + if(do_after(user, P.cleanspeed, target = src)) + user.visible_message("[user] has cleaned \the [src].", "You clean \the [src].") + dirty = 0 + update_icon() + return TRUE - else if(src.dirty==100) // The microwave is all dirty so can't be used! - to_chat(user, "It's dirty!") - return 1 + if(dirty == 100) // The microwave is all dirty so can't be used! + to_chat(user, "\The [src] is dirty!") + return TRUE - else if(istype(O, /obj/item/storage/bag/tray)) + if(istype(O, /obj/item/storage/bag/tray)) var/obj/item/storage/T = O var/loaded = 0 for(var/obj/item/reagent_containers/food/snacks/S in T.contents) - if (contents.len>=max_n_of_items) - to_chat(user, "[src] is full, you can't put anything in!") - return 1 + if(ingredients.len >= max_n_of_items) + to_chat(user, "\The [src] is full, you can't put anything in!") + return TRUE if(SEND_SIGNAL(T, COMSIG_TRY_STORAGE_TAKE, S, src)) loaded++ - + ingredients += S if(loaded) - to_chat(user, "You insert [loaded] items into [src].") + to_chat(user, "You insert [loaded] items into \the [src].") + return + if(O.w_class <= WEIGHT_CLASS_NORMAL && !istype(O, /obj/item/storage) && user.a_intent == INTENT_HELP) + if(ingredients.len >= max_n_of_items) + to_chat(user, "\The [src] is full, you can't put anything in!") + return TRUE + if(!user.transferItemToLoc(O, src)) + to_chat(user, "\The [O] is stuck to your hand!") + return FALSE - else if(O.w_class <= WEIGHT_CLASS_NORMAL && !istype(O, /obj/item/storage) && user.a_intent == INTENT_HELP) - if (contents.len>=max_n_of_items) - to_chat(user, "[src] is full, you can't put anything in!") - return 1 - else - if(!user.transferItemToLoc(O, src)) - to_chat(user, "\the [O] is stuck to your hand, you cannot put it in \the [src]!") - return 0 + ingredients += O + user.visible_message("[user] has added \a [O] to \the [src].", "You add [O] to \the [src].") + return - user.visible_message( \ - "[user] has added \the [O] to \the [src].", \ - "You add \the [O] to \the [src].") - - else - ..() - updateUsrDialog() + ..() /obj/machinery/microwave/AltClick(mob/user) - if(user.canUseTopic(src, BE_CLOSE) && !(operating || broken > 0 || panel_open || !anchored || dirty == 100)) + if(user.canUseTopic(src, !issilicon(usr))) cook() -/******************* -* Microwave Menu -********************/ - -/obj/machinery/microwave/ui_interact(mob/user) // The microwave Menu +/obj/machinery/microwave/ui_interact(mob/user) . = ..() - if(panel_open || !anchored) + + if(operating || panel_open || !anchored || !user.canUseTopic(src, !issilicon(user))) + return + if(isAI(user) && (stat & NOPOWER)) return - var/dat = "
" - if(broken > 0) - dat += "ERROR: 09734014-A2379-D18746 --Bad memory
Contact your operator or use command line to rebase memory ///git checkout {HEAD} -a commit pull --rebase push {*NEW HEAD*}
" //Thats how all the git fiddling looks to me - else if(operating) - dat += "Microwaving in progress!
Please wait...!" - else if(dirty==100) - dat += "ERROR: >> 0 --Response input zero
Contact your operator of the device manifactor support." - else - var/list/items_counts = new - for (var/obj/O in contents) - if(istype(O, /obj/item/stack/)) - var/obj/item/stack/S = O - items_counts[O.name] += S.amount - else - items_counts[O.name]++ - for (var/O in items_counts) - var/N = items_counts[O] - dat += "[capitalize(O)]: [N]
" - - if (items_counts.len==0) - dat += "The microwave is empty." + if(!length(ingredients)) + if(isAI(user)) + examine(user) else - dat = "

Ingredients:

[dat]" - dat += "Turn on" - dat += "Eject ingredients
" + to_chat(user, "\The [src] is empty.") + return - var/datum/browser/popup = new(user, "microwave", name, 300, 300) - popup.set_content(dat) - popup.open() + var/choice = show_radial_menu(user, src, isAI(user) ? ai_radial_options : radial_options, require_near = !issilicon(user)) -/*********************************** -* Microwave Menu Handling/Cooking -************************************/ + // post choice verification + if(operating || panel_open || !anchored || !user.canUseTopic(src, !issilicon(user))) + return + if(isAI(user) && (stat & NOPOWER)) + return + + usr.set_machine(src) + switch(choice) + if("eject") + eject() + if("use") + cook() + if("examine") + examine(user) + +/obj/machinery/microwave/proc/eject() + for(var/i in ingredients) + var/atom/movable/AM = i + AM.forceMove(drop_location()) + ingredients.Cut() /obj/machinery/microwave/proc/cook() if(stat & (NOPOWER|BROKEN)) return + if(operating || broken > 0 || panel_open || !anchored || dirty == 100) + return + + if(wire_disabled) + audible_message("[src] buzzes.") + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + return + + if(prob(max((5 / efficiency) - 5, dirty * 5))) //a clean unupgraded microwave has no risk of failure + muck() + return + for(var/obj/O in ingredients) + if(istype(O, /obj/item/reagent_containers/food) || istype(O, /obj/item/grown)) + continue + if(prob(min(dirty * 5, 100))) + start_can_fail() + return + break start() - if (prob(max(5/efficiency-5,dirty*5))) //a clean unupgraded microwave has no risk of failure - muck_start() - if (!microwaving(4)) - muck_finish() - return - muck_finish() - return +/obj/machinery/microwave/proc/turn_on() + visible_message("\The [src] turns on.", "You hear a microwave humming.") + operating = TRUE - else - if(has_extra_item() && prob(min(dirty*5,100)) && !microwaving(4)) - broke() - return + set_light(1.5) + soundloop.start() + update_icon() - if(!microwaving(10)) - abort() - return - stop() +/obj/machinery/microwave/proc/spark() + visible_message("Sparks fly around [src]!") + var/datum/effect_system/spark_spread/s = new + s.set_up(2, 1, src) + s.start() - var/metal = 0 - for(var/obj/item/O in contents) - O.microwave_act(src) - if(O.materials[MAT_METAL]) - metal += O.materials[MAT_METAL] - - if(metal) - visible_message("Sparks fly around [src]!") - if(prob(max(metal/2, 33))) - explosion(loc,0,1,2) - broke() - return - - dropContents() - return - -/obj/machinery/microwave/proc/microwaving(seconds as num) - for (var/i=1 to seconds) - if (stat & (NOPOWER|BROKEN)) - return 0 - use_power(500) - sleep(max(12-2*efficiency,2)) // standard microwave means sleep(10). The better the efficiency, the faster the cooking - return 1 - -/obj/machinery/microwave/proc/has_extra_item() - for (var/obj/O in contents) - if ( \ - !istype(O, /obj/item/reagent_containers/food) && \ - !istype(O, /obj/item/grown) \ - ) - return 1 - return 0 +#define MICROWAVE_NORMAL 0 +#define MICROWAVE_MUCK 1 +#define MICROWAVE_PRE 2 /obj/machinery/microwave/proc/start() - visible_message("The microwave turns on.", "You hear a microwave humming.") - soundloop.start() - operating = TRUE - icon_state = "mw1" - set_light(1.5) - updateUsrDialog() + turn_on() + loop(MICROWAVE_NORMAL, 10) -/obj/machinery/microwave/proc/abort() - operating = FALSE // Turn it off again aferwards - icon_state = "mw" - updateUsrDialog() - set_light(0) - soundloop.stop() +/obj/machinery/microwave/proc/start_can_fail() + turn_on() + loop(MICROWAVE_PRE, 4) -/obj/machinery/microwave/proc/stop() - abort() +/obj/machinery/microwave/proc/muck() + turn_on() + playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) + dirty_anim_playing = TRUE + update_icon() + loop(MICROWAVE_MUCK, 4) -/obj/machinery/microwave/proc/dispose() - for (var/obj/O in contents) - O.forceMove(drop_location()) - to_chat(usr, "You dispose of the microwave contents.") - updateUsrDialog() +/obj/machinery/microwave/proc/loop(type, time, wait = max(12 - 2 * efficiency, 2)) // standard wait is 10 + if(stat & (NOPOWER|BROKEN)) + if(MICROWAVE_PRE) + pre_fail() + return + if(!time) + switch(type) + if(MICROWAVE_NORMAL) + loop_finish() + if(MICROWAVE_MUCK) + muck_finish() + if(MICROWAVE_PRE) + pre_success() + return + time-- + use_power(500) + addtimer(CALLBACK(src, .proc/loop, type, time, wait), wait) -/obj/machinery/microwave/proc/muck_start() - playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) // Play a splat sound - icon_state = "mwbloody1" // Make it look dirty!! +/obj/machinery/microwave/proc/loop_finish() + operating = FALSE + + var/metal = 0 + for(var/obj/item/O in ingredients) + O.microwave_act(src) + if(O.materials[MAT_METAL]) + metal += O.materials[MAT_METAL] + + if(metal) + spark() + broken = 2 + if(prob(max(metal / 2, 33))) + explosion(loc, 0, 1, 2) + else + dropContents(ingredients) + ingredients.Cut() + + after_finish_loop() + +/obj/machinery/microwave/proc/pre_fail() + broken = 2 + operating = FALSE + spark() + after_finish_loop() + +/obj/machinery/microwave/proc/pre_success() + loop(MICROWAVE_NORMAL, 10) /obj/machinery/microwave/proc/muck_finish() - visible_message("The microwave gets covered in muck!") - dirty = 100 // Make it dirty so it can't be used util cleaned - icon_state = "mwbloody" // Make it look dirty too - operating = FALSE // Turn it off again aferwards - updateUsrDialog() + visible_message("\The [src] gets covered in muck!") + + dirty = 100 + dirty_anim_playing = FALSE + operating = FALSE + for(var/obj/item/reagent_containers/food/snacks/S in src) if(prob(50)) new /obj/item/reagent_containers/food/snacks/badrecipe(src) qdel(S) + + after_finish_loop() + +/obj/machinery/microwave/proc/after_finish_loop() set_light(0) soundloop.stop() + update_icon() -/obj/machinery/microwave/proc/broke() - var/datum/effect_system/spark_spread/s = new - s.set_up(2, 1, src) - s.start() - icon_state = "mwb" // Make it look all busted up and shit - visible_message("The microwave breaks!") //Let them know they're stupid - broken = 2 // Make it broken so it can't be used util fixed - flags_1 = null //So you can't add condiments - operating = FALSE // Turn it off again aferwards - updateUsrDialog() - set_light(0) - soundloop.stop() - -/obj/machinery/microwave/Topic(href, href_list) - if(..() || panel_open) - return - - usr.set_machine(src) - if(operating) - updateUsrDialog() - return - - switch(href_list["action"]) - if ("cook") - cook() - - if ("dispose") - dispose() - updateUsrDialog() +#undef MICROWAVE_NORMAL +#undef MICROWAVE_MUCK +#undef MICROWAVE_PRE \ No newline at end of file diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm index b06a160180..d608a73560 100644 --- a/code/modules/food_and_drinks/pizzabox.dm +++ b/code/modules/food_and_drinks/pizzabox.dm @@ -332,6 +332,12 @@ /obj/item/pizzabox/infinite/proc/attune_pizza(mob/living/carbon/human/noms) //tonight on "proc names I never thought I'd type" if(!pizza_preferences[noms.ckey]) pizza_preferences[noms.ckey] = pickweight(pizza_types) + if(noms.has_quirk(/datum/quirk/pineapple_liker)) + pizza_preferences[noms.ckey] = /obj/item/reagent_containers/food/snacks/pizza/pineapple + else if(noms.has_quirk(/datum/quirk/pineapple_hater)) + var/list/pineapple_pizza_liker = pizza_types.Copy() + pineapple_pizza_liker -= /obj/item/reagent_containers/food/snacks/pizza/pineapple + pizza_preferences[noms.ckey] = pickweight(pineapple_pizza_liker) if(noms.mind && noms.mind.assigned_role == "Botanist") pizza_preferences[noms.ckey] = /obj/item/reagent_containers/food/snacks/pizza/dank diff --git a/code/modules/games/cas.dm b/code/modules/games/cas.dm index 9197e3d044..8953753a89 100644 --- a/code/modules/games/cas.dm +++ b/code/modules/games/cas.dm @@ -31,18 +31,17 @@ decksize = 50 card_text_file = "strings/cas_black.txt" -/obj/item/toy/cards/deck/cas/Initialize() - . = ..() +/obj/item/toy/cards/deck/cas/populate_deck() var/static/list/cards_against_space = list("cas_white" = world.file2list("strings/cas_white.txt"),"cas_black" = world.file2list("strings/cas_black.txt")) allcards = cards_against_space[card_face] var/list/possiblecards = allcards.Copy() if(possiblecards.len < decksize) // sanity check decksize = (possiblecards.len - 1) var/list/randomcards = list() - while (randomcards.len < decksize) + for(var/x in 1 to decksize) randomcards += pick_n_take(possiblecards) - for(var/i=1 to randomcards.len) - var/cardtext = randomcards[i] + for(var/x in 1 to randomcards.len) + var/cardtext = randomcards[x] var/datum/playingcard/P P = new() P.name = "[cardtext]" @@ -50,7 +49,7 @@ cards += P if(!blanks) return - for(var/x=1 to blanks) + for(var/x in 1 to blanks) var/datum/playingcard/P P = new() P.name = "Blank Card" @@ -58,10 +57,7 @@ cards += P shuffle_inplace(cards) // distribute blank cards throughout deck -/obj/item/toy/cards/deck/cas/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/item/toy/cards/deck/cas/draw_card(mob/user) if(user.lying) return if(cards.len == 0) diff --git a/code/modules/jobs/job_types/civilian_chaplain.dm b/code/modules/jobs/job_types/civilian_chaplain.dm index e44347a208..776727a5f8 100644 --- a/code/modules/jobs/job_types/civilian_chaplain.dm +++ b/code/modules/jobs/job_types/civilian_chaplain.dm @@ -24,14 +24,14 @@ Chaplain var/obj/item/storage/book/bible/booze/B = new - if(SSreligion.religion) - B.deity_name = SSreligion.deity - B.name = SSreligion.bible_name - B.icon_state = SSreligion.bible_icon_state - B.item_state = SSreligion.bible_item_state - to_chat(H, "There is already an established religion onboard the station. You are an acolyte of [SSreligion.deity]. Defer to the Chaplain.") + if(GLOB.religion) + B.deity_name = GLOB.deity + B.name = GLOB.bible_name + B.icon_state = GLOB.bible_icon_state + B.item_state = GLOB.bible_item_state + to_chat(H, "There is already an established religion onboard the station. You are an acolyte of [GLOB.deity]. Defer to the Chaplain.") H.equip_to_slot_or_del(B, SLOT_IN_BACKPACK) - var/nrt = SSreligion.holy_weapon_type || /obj/item/nullrod + var/nrt = GLOB.holy_weapon_type || /obj/item/nullrod var/obj/item/nullrod/N = new nrt(H) H.put_in_hands(N) return @@ -74,9 +74,9 @@ Chaplain else B.name = "The Holy Book of [new_religion]" - SSreligion.religion = new_religion - SSreligion.bible_name = B.name - SSreligion.deity = B.deity_name + GLOB.religion = new_religion + GLOB.bible_name = B.name + GLOB.deity = B.deity_name H.equip_to_slot_or_del(B, SLOT_IN_BACKPACK) diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index 8ae63a8a76..699df5de12 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -485,11 +485,11 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums if(href_list["printbible"]) if(cooldown < world.time) var/obj/item/storage/book/bible/B = new /obj/item/storage/book/bible(src.loc) - if(SSreligion.bible_icon_state && SSreligion.bible_item_state) - B.icon_state = SSreligion.bible_icon_state - B.item_state = SSreligion.bible_item_state - B.name = SSreligion.bible_name - B.deity_name = SSreligion.deity + if(GLOB.bible_icon_state && GLOB.bible_item_state) + B.icon_state = GLOB.bible_icon_state + B.item_state = GLOB.bible_item_state + B.name = GLOB.bible_name + B.deity_name = GLOB.deity cooldown = world.time + PRINTER_COOLDOWN else say("Printer currently unavailable, please wait a moment.") diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 84be6438c0..686a028b47 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -164,7 +164,7 @@ return var/obj/effect/mob_spawn/MS = pick(GLOB.mob_spawners[href_list["JoinAsGhostRole"]]) - if(istype(MS) && MS.attack_ghost(src, latejoinercalling = TRUE)) + if(MS?.attack_ghost(src, latejoinercalling = TRUE)) SSticker.queued_players -= src SSticker.queue_delay = 4 qdel(src) @@ -443,9 +443,10 @@ for(var/datum/job/job in SSjob.occupations) if(job && IsJobUnavailable(job.title, TRUE) == JOB_AVAILABLE) available_job_count++ - for(var/spawner in GLOB.mob_spawners) - available_job_count++ - break + for(var/obj/effect/mob_spawn/spawner in GLOB.mob_spawners) + if(spawner.can_latejoin()) + available_job_count++ + break if(!available_job_count) dat += "
There are currently no open positions!
" @@ -464,8 +465,9 @@ "Science" = list(jobs = list(), titles = GLOB.science_positions, color = "#e6b3e6"), "Security" = list(jobs = list(), titles = GLOB.security_positions, color = "#ff9999"), ) - for(var/spawner in GLOB.mob_spawners) - categorizedJobs["Ghost Role"]["jobs"] += spawner + for(var/obj/effect/mob_spawn/spawner in GLOB.mob_spawners) + if(spawner.can_latejoin()) + categorizedJobs["Ghost Role"]["jobs"] += spawner for(var/datum/job/job in SSjob.occupations) if(job && IsJobUnavailable(job.title, TRUE) == JOB_AVAILABLE) diff --git a/code/modules/mob/dead/new_player/sprite_accessories/socks.dm b/code/modules/mob/dead/new_player/sprite_accessories/socks.dm index 01a83dcc9f..3384f3754b 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/socks.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/socks.dm @@ -67,6 +67,38 @@ name = "Short (White)" icon_state = "white_short" +/datum/sprite_accessory/socks/stockings_blue + name = "Stockings (Blue)" + icon_state = "stockings_blue" + +/datum/sprite_accessory/socks/stockings_cyan + name = "Stockings (Cyan)" + icon_state = "stockings_cyan" + +/datum/sprite_accessory/socks/stockings_dpink + name = "Stockings (Dark Pink)" + icon_state = "stockings_dpink" + +/datum/sprite_accessory/socks/stockings_green + name = "Stockings (Green)" + icon_state = "stockings_black" + +/datum/sprite_accessory/socks/stockings_orange + name = "Stockings (Orange)" + icon_state = "stockings_orange" + +/datum/sprite_accessory/socks/stockings_programmer + name = "Stockings (Programmer)" + icon_state = "stockings_lpink" + +/datum/sprite_accessory/socks/stockings_purple + name = "Stockings (Purple)" + icon_state = "stockings_purple" + +/datum/sprite_accessory/socks/stockings_yellow + name = "Stockings (Yellow)" + icon_state = "stockings_yellow" + /datum/sprite_accessory/socks/bee_thigh name = "Thigh-high (Bee)" icon_state = "bee_thigh" diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 4fb3fb0243..3324b07217 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -44,6 +44,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/siemens_coeff = 1 //base electrocution coefficient var/damage_overlay_type = "human" //what kind of damage overlays (if any) appear on our species when wounded? var/fixed_mut_color = "" //to use MUTCOLOR with a fixed color that's independent of dna.feature["mcolor"] + var/list/special_step_sounds //Sounds to override barefeet walkng + var/grab_sound //Special sound for grabbing // species-only traits. Can be found in DNA.dm var/list/species_traits = list() diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index ff90929c4b..2907caff13 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -30,6 +30,7 @@ var/list/special_names = list("Tarkus") var/human_surname_chance = 3 var/special_name_chance = 5 + var/owner //dobby is a free golem /datum/species/golem/random_name(gender,unique,lastname) var/golem_surname = pick(GLOB.golem_names) @@ -807,3 +808,196 @@ /datum/species/golem/plastic/on_species_loss(mob/living/carbon/C) . = ..() C.ventcrawler = initial(C.ventcrawler) + +/datum/species/golem/bronze + name = "Bronze Golem" + id = "bronze golem" + prefix = "Bronze" + special_names = list("Bell") + fixed_mut_color = "cd7f32" + info_text = "As a Bronze Golem, you are very resistant to loud noises, and make loud noises if something hard hits you, however this ability does hurt your hearing." + special_step_sounds = list('sound/machines/clockcult/integration_cog_install.ogg', 'sound/magic/clockwork/fellowship_armory.ogg' ) + attack_verb = "bonk" + mutantears = /obj/item/organ/ears/bronze + var/last_gong_time = 0 + var/gong_cooldown = 150 + +/datum/species/golem/bronze/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) + if(!(world.time > last_gong_time + gong_cooldown)) + return ..() + if(P.flag == "bullet" || P.flag == "bomb") + gong(H) + return ..() + +/datum/species/golem/bronze/spec_hitby(atom/movable/AM, mob/living/carbon/human/H) + ..() + if(world.time > last_gong_time + gong_cooldown) + gong(H) + +/datum/species/golem/bronze/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) + ..() + if(world.time > last_gong_time + gong_cooldown && M.a_intent != INTENT_HELP) + gong(H) + +/datum/species/golem/bronze/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H) + ..() + if(world.time > last_gong_time + gong_cooldown) + gong(H) + +/datum/species/golem/bronze/on_hit(obj/item/projectile/P, mob/living/carbon/human/H) + ..() + if(world.time > last_gong_time + gong_cooldown) + gong(H) + +/datum/species/golem/bronze/proc/gong(mob/living/carbon/human/H) + last_gong_time = world.time + for(var/mob/living/M in get_hearers_in_view(7,H)) + if(M.stat == DEAD) //F + return + if(M == H) + H.show_message("You cringe with pain as your body rings around you!", 2) + H.playsound_local(H, 'sound/effects/gong.ogg', 100, TRUE) + H.soundbang_act(2, 0, 100, 1) + H.jitteriness += 7 + var/distance = max(0,get_dist(get_turf(H),get_turf(M))) + switch(distance) + if(0 to 1) + M.show_message("GONG!", 2) + M.playsound_local(H, 'sound/effects/gong.ogg', 100, TRUE) + M.soundbang_act(1, 0, 30, 3) + M.confused += 10 + M.jitteriness += 4 + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "gonged", /datum/mood_event/loud_gong) + if(2 to 3) + M.show_message("GONG!", 2) + M.playsound_local(H, 'sound/effects/gong.ogg', 75, TRUE) + M.soundbang_act(1, 0, 15, 2) + M.jitteriness += 3 + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "gonged", /datum/mood_event/loud_gong) + else + M.show_message("GONG!", 2) + M.playsound_local(H, 'sound/effects/gong.ogg', 50, TRUE) + + +/datum/species/golem/cardboard //Faster but weaker, can also make new shells on its own + name = "Cardboard Golem" + id = "cardboard golem" + prefix = "Cardboard" + special_names = list("Box") + info_text = "As a Cardboard Golem, you aren't very strong, but you are a bit quicker and can easily create more brethren by using cardboard on yourself." + species_traits = list(NOBLOOD,NO_UNDERWEAR,NOGENITALS,NOAROUSAL,MUTCOLORS) + inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER) + fixed_mut_color = "ffffff" + limbs_id = "c_golem" //special sprites + attack_verb = "bash" + armor = 25 + burnmod = 1.25 + heatmod = 2 + speedmod = 1.5 + punchdamagelow = 4 + punchstunthreshold = 7 + punchdamagehigh = 8 + var/last_creation = 0 + var/brother_creation_cooldown = 300 + +/datum/species/golem/cardboard/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H) + . = ..() + if(user != H) + return FALSE //forced reproduction is rape. + if(istype(I, /obj/item/stack/sheet/cardboard)) + var/obj/item/stack/sheet/cardboard/C = I + if(last_creation + brother_creation_cooldown > world.time) //no cheesing dork + return + if(C.amount < 10) + to_chat(H, "You do not have enough cardboard!") + return FALSE + to_chat(H, "You attempt to create a new cardboard brother.") + if(do_after(user, 30, target = user)) + if(last_creation + brother_creation_cooldown > world.time) //no cheesing dork + return + if(!C.use(10)) + to_chat(H, "You do not have enough cardboard!") + return FALSE + to_chat(H, "You create a new cardboard golem shell.") + create_brother(H.loc) + +/datum/species/golem/cardboard/proc/create_brother(var/location) + new /obj/effect/mob_spawn/human/golem/servant(location, /datum/species/golem/cardboard, owner) + last_creation = world.time + +/datum/species/golem/leather + name = "Leather Golem" + id = "leather golem" + special_names = list("Face", "Man", "Belt") //Ah dude 4 strength 4 stam leather belt AHHH + inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER, TRAIT_STRONG_GRABBER) + prefix = "Leather" + fixed_mut_color = "624a2e" + info_text = "As a Leather Golem, you are flammable, but you can grab things with incredible ease, allowing all your grabs to start at a strong level." + attack_verb = "whipp" + grab_sound = 'sound/weapons/whipgrab.ogg' + attack_sound = 'sound/weapons/whip.ogg' + +/datum/species/golem/bone + name = "Bone Golem" + id = "bone golem" + say_mod = "rattles" + prefix = "Bone" + limbs_id = "b_golem" + special_names = list("Head", "Broth", "Fracture", "Rattler", "Appetit") + liked_food = GROSS | MEAT | RAW + toxic_food = null + inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID) + mutanttongue = /obj/item/organ/tongue/bone + sexes = FALSE + fixed_mut_color = "ffffff" + attack_verb = "rattl" + species_traits = list(NOBLOOD,NO_UNDERWEAR,NOGENITALS,NOAROUSAL,MUTCOLORS) + inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_FAKEDEATH,TRAIT_CALCIUM_HEALER) + info_text = "As a Bone Golem, You have a powerful spell that lets you chill your enemies with fear, and milk heals you! Just make sure to watch our for bone-hurting juice." + var/datum/action/innate/bonechill/bonechill + +/datum/species/golem/bone/on_species_gain(mob/living/carbon/C, datum/species/old_species) + ..() + if(ishuman(C)) + bonechill = new + bonechill.Grant(C) + +/datum/species/golem/bone/on_species_loss(mob/living/carbon/C) + if(bonechill) + bonechill.Remove(C) + ..() + +/datum/action/innate/bonechill + name = "Bone Chill" + desc = "Rattle your bones and strike fear into your enemies!" + check_flags = AB_CHECK_CONSCIOUS + icon_icon = 'icons/mob/actions/actions_spells.dmi' + button_icon_state = "bonechill" + var/cooldown = 600 + var/last_use + var/snas_chance = 3 + +/datum/action/innate/bonechill/Activate() + if(world.time < last_use + cooldown) + to_chat("You aren't ready yet to rattle your bones again") + return + owner.visible_message("[owner] rattles [owner.p_their()] bones harrowingly.", "You rattle your bones") + last_use = world.time + if(prob(snas_chance)) + playsound(get_turf(owner),'sound/magic/RATTLEMEBONES2.ogg', 100) + if(ishuman(owner)) + var/mob/living/carbon/human/H = owner + var/mutable_appearance/badtime = mutable_appearance('icons/mob/human_parts.dmi', "b_golem_eyes", -FIRE_LAYER-0.5) + badtime.appearance_flags = RESET_COLOR + H.overlays_standing[FIRE_LAYER+0.5] = badtime + H.apply_overlay(FIRE_LAYER+0.5) + addtimer(CALLBACK(H, /mob/living/carbon/.proc/remove_overlay, FIRE_LAYER+0.5), 25) + else + playsound(get_turf(owner),'sound/magic/RATTLEMEBONES.ogg', 100) + for(var/mob/living/L in orange(7, get_turf(owner))) + if((MOB_UNDEAD in L.mob_biotypes) || isgolem(L) || HAS_TRAIT(L, TRAIT_RESISTCOLD)) + return //Do not affect our brothers + + to_chat(L, "A spine-chilling sound chills you to the bone!") + L.apply_status_effect(/datum/status_effect/bonechill) + SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "spooked", /datum/mood_event/spooked) diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index afd6e4e7f5..d7bb151ddc 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -5,7 +5,7 @@ sexes = 0 meat = /obj/item/stack/sheet/mineral/plasma species_traits = list(NOBLOOD,NOTRANSSTING,NOGENITALS) - inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_NOHUNGER) + inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_NOHUNGER,TRAIT_CALCIUM_HEALER) inherent_biotypes = list(MOB_INORGANIC, MOB_HUMANOID) mutantlungs = /obj/item/organ/lungs/plasmaman mutanttongue = /obj/item/organ/tongue/bone/plasmaman diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm index 5c2b01a179..135992f3a6 100644 --- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm +++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm @@ -7,7 +7,7 @@ sexes = 0 meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL) - inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH) + inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER) inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID) mutanttongue = /obj/item/organ/tongue/bone damage_overlay_type = ""//let's not show bloody wounds or burns over bones. @@ -21,4 +21,4 @@ /datum/species/skeleton/pirate name = "Space Queen's Skeleton" - inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH) + inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER) diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm index 4c1c235fe1..85436178fe 100644 --- a/code/modules/mob/living/carbon/monkey/combat.dm +++ b/code/modules/mob/living/carbon/monkey/combat.dm @@ -73,39 +73,21 @@ if(I.loc == src) return TRUE - if(I.anchored) + if(I.anchored || !put_in_hands(I)) blacklistItems[I] ++ return FALSE - // WEAPONS - if(istype(I, /obj/item)) - var/obj/item/W = I - if(W.force >= best_force) - put_in_hands(W) - best_force = W.force - return TRUE - - // CLOTHING - else if(istype(I, /obj/item/clothing)) - var/obj/item/clothing/C = I - monkeyDrop(C) - addtimer(CALLBACK(src, .proc/pickup_and_wear, C), 5) - return TRUE - - // EVERYTHING ELSE + if(I.force >= best_force) + best_force = I.force else - if(!get_item_for_held_index(1) || !get_item_for_held_index(2)) - put_in_hands(I) - return TRUE + addtimer(CALLBACK(src, .proc/pickup_and_wear, I), 5) - blacklistItems[I] ++ - return FALSE + return TRUE -/mob/living/carbon/monkey/proc/pickup_and_wear(var/obj/item/clothing/C) - if(!equip_to_appropriate_slot(C)) - monkeyDrop(get_item_by_slot(C)) // remove the existing item if worn - sleep(5) - equip_to_appropriate_slot(C) +/mob/living/carbon/monkey/proc/pickup_and_wear(obj/item/I) + if(QDELETED(I) || I.loc != src) + return + equip_to_appropriate_slot(I) /mob/living/carbon/monkey/resist_restraints() var/obj/item/I = null @@ -311,7 +293,8 @@ if(I == pickupTarget) M.visible_message("[src] snatches [pickupTarget] from [M].", "[src] snatched [pickupTarget]!") if(M.temporarilyRemoveItemFromInventory(pickupTarget) && !QDELETED(pickupTarget)) - equip_item(pickupTarget) + if(!equip_item(pickupTarget)) + dropItemToGround(pickupTarget) else M.visible_message("[src] tried to snatch [pickupTarget] from [M], but failed!", "[src] tried to grab [pickupTarget]!") pickpocketing = FALSE diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index b253e27e8d..b844a294be 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -263,7 +263,7 @@ var/mob/M = AM log_combat(src, M, "grabbed", addition="passive grab") - if(!supress_message) + if(!supress_message && !(iscarbon(AM) && HAS_TRAIT(src, TRAIT_STRONG_GRABBER))) visible_message("[src] has grabbed [M][(zone_selected == "l_arm" || zone_selected == "r_arm")? " by their hands":" passively"]!") //Cit change - And they thought ERP was bad. if(!iscarbon(src)) M.LAssailant = null @@ -281,6 +281,11 @@ var/datum/disease/D = thing if(D.spread_flags & DISEASE_SPREAD_CONTACT_SKIN) ContactContractDisease(D) + + if(iscarbon(L)) + var/mob/living/carbon/C = L + if(HAS_TRAIT(src, TRAIT_STRONG_GRABBER)) + C.grippedby(src) //mob verbs are a lot faster than object verbs //for more info on why this is not atom/pull, see examinate() in mob.dm diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 6d225d3913..1b1eb1a805 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -288,8 +288,17 @@ /mob/living/silicon/ai/can_interact_with(atom/A) . = ..() + var/turf/ai = get_turf(src) + var/turf/target = get_turf(A) if (.) return + + if(!target) + return + + if ((ai.z != target.z) && !is_station_level(ai.z)) + return FALSE + if (istype(loc, /obj/item/aicard)) var/turf/T0 = get_turf(src) var/turf/T1 = get_turf(A) diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index 2a298d39b1..4b08ccf608 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -1,4 +1,4 @@ - + /obj/item/paperplane name = "paper plane" desc = "Paper, folded in the shape of a plane." @@ -122,7 +122,7 @@ to_chat(user, "Alt-click [src] to fold it into a paper plane.") /obj/item/paper/AltClick(mob/living/carbon/user, obj/item/I) - if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) + if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user), NO_TK)) return to_chat(user, "You fold [src] into the shape of a plane!") user.temporarilyRemoveItemFromInventory(src) diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 10c4dbaeca..fa9d60a219 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -51,7 +51,8 @@ //these become available once upgraded. var/list/upgrade_reagents = list( "oil", - "ammonia" + "ammonia", + "ash" ) var/list/upgrade_reagents2 = list( @@ -248,13 +249,8 @@ work_animation() . = TRUE if("eject") - if(beaker) - beaker.forceMove(drop_location()) - if(Adjacent(usr) && !issilicon(usr)) - usr.put_in_hands(beaker) - beaker = null - update_icon() - . = TRUE + replace_beaker(usr) + . = TRUE //no afterattack if("dispense_recipe") if(!is_operational() || QDELETED(cell)) return @@ -267,7 +263,7 @@ if(beaker && dispensable_reagents.Find(r_id)) // but since we verify we have the reagent, it'll be fine var/datum/reagents/R = beaker.reagents var/free = R.maximum_volume - R.total_volume - var/actual = min(round(chemicals_to_dispense[key], res), (cell.charge * powerefficiency)*10, free) + var/actual = min(max(chemicals_to_dispense[key], res), (cell.charge * powerefficiency)*10, free) if(actual) if(!cell.use(actual / powerefficiency)) say("Not enough energy to complete operation!") @@ -320,14 +316,12 @@ return if(istype(I, /obj/item/reagent_containers) && !(I.item_flags & ABSTRACT) && I.is_open_container()) var/obj/item/reagent_containers/B = I - . = 1 //no afterattack - if(beaker) - to_chat(user, "A container is already loaded into [src]!") - return + . = TRUE //no afterattack if(!user.transferItemToLoc(B, src)) return - beaker = B + replace_beaker(user, B) to_chat(user, "You add [B] to [src].") + updateUsrDialog() update_icon() else if(user.a_intent != INTENT_HARM && !istype(I, /obj/item/card/emag)) to_chat(user, "You can't load [I] into [src]!") @@ -379,7 +373,17 @@ dispensable_reagents |= upgrade_reagents3 powerefficiency = round(newpowereff, 0.01) - +/obj/machinery/chem_dispenser/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker) + if(beaker) + beaker.forceMove(drop_location()) + if(user && Adjacent(user) && !issiliconoradminghost(user)) + user.put_in_hands(beaker) + if(new_beaker) + beaker = new_beaker + else + beaker = null + update_icon() + return TRUE /obj/machinery/chem_dispenser/on_deconstruction() cell = null @@ -415,6 +419,12 @@ final_list += list(avoid_assoc_duplicate_keys(fuck[1],key_list) = text2num(fuck[2])) return final_list +/obj/machinery/chem_dispenser/AltClick(mob/living/user) + if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + replace_beaker(user) + return + /obj/machinery/chem_dispenser/drinks/Initialize() . = ..() AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE) @@ -478,9 +488,16 @@ "tomatojuice", "lemonjuice", "menthol" - ) //prevents the soda machine from obtaining chemical upgrades. . - upgrade_reagents = null - upgrade_reagents2 = null + ) + upgrade_reagents = list( + "mushroomhallucinogen", + "nothing", + "cryoxadone" + ) + upgrade_reagents2 = list( + "banana", + "berryjuice" + ) upgrade_reagents3 = null emagged_reagents = list( "thirteenloko", @@ -534,18 +551,19 @@ "triple_sec", "sake", "applejack" - )//prevents the booze machine from obtaining chemical upgrades. - upgrade_reagents = null + ) + upgrade_reagents = list( + "ethanol", + "fernet" + ) upgrade_reagents2 = null upgrade_reagents3 = null emagged_reagents = list( - "ethanol", "iron", "alexander", "clownstears", "minttoxin", "atomicbomb", - "fernet", "aphro", "aphro+" ) diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index e4c6966cff..a17b1e8190 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -28,13 +28,23 @@ else icon_state = "mixer0b" -/obj/machinery/chem_heater/proc/eject_beaker(mob/user) +/obj/machinery/chem_heater/AltClick(mob/living/user) + if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + replace_beaker(user) + return + +/obj/machinery/chem_heater/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker) if(beaker) beaker.forceMove(drop_location()) - if(Adjacent(user) && !issilicon(user)) + if(user && Adjacent(user) && !issiliconoradminghost(user)) user.put_in_hands(beaker) + if(new_beaker) + beaker = new_beaker + else beaker = null update_icon() + return TRUE /obj/machinery/chem_heater/RefreshParts() heater_coefficient = 0.1 @@ -58,21 +68,19 @@ return if(istype(I, /obj/item/reagent_containers) && !(I.item_flags & ABSTRACT) && I.is_open_container()) - . = 1 //no afterattack - if(beaker) - to_chat(user, "A container is already loaded into [src]!") + . = TRUE //no afterattack + var/obj/item/reagent_containers/B = I + if(!user.transferItemToLoc(B, src)) return - - if(!user.transferItemToLoc(I, src)) - return - beaker = I - to_chat(user, "You add [I] to [src].") + replace_beaker(user, B) + to_chat(user, "You add [B] to [src].") + updateUsrDialog() update_icon() return return ..() /obj/machinery/chem_heater/on_deconstruction() - eject_beaker() + replace_beaker() return ..() /obj/machinery/chem_heater/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ @@ -122,5 +130,5 @@ target_temperature = CLAMP(target, 0, 1000) if("eject") on = FALSE - eject_beaker(usr) + replace_beaker(usr) . = TRUE diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 6327c5ba3a..aeed5ffc37 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -60,16 +60,6 @@ else icon_state = "mixer0" -/obj/machinery/chem_master/proc/eject_beaker(mob/user) - if(beaker) - beaker.forceMove(drop_location()) - if(Adjacent(user) && !issilicon(user)) - user.put_in_hands(beaker) - else - adjust_item_drop_location(beaker) - beaker = null - update_icon() - /obj/machinery/chem_master/blob_act(obj/structure/blob/B) if (prob(50)) qdel(src) @@ -85,36 +75,49 @@ return if(istype(I, /obj/item/reagent_containers) && !(I.item_flags & ABSTRACT) && I.is_open_container()) - . = 1 // no afterattack + . = TRUE // no afterattack if(panel_open) to_chat(user, "You can't use the [src.name] while its panel is opened!") return - if(beaker) - to_chat(user, "A container is already loaded into [src]!") + var/obj/item/reagent_containers/B = I + if(!user.transferItemToLoc(B, src)) return - if(!user.transferItemToLoc(I, src)) - return - - beaker = I - to_chat(user, "You add [I] to [src].") - src.updateUsrDialog() + replace_beaker(user, B) + to_chat(user, "You add [B] to [src].") + updateUsrDialog() update_icon() - else if(!condi && istype(I, /obj/item/storage/pill_bottle)) if(bottle) to_chat(user, "A pill bottle is already loaded into [src]!") return if(!user.transferItemToLoc(I, src)) return - bottle = I to_chat(user, "You add [I] into the dispenser slot.") - src.updateUsrDialog() + updateUsrDialog() else return ..() +/obj/machinery/chem_master/AltClick(mob/living/user) + if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + replace_beaker(user) + return + +/obj/machinery/chem_master/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker) + if(beaker) + beaker.forceMove(drop_location()) + if(user && Adjacent(user) && !issiliconoradminghost(user)) + user.put_in_hands(beaker) + if(new_beaker) + beaker = new_beaker + else + beaker = null + update_icon() + return TRUE + /obj/machinery/chem_master/on_deconstruction() - eject_beaker() + replace_beaker(usr) if(bottle) bottle.forceMove(drop_location()) adjust_item_drop_location(bottle) @@ -164,7 +167,7 @@ return switch(action) if("eject") - eject_beaker(usr) + replace_beaker(usr) . = TRUE if("ejectp") diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm index 5c39cd9db2..1847f1f722 100644 --- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm +++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm @@ -19,6 +19,12 @@ var/speed = 1 var/list/holdingitems + var/static/radial_examine = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine") + var/static/radial_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject") + var/static/radial_grind = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_grind") + var/static/radial_juice = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_juice") + var/static/radial_mix = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_mix") + /obj/machinery/reagentgrinder/Initialize() . = ..() holdingitems = list() @@ -51,7 +57,6 @@ if(A == beaker) beaker = null update_icon() - updateUsrDialog() if(holdingitems[A]) holdingitems -= A @@ -67,6 +72,18 @@ else icon_state = "juicer0" +/obj/machinery/reagentgrinder/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker) + if(beaker) + beaker.forceMove(drop_location()) + if(user && Adjacent(user) && !issiliconoradminghost(user)) + user.put_in_hands(beaker) + if(new_beaker) + beaker = new_beaker + else + beaker = null + update_icon() + return TRUE + /obj/machinery/reagentgrinder/attackby(obj/item/I, mob/user, params) //You can only screw open empty grinder if(!beaker && !length(holdingitems) && default_deconstruction_screwdriver(user, icon_state, icon_state, I)) @@ -82,17 +99,14 @@ return TRUE if (istype(I, /obj/item/reagent_containers) && !(I.item_flags & ABSTRACT) && I.is_open_container()) - if (!beaker) - if(!user.transferItemToLoc(I, src)) - to_chat(user, "[I] is stuck to your hand!") - return TRUE - to_chat(user, "You slide [I] into [src].") - beaker = I - update_icon() - updateUsrDialog() - else - to_chat(user, "There's already a container inside [src].") - return TRUE //no afterattack + var/obj/item/reagent_containers/B = I + . = TRUE + if(!user.transferItemToLoc(B, src)) + return + replace_beaker(user, B) + to_chat(user, "You add [B] to [src].") + update_icon() + return if(holdingitems.len >= limit) to_chat(user, "[src] is filled to capacity!") @@ -108,8 +122,6 @@ to_chat(user, "You empty [I] into [src].") else to_chat(user, "You fill [src] to the brim.") - - updateUsrDialog() return TRUE if(!I.grind_results && !I.juice_results) @@ -125,104 +137,89 @@ if(user.transferItemToLoc(I, src)) to_chat(user, "You add [I] to [src].") holdingitems[I] = TRUE - updateUsrDialog() return FALSE /obj/machinery/reagentgrinder/ui_interact(mob/user) // The microwave Menu //I am reasonably certain that this is not a microwave . = ..() - var/is_chamber_empty = FALSE - var/is_beaker_ready = FALSE - var/processing_chamber = "" - var/beaker_contents = "" - var/dat = "" - if(!operating) - for (var/i in holdingitems) - var/obj/item/O = i - processing_chamber += "\A [O.name]
" + if(operating || !user.canUseTopic(src, !issilicon(user))) + return - if (!processing_chamber) - is_chamber_empty = TRUE - processing_chamber = "Nothing." - if (!beaker) - beaker_contents = "No beaker attached.
" - else - is_beaker_ready = TRUE - beaker_contents = "The beaker contains:
" - var/anything = FALSE - for(var/datum/reagent/R in beaker.reagents.reagent_list) - anything = TRUE - beaker_contents += "[R.volume] - [R.name]
" - if(!anything) - beaker_contents += "Nothing
" + var/list/options = list() - dat = {" - Processing chamber contains:
- [processing_chamber]
- [beaker_contents]
- "} - if (is_beaker_ready) - if(!is_chamber_empty && !(stat & (NOPOWER|BROKEN))) - dat += "Grind the reagents
" - dat += "Juice the reagents

" - else if (beaker.reagents.total_volume) - dat += "Mix the reagents

" - if(length(holdingitems)) - dat += "Eject the reagents
" - if(beaker) - dat += "Detach the beaker
" + if(beaker || length(holdingitems)) + options["eject"] = radial_eject + + if(isAI(user)) + if(stat & NOPOWER) + return + options["examine"] = radial_examine + + // if there is no power or it's broken, the procs will fail but the buttons will still show + if(length(holdingitems)) + options["grind"] = radial_grind + options["juice"] = radial_juice + else if(beaker?.reagents.total_volume) + options["mix"] = radial_mix + + var/choice + + if(length(options) < 1) + return + if(length(options) == 1) + for(var/key in options) + choice = key else - dat += "Please wait..." + choice = show_radial_menu(user, src, options, require_near = !issilicon(user)) - var/datum/browser/popup = new(user, "reagentgrinder", "All-In-One Grinder") - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - popup.open(1) - return + // post choice verification + if(operating || (isAI(user) && stat & NOPOWER) || !user.canUseTopic(src, !issilicon(user))) + return -/obj/machinery/reagentgrinder/Topic(href, href_list) - if(..()) - return - var/mob/user = usr - if(!user.canUseTopic(src)) - return - if(stat & (NOPOWER|BROKEN)) - return - user.set_machine(src) - if(operating) - updateUsrDialog() - return - switch(href_list["action"]) - if ("grind") + switch(choice) + if("eject") + eject(user) + if("grind") grind(user) if("juice") juice(user) if("mix") mix(user) - if("eject") - eject(user) - if("detach") - detach(user) - updateUsrDialog() + if("examine") + examine(user) -/obj/machinery/reagentgrinder/proc/detach(mob/user) - if(!beaker) +/obj/machinery/reagentgrinder/examine(mob/user) + . = ..() + if(!in_range(user, src) && !issilicon(user) && !isobserver(user)) + to_chat(user, "You're too far away to examine [src]'s contents and display!") return - beaker.forceMove(drop_location()) - if(Adjacent(user) && !issilicon(user)) - user.put_in_hands(beaker) - beaker = null - update_icon() - updateUsrDialog() + + if(operating) + to_chat(user, "\The [src] is operating.") + return + + if(beaker || length(holdingitems)) + to_chat(user, "\The [src] contains:") + if(beaker) + to_chat(user, "- \A [beaker].") + for(var/i in holdingitems) + var/obj/item/O = i + to_chat(user, "- \A [O.name].") + + if(!(stat & (NOPOWER|BROKEN))) + to_chat(user, "The status display reads:") + to_chat(user, "- Grinding reagents at [speed*100]%.") + if(beaker) + for(var/datum/reagent/R in beaker.reagents.reagent_list) + to_chat(user, "- [R.volume] units of [R.name].") /obj/machinery/reagentgrinder/proc/eject(mob/user) - if(!length(holdingitems)) - return for(var/i in holdingitems) var/obj/item/O = i O.forceMove(drop_location()) holdingitems -= O - updateUsrDialog() + if(beaker) + replace_beaker(user) /obj/machinery/reagentgrinder/proc/remove_object(obj/item/O) holdingitems -= O @@ -240,7 +237,6 @@ /obj/machinery/reagentgrinder/proc/operate_for(time, silent = FALSE, juicing = FALSE) shake_for(time / speed) - updateUsrDialog() operating = TRUE if(!silent) if(!juicing) @@ -251,11 +247,10 @@ /obj/machinery/reagentgrinder/proc/stop_operating() operating = FALSE - updateUsrDialog() /obj/machinery/reagentgrinder/proc/juice() power_change() - if(!beaker || (beaker && (beaker.reagents.total_volume >= beaker.reagents.maximum_volume))) + if(!beaker || stat & (NOPOWER|BROKEN) || beaker.reagents.total_volume >= beaker.reagents.maximum_volume) return operate_for(50, juicing = TRUE) for(var/obj/item/i in holdingitems) @@ -274,7 +269,7 @@ /obj/machinery/reagentgrinder/proc/grind() power_change() - if(!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)) + if(!beaker || stat & (NOPOWER|BROKEN) || beaker.reagents.total_volume >= beaker.reagents.maximum_volume) return operate_for(60) for(var/i in holdingitems) @@ -296,13 +291,13 @@ /obj/machinery/reagentgrinder/proc/mix(mob/user) //For butter and other things that would change upon shaking or mixing power_change() - if(!beaker) + if(!beaker || stat & (NOPOWER|BROKEN)) return operate_for(50, juicing = TRUE) addtimer(CALLBACK(src, /obj/machinery/reagentgrinder/proc/mix_complete), 50) /obj/machinery/reagentgrinder/proc/mix_complete() - if(beaker && beaker.reagents.total_volume) + if(beaker?.reagents.total_volume) //Recipe to make Butter var/butter_amt = FLOOR(beaker.reagents.get_reagent_amount("milk") / MILK_TO_BUTTER_COEFF, 1) beaker.reagents.remove_reagent("milk", MILK_TO_BUTTER_COEFF * butter_amt) diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 193ce18b0c..4e40233713 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -213,15 +213,15 @@ glass_desc = "White and nutritious goodness!" /datum/reagent/consumable/milk/on_mob_life(mob/living/carbon/M) - if(M.getBruteLoss() && prob(20)) - M.heal_bodypart_damage(1,0, 0) + if(HAS_TRAIT(M, TRAIT_CALCIUM_HEALER)) + M.heal_bodypart_damage(1.5,0, 0) . = 1 + else + if(M.getBruteLoss() && prob(20)) + M.heal_bodypart_damage(1,0, 0) + . = 1 if(holder.has_reagent("capsaicin")) holder.remove_reagent("capsaicin", 2) - var/datum/dna/Mdna = M.has_dna() - if(Mdna && Mdna.species && (Mdna.species.id == "plasmaman" || Mdna.species.id == "skeleton")) - M.heal_bodypart_damage(1,0, 0) - . = 1 ..() /datum/reagent/consumable/soymilk diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index d9a4e3a843..6bd165f23e 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -887,3 +887,64 @@ /datum/reagent/toxin/mimesbane/on_mob_end_metabolize(mob/living/L) REMOVE_TRAIT(L, TRAIT_EMOTEMUTE, id) + +/datum/reagent/toxin/bonehurtingjuice //oof ouch + name = "Bone Hurting Juice" + id = "bonehurtingjuice" + description = "A strange substance that looks a lot like water. Drinking it is oddly tempting. Oof ouch." + color = "#AAAAAA77" //RGBA: 170, 170, 170, 77 + toxpwr = 0 + taste_description = "bone hurting" + overdose_threshold = 20 + +/datum/reagent/toxin/bonehurtingjuice/on_mob_add(mob/living/carbon/M) + M.say("oof ouch my bones", forced = /datum/reagent/toxin/bonehurtingjuice) + +/datum/reagent/toxin/bonehurtingjuice/on_mob_life(mob/living/carbon/M) + M.adjustStaminaLoss(7.5, 0) + if(HAS_TRAIT(M, TRAIT_CALCIUM_HEALER)) + M.adjustBruteLoss(3.5, 0) + if(prob(12)) + switch(rand(1, 3)) + if(1) + var/list/possible_says = list("oof.", "ouch!", "my bones.", "oof ouch.", "oof ouch my bones.") + M.say(pick(possible_says), forced = /datum/reagent/toxin/bonehurtingjuice) + if(2) + var/list/possible_mes = list("oofs softly.", "looks like their bones hurt.", "grimaces, as though their bones hurt.") + M.say("*custom " + pick(possible_mes), forced = /datum/reagent/toxin/bonehurtingjuice) + if(3) + to_chat(M, "Your bones hurt!") + return ..() + +/datum/reagent/toxin/bonehurtingjuice/overdose_process(mob/living/carbon/M) + if(prob(6) && iscarbon(M)) //big oof + var/selected_part + switch(rand(1, 4)) //God help you if the same limb gets picked twice quickly. + if(1) + selected_part = BODY_ZONE_L_ARM + if(2) + selected_part = BODY_ZONE_R_ARM + if(3) + selected_part = BODY_ZONE_L_LEG + if(4) + selected_part = BODY_ZONE_R_LEG + var/obj/item/bodypart/bp = M.get_bodypart(selected_part) + if(M.dna.species.type != /datum/species/skeleton || M.dna.species.type != /datum/species/plasmaman || M.dna.species.type != /datum/species/golem/bone) //We're so sorry skeletons, you're so misunderstood + if(bp) + bp.receive_damage(0, 0, 200) + playsound(M, get_sfx("desceration"), 50, TRUE, -1) + M.visible_message("[M]'s bones hurt too much!!", "Your bones hurt too much!!") + M.say("OOF!!", forced = /datum/reagent/toxin/bonehurtingjuice) + else //SUCH A LUST FOR REVENGE!!! + to_chat(M, "A phantom limb hurts!") + M.say("Why are we still here, just to suffer?", forced = /datum/reagent/toxin/bonehurtingjuice) + else //you just want to socialize + if(bp) + playsound(M, get_sfx("desceration"), 50, TRUE, -1) + M.visible_message("[M] rattles loudly and flails around!!", "Your bones hurt so much that your missing muscles spasm!!") + M.say("OOF!!", forced=/datum/reagent/toxin/bonehurtingjuice) + bp.receive_damage(200, 0, 0) //But I don't think we should + else + to_chat(M, "Your missing arm aches from wherever you left it.") + M.emote("sigh") + return ..() diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index 29863c2b90..b29a1c6809 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -64,8 +64,8 @@ strengthdiv = 8 for(var/mob/living/simple_animal/revenant/R in get_hearers_in_view(7,get_turf(holder.my_atom))) var/deity - if(SSreligion.deity) - deity = SSreligion.deity + if(GLOB.deity) + deity = GLOB.deity else deity = "Christ" to_chat(R, "The power of [deity] compels you!") diff --git a/code/modules/reagents/chemistry/recipes/toxins.dm b/code/modules/reagents/chemistry/recipes/toxins.dm index 22e21b1db0..726175a6c6 100644 --- a/code/modules/reagents/chemistry/recipes/toxins.dm +++ b/code/modules/reagents/chemistry/recipes/toxins.dm @@ -119,3 +119,10 @@ id = "mimesbane" results = list("mimesbane" = 3) required_reagents = list("radium" = 1, "mutetoxin" = 1, "nothing" = 1) + +/datum/chemical_reaction/bonehurtingjuice + name = "Bone Hurting Juice" + id = "bonehurtingjuice" + results = list("bonehurtingjuice" = 5) + required_reagents = list("mutagen" = 1, "itching_powder" = 3, "milk" = 1) + mix_message = "The mixture suddenly becomes clear and looks a lot like water. You feel a strong urge to drink it." diff --git a/code/modules/research/designs/comp_board_designs/comp_board_designs_all_misc.dm b/code/modules/research/designs/comp_board_designs/comp_board_designs_all_misc.dm index 780a1bc97d..65a435a309 100644 --- a/code/modules/research/designs/comp_board_designs/comp_board_designs_all_misc.dm +++ b/code/modules/research/designs/comp_board_designs/comp_board_designs_all_misc.dm @@ -21,6 +21,14 @@ category = list("Computer Boards") departmental_flags = DEPARTMENTAL_FLAG_ALL +/datum/design/board/minesweeper + name = "Computer Design (Minesweeper Arcade Machine)" + desc = "Allows for the construction of circuit boards used to build a new Minesweeper machine." + id = "arcade_minesweeper" + build_path = /obj/item/circuitboard/computer/arcade/minesweeper + category = list("Computer Boards") + departmental_flags = DEPARTMENTAL_FLAG_ALL + /datum/design/board/slot_machine name = "Computer Design (Slot Machine)" desc = "Allows for the construction of circuit boards used to build a new slot machine." diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm index 161ea3ac62..92a637ce43 100644 --- a/code/modules/ruins/lavaland_ruin_code.dm +++ b/code/modules/ruins/lavaland_ruin_code.dm @@ -81,7 +81,11 @@ /obj/item/stack/sheet/cloth = /datum/species/golem/cloth, /obj/item/stack/sheet/mineral/adamantine = /datum/species/golem/adamantine, /obj/item/stack/sheet/plastic = /datum/species/golem/plastic, - /obj/item/stack/tile/brass = /datum/species/golem/clockwork) + /obj/item/stack/tile/brass = /datum/species/golem/clockwork, + /obj/item/stack/tile/bronze = /datum/species/golem/bronze, + /obj/item/stack/sheet/cardboard = /datum/species/golem/cardboard, + /obj/item/stack/sheet/leather = /datum/species/golem/leather, + /obj/item/stack/sheet/bone = /datum/species/golem/bone) if(istype(I, /obj/item/stack)) var/obj/item/stack/O = I diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm index b0a2f38c46..8e191a41a9 100644 --- a/code/modules/surgery/organs/ears.dm +++ b/code/modules/surgery/organs/ears.dm @@ -94,3 +94,9 @@ H.dna.features["ears"] = "None" H.dna.species.mutant_bodyparts -= "ears" H.update_body() + +/obj/item/organ/ears/bronze + name = "tin ears" + desc = "The robust ears of a bronze golem. " + damage_multiplier = 0.1 //STRONK + bang_protect = 1 //Fear me weaklings. diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index 3018ebf03c..af1c954c5b 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -1785,10 +1785,10 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes desc = "Nothing is more terrifying than clowns with fully automatic weaponry." item = /obj/item/storage/backpack/duffelbag/clown/syndie -/datum/uplink_item/badass/durasteel_toolbox - name = "Durasteel Toolbox" +/datum/uplink_item/badass/plastitanium_toolbox + name = "Plastitanium Toolbox" desc = "A very high impact toolbox. Excels at destroying stationary structures." - item = /obj/item/storage/toolbox/durasteel + item = /obj/item/storage/toolbox/plastitanium cost = 2 //18 damage on mobs, 50 on objects, 4.5 stam/hit /datum/uplink_item/badass/balloon diff --git a/html/changelogs/AutoChangeLog-pr-8581.yml b/html/changelogs/AutoChangeLog-pr-8581.yml new file mode 100644 index 0000000000..90433ecb88 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8581.yml @@ -0,0 +1,6 @@ +author: "Ghommie" +delete-after: True +changes: + - rscadd: "Reskinnable PDAs. A related game preference." + - refactor: "Refactoring the pda, pda painter, obj reskinning and chameleon pda a bit to support this feature." + - imageadd: "more PDA sprites and ported reskins." diff --git a/html/changelogs/AutoChangeLog-pr-8681.yml b/html/changelogs/AutoChangeLog-pr-8681.yml new file mode 100644 index 0000000000..1cd5f04124 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8681.yml @@ -0,0 +1,6 @@ +author: "Ghommie (Original PRs by Tortellini Tony and BuffEngineering)" +delete-after: True +changes: + - bugfix: "E-cigs will continue to display their setting after being emagged." + - bugfix: "Vapes now come out of the mouth. +fix Fixes an E-cig initialize() runtime." diff --git a/html/changelogs/AutoChangeLog-pr-8708.yml b/html/changelogs/AutoChangeLog-pr-8708.yml new file mode 100644 index 0000000000..0929c2ee6c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8708.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - spellcheck: "Ironic" diff --git a/html/changelogs/AutoChangeLog-pr-8720.yml b/html/changelogs/AutoChangeLog-pr-8720.yml new file mode 100644 index 0000000000..81684baeac --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8720.yml @@ -0,0 +1,4 @@ +author: "Ghommie (Credits to Kmc2000 for the original PR)" +delete-after: True +changes: + - rscadd: "Porting in MRE boxes from Yogstation. But be careful, eating possibly expired MREs found in maintenance comes with an unrealistically large (actually small) chance of food poisoning. Otherwise just bail out and order actually safe-to-eat MREs from cargo for 2000 credits." diff --git a/html/changelogs/AutoChangeLog-pr-8726.yml b/html/changelogs/AutoChangeLog-pr-8726.yml new file mode 100644 index 0000000000..49da4299ce --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8726.yml @@ -0,0 +1,4 @@ +author: "Sishen1542" +delete-after: True +changes: + - balance: "Changed bible heal proc, halving the healed damage and increasing brain damage 5x in exchange for a much wider array of items to protect you from it." diff --git a/html/changelogs/AutoChangeLog-pr-8727.yml b/html/changelogs/AutoChangeLog-pr-8727.yml new file mode 100644 index 0000000000..b1ca5f0d51 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8727.yml @@ -0,0 +1,5 @@ +author: "Ghommie (original PRs by Jujumatic and PKPenguin321, respectively)" +delete-after: True +changes: + - rscadd: "Minesweeper Arcade machines. The higher the difficulty setting, the better the prizes will be." + - rscadd: "Also keep your eye out for another new (and rare) arcade game!" diff --git a/html/changelogs/AutoChangeLog-pr-8728.yml b/html/changelogs/AutoChangeLog-pr-8728.yml new file mode 100644 index 0000000000..2e860e737f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8728.yml @@ -0,0 +1,6 @@ +author: "Sishen1542" +delete-after: True +changes: + - tweak: "Moved around some chems from emag list into upgrades." + - balance: "Added some fun chems to dispensers." + - bugfix: "Gave dispensers old tg functionality." diff --git a/html/changelogs/AutoChangeLog-pr-8729.yml b/html/changelogs/AutoChangeLog-pr-8729.yml new file mode 100644 index 0000000000..a72f624352 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8729.yml @@ -0,0 +1,4 @@ +author: "Ghommie (original PR by AffectedArc07)" +delete-after: True +changes: + - tweak: "Religion is now a globalvar instead of being a subsystem for some reason" diff --git a/html/changelogs/AutoChangeLog-pr-8730.yml b/html/changelogs/AutoChangeLog-pr-8730.yml new file mode 100644 index 0000000000..d0204f2830 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8730.yml @@ -0,0 +1,6 @@ +author: "Ghommie (original PRs by Tlaltecuhtli and nicbn)" +delete-after: True +changes: + - rscadd: "alt click to eject beakers from chem masters + chem dispensers + grinders + chem heaters" + - rscadd: "hit chem master + chem dispenser + chem heaters with a beaker and if its loaded with another it swaps em" + - rscadd: "All-In-One Blender UI uses a radial menu now. You can see the contents and reagents by examining." diff --git a/html/changelogs/AutoChangeLog-pr-8731.yml b/html/changelogs/AutoChangeLog-pr-8731.yml new file mode 100644 index 0000000000..0728c12124 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8731.yml @@ -0,0 +1,9 @@ +author: "Ghommie (original PRs by nicbn and coiax)" +delete-after: True +changes: + - rscadd: "Microwave UI uses a radial menu now. You can see the contents by examining." + - rscadd: "Microwaves have a single wire accessible when open, the activation wire. +When cut, the microwave will no longer function, when pulsed, the microwave +will turn on." + - rscadd: "Stabilized dark purple extracts now cook items in your hands, rather than dropping +the cooked item on the floor." diff --git a/html/changelogs/AutoChangeLog-pr-8737.yml b/html/changelogs/AutoChangeLog-pr-8737.yml new file mode 100644 index 0000000000..d8e868df33 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8737.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixes CWC construct shells being visible as ghost role to latejoiners." diff --git a/html/changelogs/AutoChangeLog-pr-8738.yml b/html/changelogs/AutoChangeLog-pr-8738.yml new file mode 100644 index 0000000000..f0e48a77b5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8738.yml @@ -0,0 +1,4 @@ +author: "Ghommie (original PR by ShizCalev)" +delete-after: True +changes: + - bugfix: "Pineapple haters/lovers will get/no longer get pineapple pizzas respectively from infinite pizza boxes." diff --git a/html/changelogs/AutoChangeLog-pr-8739.yml b/html/changelogs/AutoChangeLog-pr-8739.yml new file mode 100644 index 0000000000..0c25a1a649 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8739.yml @@ -0,0 +1,5 @@ +author: "Sishen1542" +delete-after: True +changes: + - rscadd: "Leather, cardboard, bronze & bone golems!" + - rscadd: "Bone hurting juice and interactions with plasmamen, skeletons & bone golems!" diff --git a/html/changelogs/AutoChangeLog-pr-8741.yml b/html/changelogs/AutoChangeLog-pr-8741.yml new file mode 100644 index 0000000000..be803933ae --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8741.yml @@ -0,0 +1,4 @@ +author: "Ghommie (original PR by AffectedArc07 and Shazbot)" +delete-after: True +changes: + - imageadd: "Added 8 new sock styles" diff --git a/html/changelogs/AutoChangeLog-pr-8744.yml b/html/changelogs/AutoChangeLog-pr-8744.yml new file mode 100644 index 0000000000..2979a4a842 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8744.yml @@ -0,0 +1,4 @@ +author: "Linzolle" +delete-after: True +changes: + - bugfix: "atmos helmet visual bug" diff --git a/html/changelogs/AutoChangeLog-pr-8745.yml b/html/changelogs/AutoChangeLog-pr-8745.yml new file mode 100644 index 0000000000..6feaa2eadd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8745.yml @@ -0,0 +1,5 @@ +author: "Sishen1542" +delete-after: True +changes: + - rscadd: "Ported addition of new CAS cards." + - bugfix: "Ported a fix for CAS." diff --git a/html/changelogs/AutoChangeLog-pr-8753.yml b/html/changelogs/AutoChangeLog-pr-8753.yml new file mode 100644 index 0000000000..04fd009e2f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8753.yml @@ -0,0 +1,4 @@ +author: "Sishen1542" +delete-after: True +changes: + - balance: "Ported the inability for non-station AI to interact with station z-level." diff --git a/html/changelogs/AutoChangeLog-pr-8755.yml b/html/changelogs/AutoChangeLog-pr-8755.yml new file mode 100644 index 0000000000..a1c4742802 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8755.yml @@ -0,0 +1,6 @@ +author: "Poojawa" +delete-after: True +changes: + - tweak: "tweaked the Genital character creation layout to look better" + - bugfix: "fixed having balls/womb when you don't have the linked organ at character creation" + - bugfix: "fixed being able to squeeze semen directly from your balls. Probably." diff --git a/html/changelogs/AutoChangeLog-pr-8756.yml b/html/changelogs/AutoChangeLog-pr-8756.yml new file mode 100644 index 0000000000..8d78c6d5e8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8756.yml @@ -0,0 +1,4 @@ +author: "Sishen1542" +delete-after: True +changes: + - balance: "HoS mains can now peacefully sleep in their office." diff --git a/html/changelogs/AutoChangeLog-pr-8760.yml b/html/changelogs/AutoChangeLog-pr-8760.yml new file mode 100644 index 0000000000..78812c5c05 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8760.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - balance: "rebalanced lingy dingy powery gamey" diff --git a/html/changelogs/AutoChangeLog-pr-8762.yml b/html/changelogs/AutoChangeLog-pr-8762.yml new file mode 100644 index 0000000000..e248589b1b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8762.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - imageadd: "new sprites for the flechette gun, its magazines and the toy ray gun" diff --git a/html/changelogs/AutoChangeLog-pr-8764.yml b/html/changelogs/AutoChangeLog-pr-8764.yml new file mode 100644 index 0000000000..ad5b82505a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8764.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - tweak: "holster doing holster things" diff --git a/html/changelogs/AutoChangeLog-pr-8766.yml b/html/changelogs/AutoChangeLog-pr-8766.yml new file mode 100644 index 0000000000..33c2a47a71 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8766.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixes being able to teleport papers to your location with TK." diff --git a/html/changelogs/AutoChangeLog-pr-8767.yml b/html/changelogs/AutoChangeLog-pr-8767.yml new file mode 100644 index 0000000000..ce01bf471b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8767.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed some monkey-code shenanigeans making items sometimes disappear from pickpocketing." diff --git a/icons/misc/minesweeper_tiles/eight.png b/icons/misc/minesweeper_tiles/eight.png new file mode 100644 index 0000000000..3a5c4179ef Binary files /dev/null and b/icons/misc/minesweeper_tiles/eight.png differ diff --git a/icons/misc/minesweeper_tiles/empty.png b/icons/misc/minesweeper_tiles/empty.png new file mode 100644 index 0000000000..8a4fb536bb Binary files /dev/null and b/icons/misc/minesweeper_tiles/empty.png differ diff --git a/icons/misc/minesweeper_tiles/five.png b/icons/misc/minesweeper_tiles/five.png new file mode 100644 index 0000000000..dacf837f9b Binary files /dev/null and b/icons/misc/minesweeper_tiles/five.png differ diff --git a/icons/misc/minesweeper_tiles/flag.png b/icons/misc/minesweeper_tiles/flag.png new file mode 100644 index 0000000000..e71d8685ed Binary files /dev/null and b/icons/misc/minesweeper_tiles/flag.png differ diff --git a/icons/misc/minesweeper_tiles/four.png b/icons/misc/minesweeper_tiles/four.png new file mode 100644 index 0000000000..17a2bdfeb4 Binary files /dev/null and b/icons/misc/minesweeper_tiles/four.png differ diff --git a/icons/misc/minesweeper_tiles/hidden.png b/icons/misc/minesweeper_tiles/hidden.png new file mode 100644 index 0000000000..8d34a2a7f3 Binary files /dev/null and b/icons/misc/minesweeper_tiles/hidden.png differ diff --git a/icons/misc/minesweeper_tiles/mine.png b/icons/misc/minesweeper_tiles/mine.png new file mode 100644 index 0000000000..e16c89c2a8 Binary files /dev/null and b/icons/misc/minesweeper_tiles/mine.png differ diff --git a/icons/misc/minesweeper_tiles/minehit.png b/icons/misc/minesweeper_tiles/minehit.png new file mode 100644 index 0000000000..f0c9699d97 Binary files /dev/null and b/icons/misc/minesweeper_tiles/minehit.png differ diff --git a/icons/misc/minesweeper_tiles/one.png b/icons/misc/minesweeper_tiles/one.png new file mode 100644 index 0000000000..a84e6010a3 Binary files /dev/null and b/icons/misc/minesweeper_tiles/one.png differ diff --git a/icons/misc/minesweeper_tiles/seven.png b/icons/misc/minesweeper_tiles/seven.png new file mode 100644 index 0000000000..10d71c427e Binary files /dev/null and b/icons/misc/minesweeper_tiles/seven.png differ diff --git a/icons/misc/minesweeper_tiles/six.png b/icons/misc/minesweeper_tiles/six.png new file mode 100644 index 0000000000..fe2ba800f4 Binary files /dev/null and b/icons/misc/minesweeper_tiles/six.png differ diff --git a/icons/misc/minesweeper_tiles/three.png b/icons/misc/minesweeper_tiles/three.png new file mode 100644 index 0000000000..1c128d88ee Binary files /dev/null and b/icons/misc/minesweeper_tiles/three.png differ diff --git a/icons/misc/minesweeper_tiles/two.png b/icons/misc/minesweeper_tiles/two.png new file mode 100644 index 0000000000..ff74af5c82 Binary files /dev/null and b/icons/misc/minesweeper_tiles/two.png differ diff --git a/icons/mob/actions/actions_spells.dmi b/icons/mob/actions/actions_spells.dmi index dd8a6fb869..30927d3608 100644 Binary files a/icons/mob/actions/actions_spells.dmi and b/icons/mob/actions/actions_spells.dmi differ diff --git a/icons/mob/human_parts_greyscale.dmi b/icons/mob/human_parts_greyscale.dmi index f49a27fda4..3bb3874d35 100644 Binary files a/icons/mob/human_parts_greyscale.dmi and b/icons/mob/human_parts_greyscale.dmi differ diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi index fbfa039451..5f0b665ff4 100644 Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index b3b2f7703c..42c32f134a 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/mob/underwear.dmi b/icons/mob/underwear.dmi index 25e7d2c6d0..5e6725cec7 100644 Binary files a/icons/mob/underwear.dmi and b/icons/mob/underwear.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 2970de757b..568adb69b3 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/pda.dmi b/icons/obj/pda.dmi index 241bb46b98..1957fb1666 100644 Binary files a/icons/obj/pda.dmi and b/icons/obj/pda.dmi differ diff --git a/icons/obj/pda_alt.dmi b/icons/obj/pda_alt.dmi new file mode 100644 index 0000000000..4f03d2c574 Binary files /dev/null and b/icons/obj/pda_alt.dmi differ diff --git a/icons/obj/pda_modern.dmi b/icons/obj/pda_modern.dmi new file mode 100644 index 0000000000..26c3b9ce16 Binary files /dev/null and b/icons/obj/pda_modern.dmi differ diff --git a/icons/obj/pda_rugged.dmi b/icons/obj/pda_rugged.dmi new file mode 100644 index 0000000000..84c8ffd1f9 Binary files /dev/null and b/icons/obj/pda_rugged.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 9467e8f818..9037bfc0d0 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/modular_citadel/code/game/objects/items/devices/PDA/PDA.dm b/modular_citadel/code/game/objects/items/devices/PDA/PDA.dm deleted file mode 100644 index d26cf28778..0000000000 --- a/modular_citadel/code/game/objects/items/devices/PDA/PDA.dm +++ /dev/null @@ -1,4 +0,0 @@ -//Overrides TG's PDA sprites with Cit's PDA sprites. Remind me to turn this into a pref somewhere down the line. - -/obj/item/pda - icon = 'modular_citadel/icons/obj/pda.dmi' diff --git a/modular_citadel/code/game/objects/items/holy_weapons.dm b/modular_citadel/code/game/objects/items/holy_weapons.dm index 204a27f3fa..3ecc6cc31b 100644 --- a/modular_citadel/code/game/objects/items/holy_weapons.dm +++ b/modular_citadel/code/game/objects/items/holy_weapons.dm @@ -11,8 +11,8 @@ /obj/item/nullrod/rosary/Initialize() .=..() - if(SSreligion.religion) - deity_name = SSreligion.deity + if(GLOB.religion) + deity_name = GLOB.deity /obj/item/nullrod/rosary/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) if(!istype(M)) diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/modular_citadel/code/modules/arousal/organs/testicles.dm index 0b86d58208..1e6b4d62d4 100644 --- a/modular_citadel/code/modules/arousal/organs/testicles.dm +++ b/modular_citadel/code/modules/arousal/organs/testicles.dm @@ -11,7 +11,7 @@ var/sack_size = BALLS_SACK_SIZE_DEF fluid_id = "semen" producing = TRUE - can_masturbate_with = TRUE + can_masturbate_with = FALSE masturbation_verb = "massage" can_climax = TRUE var/sent_full_message = TRUE //defaults to 1 since they're full to start diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm index f3f21a2e9b..091611219c 100644 --- a/modular_citadel/code/modules/client/loadout/__donator.dm +++ b/modular_citadel/code/modules/client/loadout/__donator.dm @@ -408,5 +408,5 @@ datum/gear/darksabresheath /datum/gear/longblackgloves name = "Luna's Gauntlets" category = SLOT_GLOVES - path = /obj/item/clothing/suit/commjacket + path = /obj/item/clothing/gloves/longblackgloves ckeywhitelist = list("bigmanclancy") diff --git a/modular_citadel/code/modules/reagents/reagent container/hypovial.dm b/modular_citadel/code/modules/reagents/reagent container/hypovial.dm index a58a7fc825..4b7972d0a7 100755 --- a/modular_citadel/code/modules/reagents/reagent container/hypovial.dm +++ b/modular_citadel/code/modules/reagents/reagent container/hypovial.dm @@ -16,6 +16,7 @@ "purple hypovial" = "hypovial-p", "black hypovial" = "hypovial-t" ) + always_reskinnable = TRUE /obj/item/reagent_containers/glass/bottle/vial/Initialize() . = ..() @@ -29,17 +30,6 @@ /obj/item/reagent_containers/glass/bottle/vial/on_reagent_change() update_icon() -/obj/item/reagent_containers/glass/bottle/vial/reskin_obj(mob/M) //Makes the vials completely reskinnable, and renames them - overrides /obj/proc/reskin_obj - if(!LAZYLEN(unique_reskin)) - return - var/choice = input(M,"Do you wish to recolour your [src]?","Vial Recolour") as null|anything in unique_reskin - if(!QDELETED(src) && choice && !current_skin && !M.incapacitated() && in_range(M,src)) - if(!unique_reskin[choice]) - return - icon_state = unique_reskin[choice] - name = choice - to_chat(M, "[src] is now skinned as '[choice].'") - /obj/item/reagent_containers/glass/bottle/vial/update_icon() cut_overlays() if(reagents.total_volume) diff --git a/modular_citadel/code/modules/research/techweb/all_nodes.dm b/modular_citadel/code/modules/research/techweb/all_nodes.dm index e561b106d8..c0ddaceaf7 100644 --- a/modular_citadel/code/modules/research/techweb/all_nodes.dm +++ b/modular_citadel/code/modules/research/techweb/all_nodes.dm @@ -19,7 +19,7 @@ display_name = "Games and Toys" description = "For the slackers on the station." prereq_ids = list("comptech") - design_ids = list("arcade_battle", "arcade_orion", "slotmachine", "autoylathe") + design_ids = list("arcade_battle", "arcade_orion", "arcade_minesweeper", "slotmachine", "autoylathe") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) export_price = 5000 diff --git a/modular_citadel/icons/mob/muzzled_helmet.dmi b/modular_citadel/icons/mob/muzzled_helmet.dmi index a96f18c3ce..e321f8ae47 100644 Binary files a/modular_citadel/icons/mob/muzzled_helmet.dmi and b/modular_citadel/icons/mob/muzzled_helmet.dmi differ diff --git a/modular_citadel/icons/obj/guns/cit_guns.dmi b/modular_citadel/icons/obj/guns/cit_guns.dmi index 8154a753e0..cc04fbcb14 100644 Binary files a/modular_citadel/icons/obj/guns/cit_guns.dmi and b/modular_citadel/icons/obj/guns/cit_guns.dmi differ diff --git a/modular_citadel/icons/obj/pda.dmi b/modular_citadel/icons/obj/pda.dmi deleted file mode 100644 index 5404b908c6..0000000000 Binary files a/modular_citadel/icons/obj/pda.dmi and /dev/null differ diff --git a/sound/arcade/minesweeper_boardpress.ogg b/sound/arcade/minesweeper_boardpress.ogg new file mode 100644 index 0000000000..a928a7498d Binary files /dev/null and b/sound/arcade/minesweeper_boardpress.ogg differ diff --git a/sound/arcade/minesweeper_emag1.ogg b/sound/arcade/minesweeper_emag1.ogg new file mode 100644 index 0000000000..4601f8df89 Binary files /dev/null and b/sound/arcade/minesweeper_emag1.ogg differ diff --git a/sound/arcade/minesweeper_emag2.ogg b/sound/arcade/minesweeper_emag2.ogg new file mode 100644 index 0000000000..84cb5c2e25 Binary files /dev/null and b/sound/arcade/minesweeper_emag2.ogg differ diff --git a/sound/arcade/minesweeper_explosion1.ogg b/sound/arcade/minesweeper_explosion1.ogg new file mode 100644 index 0000000000..f8272722fd Binary files /dev/null and b/sound/arcade/minesweeper_explosion1.ogg differ diff --git a/sound/arcade/minesweeper_explosion2.ogg b/sound/arcade/minesweeper_explosion2.ogg new file mode 100644 index 0000000000..aabd43851d Binary files /dev/null and b/sound/arcade/minesweeper_explosion2.ogg differ diff --git a/sound/arcade/minesweeper_explosion3.ogg b/sound/arcade/minesweeper_explosion3.ogg new file mode 100644 index 0000000000..22aa309d9d Binary files /dev/null and b/sound/arcade/minesweeper_explosion3.ogg differ diff --git a/sound/arcade/minesweeper_menuselect.ogg b/sound/arcade/minesweeper_menuselect.ogg new file mode 100644 index 0000000000..b9e0b765dc Binary files /dev/null and b/sound/arcade/minesweeper_menuselect.ogg differ diff --git a/sound/arcade/minesweeper_startup.ogg b/sound/arcade/minesweeper_startup.ogg new file mode 100644 index 0000000000..c51d473d60 Binary files /dev/null and b/sound/arcade/minesweeper_startup.ogg differ diff --git a/sound/arcade/minesweeper_win.ogg b/sound/arcade/minesweeper_win.ogg new file mode 100644 index 0000000000..214f1925b0 Binary files /dev/null and b/sound/arcade/minesweeper_win.ogg differ diff --git a/sound/arcade/minesweeper_winfail.ogg b/sound/arcade/minesweeper_winfail.ogg new file mode 100644 index 0000000000..878f153063 Binary files /dev/null and b/sound/arcade/minesweeper_winfail.ogg differ diff --git a/sound/effects/gong.ogg b/sound/effects/gong.ogg new file mode 100644 index 0000000000..4d12f5d0d2 Binary files /dev/null and b/sound/effects/gong.ogg differ diff --git a/sound/magic/RATTLEMEBONES.ogg b/sound/magic/RATTLEMEBONES.ogg new file mode 100644 index 0000000000..d42cf51253 Binary files /dev/null and b/sound/magic/RATTLEMEBONES.ogg differ diff --git a/sound/magic/RATTLEMEBONES2.ogg b/sound/magic/RATTLEMEBONES2.ogg new file mode 100644 index 0000000000..7265a06aab Binary files /dev/null and b/sound/magic/RATTLEMEBONES2.ogg differ diff --git a/sound/weapons/whipgrab.ogg b/sound/weapons/whipgrab.ogg new file mode 100644 index 0000000000..3b17632056 Binary files /dev/null and b/sound/weapons/whipgrab.ogg differ diff --git a/strings/cas_black.txt b/strings/cas_black.txt index b63e33cdf2..734222d1fd 100644 --- a/strings/cas_black.txt +++ b/strings/cas_black.txt @@ -1,13 +1,13 @@ Today, Security killed ____. Security, the clown's breaking into ____. -The Chaplain is worshiping the Church of _____. +Our last Chaplain believed in nothing but _____. What angered the gods this time? Why didn't engineering set up the singularity? What does the traitor steal this time? Cargo: There's a galaxy-wide shortage of _______. I don't care what they called me back on the station, I'm not a traitor. I'm a man of _________. The Syndicate is offering crew members _________ to defect. -Cargo ordered a crate full of _____. +What is Nanotrasen's highest-priority bounty? What is the gray tide protesting this time? If the Space Gods didn't want _________ they wouldn't have given us __________. Why was the death squad sent in? @@ -30,11 +30,10 @@ What made the nuclear operatives fluke? Why did the Chief Engineer disable comms? Every spaceman receives an internals box and ________. What brought the space orgy to a grinding halt? -Scientists are no longer allowed to make _____. +Scientists are no longer allowed to make ______. What was the clown's best joke? The HoP is now hiring assistants for __________. What happens when you emag an emag? -Our gang doesn't wear uniforms. Our gang wears ___________. No matter how many lizards you have, _____ is never acceptable. No, the AI's second law is NOT to serve _____. First CentCom came for the ________. Now they're coming for the __________. @@ -109,5 +108,12 @@ The auxiliary base was disabled after landing in the middle of _______. Xenobiologists have found slimes to be exceptionally responsive to _______. Why did the captain give me a medal? The curator's new exhibit is devoted solely to _________. -There's no ______ on the new escape shuttle, but there is plenty of _________! -What made me sell my soul to the devil? \ No newline at end of file +What made me sell my soul to the devil? +The engineers are testing an experimental supermatter setup involving _________. +I'm __________ in the streets, __________ in the sheets. +What's my family heirloom? +The Lawyer was fired for messaging the entire station a picture of ___________. +On Lavaland, it is rumored that ashwalkers roam, worshipping _________. +How did the traitor die a glorious death? +Nanotrasen's new state-of-the-art emergency shuttle was repurposed from _________ and _________. +What caused my brain trauma? \ No newline at end of file diff --git a/strings/cas_white.txt b/strings/cas_white.txt index 8cf224d1db..3e229862a2 100644 --- a/strings/cas_white.txt +++ b/strings/cas_white.txt @@ -2,6 +2,7 @@ Those motherfucking carp. Having sex in the maintenance tunnels. Space 'Nam. Space lesbians. +Space NEETs. Space Hitler. Space Asshole. Ragin' mages. @@ -57,7 +58,6 @@ Defusing a syndicate bomb with another bomb. Going braindead mid-murder. A petsplosion. Meat spikes. -Collecting the crew's brains. Lopping off the Captain's johnson and shooting it out a pneumatic cannon. The secret monkey technique. Putting the pAI's doorjack where it don't belong. @@ -84,7 +84,6 @@ Paranoia. Putting the boots to him, medium style. ERP-seeking meteors. Paperwork HoPs. -A sexy clown. Rampant vending machines. The prisoner transfer center. Nations. @@ -186,7 +185,6 @@ A big, black shadowling dick. Emagging. Dead lizard storage. Dermal armor. -Energy balls. Fisting somebody until they gib. Alternate uses for defibrillator paddles. Breaking spacetime with thousands of bluespace tomatoes. @@ -197,7 +195,7 @@ Plasmaman strippers. A Quartermaster who WON'T STOP ordering guns. Space lag. Polishing the captain's laser rifle. -That one asshole double agent. +That one asshole nuke op. A surprise visit from Nanotrasen's CEO. The bleeding, dismembered, beautiful corpse of the clown. A glass of ...what? @@ -220,20 +218,18 @@ Welderbombing. Validhunting. Nar'Sie making love to Lord Singulo. Fun. -Crashing the stock market. HONK! -Enough morphine to put the entire station down. +Enough morphine to make the entire station comatose. A defective comdom. Cleanbot. A beaker of dried space carp penis. An Ian storm. -voxtest2. Nuking it from orbit. My senpAI. Harmbatonning. A Nanotrasen D-Notice. TALKING MIMES. -The lusty xenomorph maid, +The lusty xenomorph maid. Using assistants as human shields. Sentient securitrons. Piloting the station into the nearest sun. @@ -247,11 +243,11 @@ Medbay stutterwhores. The scrubbers uncontrollably spewing cum. The lawyer's job. Emoting slowly drawing a gun, then slowly cocking the trigger, then slowly preparing to shoot... -NAR-SIE HAS RISEN. +NAR'SIE HAS RISEN. Pierrot's Throat. A clown bomb. Space bees? -The entire engineering team having unprotected group sex. +Driving the clown car full speed into the engine. IC in OOC. The best cookie. The wizard with his staff inserted into his anus. @@ -276,9 +272,8 @@ Draconic. Riding borgs, cowgirl style. The Voice of God. Overpowered stuns. -Unironically reading library smut. +Unironically enjoying library smut. Spiritual journeys with BZ. -Freon. Deep-fried body parts. Suit sensor unit gas chambers. Moonlighting. @@ -294,4 +289,14 @@ Mindswap. Potassium in the toilet bowls. Giving head to the heads. A lizard wearing cat ears. -DOOR STUCK!! +Precious clown gold. +Dabbing on a pile of corpses. +Tactical chairs. +The sweet, forbidden meat of the gondola. +Turning tricks for holocredits. +A captain that doesn't secure the disk. +A positive moodlet. +A sexy clown. +Razoring the wings off the moths. +Wiring the ethereals into the powernet. +Well-aged miasma. \ No newline at end of file diff --git a/tgstation.dme b/tgstation.dme index c0ccbb097b..bb47c443ff 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -256,7 +256,6 @@ #include "code\controllers\subsystem\ping.dm" #include "code\controllers\subsystem\radiation.dm" #include "code\controllers\subsystem\radio.dm" -#include "code\controllers\subsystem\religion.dm" #include "code\controllers\subsystem\research.dm" #include "code\controllers\subsystem\server_maint.dm" #include "code\controllers\subsystem\shuttle.dm" @@ -495,6 +494,7 @@ #include "code\datums\wires\autolathe.dm" #include "code\datums\wires\emitter.dm" #include "code\datums\wires\explosive.dm" +#include "code\datums\wires\microwave.dm" #include "code\datums\wires\mulebot.dm" #include "code\datums\wires\particle_accelerator.dm" #include "code\datums\wires\r_n_d.dm" @@ -639,6 +639,10 @@ #include "code\game\machinery\computer\station_alert.dm" #include "code\game\machinery\computer\telecrystalconsoles.dm" #include "code\game\machinery\computer\teleporter.dm" +#include "code\game\machinery\computer\arcade\battle.dm" +#include "code\game\machinery\computer\arcade\minesweeper.dm" +#include "code\game\machinery\computer\arcade\misc_arcade.dm" +#include "code\game\machinery\computer\arcade\orion_trail.dm" #include "code\game\machinery\doors\airlock.dm" #include "code\game\machinery\doors\airlock_electronics.dm" #include "code\game\machinery\doors\airlock_types.dm" @@ -2881,7 +2885,6 @@ #include "modular_citadel\code\game\objects\items\vending_items.dm" #include "modular_citadel\code\game\objects\items\circuitboards\machine_circuitboards.dm" #include "modular_citadel\code\game\objects\items\devices\aicard.dm" -#include "modular_citadel\code\game\objects\items\devices\PDA\PDA.dm" #include "modular_citadel\code\game\objects\items\devices\radio\encryptionkey.dm" #include "modular_citadel\code\game\objects\items\devices\radio\headset.dm" #include "modular_citadel\code\game\objects\items\devices\radio\shockcollar.dm"