"
- 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()
- return TRUE
-
-
-
-// *** 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 += "
"
- 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 += "
"
- 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 += "
"
-
- 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 += "
"
-
- 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 += "
"
- 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 += "
"
- 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 += "
"
+ 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()
+ return TRUE
\ No newline at end of file
diff --git a/code/game/machinery/computer/arcade/minesweeper.dm b/code/game/machinery/computer/arcade/minesweeper.dm
new file mode 100644
index 0000000000..535673fc05
--- /dev/null
+++ b/code/game/machinery/computer/arcade/minesweeper.dm
@@ -0,0 +1,392 @@
+#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?
" //Make unique hrefs for every square
+ if(10)
+ web += "
[MINESWEEPERIMG(minehit)]
"
+ if(11)
+ web += "
[MINESWEEPERIMG(empty)]
"
+ if(12)
+ web += "
[MINESWEEPERIMG(1)]
"
+ if(13)
+ web += "
[MINESWEEPERIMG(2)]
"
+ if(14)
+ web += "
[MINESWEEPERIMG(3)]
"
+ if(15)
+ web += "
[MINESWEEPERIMG(4)]
"
+ if(16)
+ web += "
[MINESWEEPERIMG(5)]
"
+ if(17)
+ web += "
[MINESWEEPERIMG(6)]
"
+ if(18)
+ web += "
[MINESWEEPERIMG(7)]
"
+ if(19)
+ web += "
[MINESWEEPERIMG(8)]
"
+ web += ""
+ web += "
"
+ web += ""
+ web += " "
+
+ if(safe_squares_revealed >= 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 += "
"
+ 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
+ return TRUE
+
+/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..023b1048ce
--- /dev/null
+++ b/code/game/machinery/computer/arcade/orion_trail.dm
@@ -0,0 +1,811 @@
+
+
+// *** 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 += "
"
+ 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 += "
"
+ 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 += "
"
+
+ 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 += "
"
+
+ 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 += "
"
+ 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 += "
"
+ 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 += "
"
+
+
+//Add Random/Specific crewmember
+/obj/machinery/computer/arcade/orion_trail/proc/add_crewmember(var/specific = "")
+ var/newcrew = ""
+ if(specific)
+ newcrew = specific
+ else
+ if(prob(50))
+ newcrew = pick(GLOB.first_names_male)
+ else
+ newcrew = pick(GLOB.first_names_female)
+ if(newcrew)
+ settlers += newcrew
+ alive++
+ return newcrew
+
+
+//Remove Random/Specific crewmember
+/obj/machinery/computer/arcade/orion_trail/proc/remove_crewmember(var/specific = "", var/dont_remove = "")
+ var/list/safe2remove = settlers
+ var/removed = ""
+ if(dont_remove)
+ safe2remove -= dont_remove
+ if(specific && specific != dont_remove)
+ safe2remove = list(specific)
+ else
+ removed = pick(safe2remove)
+
+ if(removed)
+ if(lings_aboard && prob(40*lings_aboard)) //if there are 2 lings you're twice as likely to get one, obviously
+ lings_aboard = max(0,--lings_aboard)
+ settlers -= removed
+ alive--
+ return removed
+
+
+/obj/machinery/computer/arcade/orion_trail/proc/win(mob/user)
+ gameStatus = ORION_STATUS_START
+ say("Congratulations, you made it to Orion!")
+ if(obj_flags & EMAGGED)
+ new /obj/item/orion_ship(loc)
+ message_admins("[ADMIN_LOOKUPFLW(usr)] made it to Orion on an emagged machine and got an explosive toy ship.")
+ log_game("[key_name(usr)] made it to Orion on an emagged machine and got an explosive toy ship.")
+ else
+ prizevend(user)
+ obj_flags &= ~EMAGGED
+ name = "The Orion Trail"
+ desc = "Learn how our ancestors got to Orion, and have fun in the process!"
+
+/obj/machinery/computer/arcade/orion_trail/emag_act(mob/user)
+ . = ..()
+ if(obj_flags & EMAGGED)
+ return
+ to_chat(user, "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
+ return TRUE
+
+/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/dance_machine.dm b/code/game/machinery/dance_machine.dm
index 7beb32eebb..1c6d713437 100644
--- a/code/game/machinery/dance_machine.dm
+++ b/code/game/machinery/dance_machine.dm
@@ -214,11 +214,11 @@
sparkles += S
switch(i)
if(1 to 8)
- S.orbit(src, 30, TRUE, 60, 36, TRUE, FALSE)
+ S.orbit(src, 30, TRUE, 60, 36, TRUE)
if(9 to 16)
- S.orbit(src, 62, TRUE, 60, 36, TRUE, FALSE)
+ S.orbit(src, 62, TRUE, 60, 36, TRUE)
if(17 to 24)
- S.orbit(src, 95, TRUE, 60, 36, TRUE, FALSE)
+ S.orbit(src, 95, TRUE, 60, 36, TRUE)
if(25)
S.pixel_y = 7
S.forceMove(get_turf(src))
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index a561a1b029..933bb4f42a 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -214,6 +214,7 @@
flick("[src.base_state]spark", src)
playsound(src, "sparks", 75, 1)
addtimer(CALLBACK(src, .proc/open_windows_me), 6)
+ return TRUE
/obj/machinery/door/window/proc/open_windows_me()
operating = FALSE
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 1fd93e1ba3..09a128c558 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,45 +727,41 @@ 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.
. = ..()
@@ -777,7 +773,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
return
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 5c1218d825..d01d8ea23d 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 48b21d58bd..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,33 +203,34 @@ 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(obj/over_object, src_location, over_location)
+/obj/item/pda/MouseDrop(mob/over, src_location, over_location)
var/mob/M = usr
- if((!istype(over_object, /obj/screen)) && usr.canUseTopic(src))
+ if((M == over) && usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return attack_self(M)
return ..()
+/obj/item/pda/attack_self_tk(mob/user)
+ to_chat(user, "The PDA's capacitive touch screen doesn't seem to respond!")
+ return
+
/obj/item/pda/interact(mob/user)
if(!user.IsAdvancedToolUser())
to_chat(user, "You don't have the dexterity to do this!")
@@ -382,7 +436,7 @@ GLOBAL_LIST_EMPTY(PDAs)
var/mob/living/U = usr
//Looking for master was kind of pointless since PDAs don't appear to have one.
- if(usr.canUseTopic(src) && !href_list["close"])
+ if(usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK) && !href_list["close"])
add_fingerprint(U)
U.set_machine(src)
@@ -636,7 +690,7 @@ GLOBAL_LIST_EMPTY(PDAs)
/obj/item/pda/proc/remove_id()
- if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE))
+ if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if (id)
@@ -736,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)
@@ -802,7 +855,7 @@ GLOBAL_LIST_EMPTY(PDAs)
/obj/item/pda/proc/remove_pen()
- if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE))
+ if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(inserted_item)
@@ -1076,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/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 40f2059d25..d8b539ac27 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -13,7 +13,8 @@
actions_types = list(/datum/action/item_action/toggle_light)
var/on = FALSE
var/brightness_on = 4 //range of light when on
- var/flashlight_power = 1 //strength of the light when on
+ var/flashlight_power = 0.8 //strength of the light when on
+ light_color = "#FFCC66"
/obj/item/flashlight/Initialize()
. = ..()
@@ -63,7 +64,7 @@
to_chat(user, "[M] doesn't have a head!")
return
- if(flashlight_power < 1)
+ if(flashlight_power < 0.3)
to_chat(user, "\The [src] isn't bright enough to see anything! ")
return
@@ -168,6 +169,8 @@
item_state = ""
flags_1 = CONDUCT_1
brightness_on = 2
+ light_color = "#FFDDCC"
+ flashlight_power = 0.3
var/holo_cooldown = 0
/obj/item/flashlight/pen/afterattack(atom/target, mob/user, proximity_flag)
@@ -204,6 +207,8 @@
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
force = 9 // Not as good as a stun baton.
brightness_on = 5 // A little better than the standard flashlight.
+ light_color = "#CDDDFF"
+ flashlight_power = 0.9
hitsound = 'sound/weapons/genhit1.ogg'
// the desk lamps are a bit special
@@ -216,6 +221,7 @@
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
force = 10
brightness_on = 5
+ light_color = "#FFDDBB"
w_class = WEIGHT_CLASS_BULKY
flags_1 = CONDUCT_1
materials = list()
@@ -252,6 +258,7 @@
desc = "A red Nanotrasen issued flare. There are instructions on the side, it reads 'pull cord, make light'."
w_class = WEIGHT_CLASS_SMALL
brightness_on = 7 // Pretty bright.
+ light_color = "#FA421A"
icon_state = "flare"
item_state = "flare"
actions_types = list()
@@ -325,6 +332,7 @@
desc = "A torch fashioned from some leaves and a log."
w_class = WEIGHT_CLASS_BULKY
brightness_on = 4
+ light_color = "#FAA44B"
icon_state = "torch"
item_state = "torch"
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
@@ -341,6 +349,8 @@
righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi'
desc = "A mining lantern."
brightness_on = 6 // luminosity when on
+ light_color = "#FFAA44"
+ flashlight_power = 0.75
/obj/item/flashlight/slime
@@ -354,6 +364,8 @@
slot_flags = ITEM_SLOT_BELT
materials = list()
brightness_on = 6 //luminosity when on
+ light_color = "#FFEEAA"
+ flashlight_power = 0.6
/obj/item/flashlight/emp
var/emp_max_charges = 4
@@ -517,6 +529,7 @@
icon_state = null
light_color = null
brightness_on = 0
+ flashlight_power = 1
light_range = 0
light_power = 10
alpha = 0
@@ -538,7 +551,6 @@
name = "eyelight"
desc = "This shouldn't exist outside of someone's head, how are you seeing this?"
brightness_on = 15
- flashlight_power = 1
flags_1 = CONDUCT_1
item_flags = DROPDEL
actions_types = list()
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/plushes.dm b/code/game/objects/items/plushes.dm
index 9528bf94ba..12de29c76e 100644
--- a/code/game/objects/items/plushes.dm
+++ b/code/game/objects/items/plushes.dm
@@ -613,6 +613,20 @@
icon_state = "plushie_awake"
item_state = "plushie_awake"
+/obj/item/toy/plush/awakenedplushie/ComponentInitialize()
+ . = ..()
+ AddComponent(/datum/component/edit_complainer)
+
+
+/obj/item/toy/plush/beeplushie
+ name = "bee plushie"
+ desc = "A cute toy that resembles an even cuter bee."
+ icon_state = "plushie_h"
+ item_state = "plushie_h"
+ attack_verb = list("stung")
+ gender = FEMALE
+ squeak_override = list('modular_citadel/sound/voice/scream_moth.ogg' = 1)
+
/obj/item/toy/plush/mothplushie
name = "insect plushie"
desc = "An adorable stuffed toy that resembles some kind of insect"
@@ -904,7 +918,3 @@
item_state = "fermis"
attack_verb = list("cuddled", "petpatted", "wigglepurred")
squeak_override = list('modular_citadel/sound/voice/merowr.ogg' = 1)
-
-/obj/item/toy/plush/awakenedplushie/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/edit_complainer)
diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm
index e70e8553ed..a9f0e038df 100644
--- a/code/game/objects/items/shields.dm
+++ b/code/game/objects/items/shields.dm
@@ -170,7 +170,7 @@
name = "tower shield"
desc = "A massive shield that can block a lot of attacks, can take a lot of abuse before braking."
armor = list("melee" = 95, "bullet" = 95, "laser" = 75, "energy" = 60, "bomb" = 90, "bio" = 90, "rad" = 0, "fire" = 90, "acid" = 10) //Armor for the item, dosnt transfer to user
- icon_state = "metal"
+ item_state = "metal"
block_chance = 75 //1/4 shots will hit*
force = 10
slowdown = 2
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/backpack.dm b/code/game/objects/items/storage/backpack.dm
index 8178f0390a..c2929dafbd 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -589,3 +589,16 @@
new /obj/item/clothing/mask/gas/clown_hat(src)
new /obj/item/bikehorn(src)
new /obj/item/implanter/sad_trombone(src)
+
+obj/item/storage/backpack/duffelbag/syndie/shredderbundle
+ desc = "A large duffel bag containing two CX Shredders, some magazines, an elite hardsuit, and a chest rig."
+
+/obj/item/storage/backpack/duffelbag/syndie/shredderbundle/PopulateContents()
+ new /obj/item/ammo_box/magazine/flechette/shredder(src)
+ new /obj/item/ammo_box/magazine/flechette/shredder(src)
+ new /obj/item/ammo_box/magazine/flechette/shredder(src)
+ new /obj/item/ammo_box/magazine/flechette/shredder(src)
+ new /obj/item/gun/ballistic/automatic/flechette/shredder(src)
+ new /obj/item/gun/ballistic/automatic/flechette/shredder(src)
+ new /obj/item/storage/belt/military(src)
+ new /obj/item/clothing/suit/space/hardsuit/syndi/elite(src)
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index 57c77e5983..e2d7fdf9d7 100755
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -541,6 +541,25 @@
/obj/item/ammo_casing/shotgun
))
+/obj/item/storage/belt/medolier
+ name = "medolier"
+ desc = "A medical bandolier for holding smartdarts."
+ icon_state = "medolier"
+ item_state = "medolier"
+
+/obj/item/storage/belt/medolier/ComponentInitialize()
+ . = ..()
+ GET_COMPONENT(STR, /datum/component/storage)
+ STR.max_items = 15
+ STR.display_numerical_stacking = FALSE
+ STR.can_hold = typecacheof(list(
+ /obj/item/reagent_containers/syringe/dart
+ ))
+
+/obj/item/storage/belt/medolier/full/PopulateContents()
+ for(var/i in 1 to 16)
+ new /obj/item/reagent_containers/syringe/dart/(src)
+
/obj/item/storage/belt/holster
name = "shoulder holster"
desc = "A holster to carry a handgun and ammo. WARNING: Badasses only."
@@ -557,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/briefcase.dm b/code/game/objects/items/storage/briefcase.dm
index 1f80cec0f5..46676b5adb 100644
--- a/code/game/objects/items/storage/briefcase.dm
+++ b/code/game/objects/items/storage/briefcase.dm
@@ -80,6 +80,21 @@
new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src)
new /obj/item/suppressor/specialoffer(src)
+
+/obj/item/storage/briefcase/modularbundle
+ desc = "It's label reads genuine hardened Captain leather, but suspiciously has no other tags or branding."
+ force = 10
+
+/obj/item/storage/briefcase/modularbundle/PopulateContents()
+ new /obj/item/gun/ballistic/automatic/pistol/modular(src)
+ new /obj/item/suppressor(src)
+ new /obj/item/ammo_box/magazine/m10mm(src)
+ new /obj/item/ammo_box/magazine/m10mm/soporific(src)
+ new /obj/item/ammo_box/c10mm/soporific(src)
+ new /obj/item/clothing/under/lawyer/blacksuit(src)
+ new /obj/item/clothing/accessory/waistcoat(src)
+ new /obj/item/clothing/suit/toggle/lawyer/black/syndie(src)
+
/obj/item/storage/briefcase/medical
name = "medical briefcase"
icon_state = "medbriefcase"
@@ -89,3 +104,4 @@
new /obj/item/clothing/neck/stethoscope(src)
new /obj/item/healthanalyzer(src)
..() //In case of paperwork
+
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/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm
index 0b520d9dc1..b672eb01ca 100644
--- a/code/game/objects/items/tanks/jetpack.dm
+++ b/code/game/objects/items/tanks/jetpack.dm
@@ -160,6 +160,11 @@
distribute_pressure = 0
gas_type = /datum/gas/carbon_dioxide
+/obj/item/tank/jetpack/carbondioxide/eva
+ name = "surplus jetpack (carbon dioxide)"
+ desc = "A tank of compressed carbon dioxide for use as propulsion in zero-gravity areas. Painted black to indicate that it should not be used as a source for internals. Rated for less than stellar EVA speeds!"
+ full_speed = FALSE
+
/obj/item/tank/jetpack/suit
name = "hardsuit jetpack upgrade"
desc = "A modular, compact set of thrusters designed to integrate with a hardsuit. It is fueled by a tank inserted into the suit's storage compartment."
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/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index ea2e99d371..b15d686b7b 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -24,15 +24,13 @@
if(ishuman(user))
var/mob/living/carbon/human/H = user
- var/userloc = H.loc
-
//see code/modules/mob/dead/new_player/preferences.dm at approx line 545 for comments!
//this is largely copypasted from there.
//handle facial hair (if necessary)
if(H.gender == MALE)
var/new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in GLOB.facial_hair_styles_list
- if(userloc != H.loc)
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return //no tele-grooming
if(new_style)
H.facial_hair_style = new_style
@@ -41,7 +39,7 @@
//handle normal hair
var/new_style = input(user, "Select a hair style", "Grooming") as null|anything in GLOB.hair_styles_list
- if(userloc != H.loc)
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return //no tele-grooming
if(new_style)
H.hair_style = new_style
@@ -90,9 +88,9 @@
/obj/structure/mirror/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
if(BRUTE)
- playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
if(BURN)
- playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
/obj/structure/mirror/magic
@@ -131,7 +129,7 @@
var/choice = input(user, "Something to change?", "Magical Grooming") as null|anything in list("name", "race", "gender", "hair", "eyes")
- if(!Adjacent(user))
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
switch(choice)
@@ -140,7 +138,7 @@
if(!newname)
return
- if(!Adjacent(user))
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
H.real_name = newname
H.name = newname
@@ -156,7 +154,7 @@
if(!newrace)
return
- if(!Adjacent(user))
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
H.set_species(newrace, icon_update=0)
@@ -186,7 +184,7 @@
if("gender")
if(!(H.gender in list("male", "female"))) //blame the patriarchy
return
- if(!Adjacent(user))
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(H.gender == "male")
if(alert(H, "Become a Witch?", "Confirmation", "Yes", "No") == "Yes")
@@ -207,7 +205,7 @@
if("hair")
var/hairchoice = alert(H, "Hair style or hair color?", "Change Hair", "Style", "Color")
- if(!Adjacent(user))
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(hairchoice == "Style") //So you just want to use a mirror then?
..()
@@ -225,7 +223,7 @@
if(BODY_ZONE_PRECISE_EYES)
var/new_eye_color = input(H, "Choose your eye color", "Eye Color","#"+H.eye_color) as color|null
- if(!Adjacent(user))
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(new_eye_color)
H.eye_color = sanitize_hexcolor(new_eye_color)
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 57dc357859..e15613c43d 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -29,69 +29,62 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/callproc()
set category = "Debug"
set name = "Advanced ProcCall"
- set waitfor = 0
+ set waitfor = FALSE
if(!check_rights(R_DEBUG))
return
var/datum/target = null
- var/targetselected = 0
+ var/targetselected = FALSE
var/returnval = null
- switch(alert("Proc owned by something?",,"Yes","No"))
- if("Yes")
- targetselected = 1
- var/list/value = vv_get_value(default_class = VV_ATOM_REFERENCE, classes = list(VV_ATOM_REFERENCE, VV_DATUM_REFERENCE, VV_MOB_REFERENCE, VV_CLIENT))
- if (!value["class"] || !value["value"])
- return
- target = value["value"]
- if("No")
- target = null
- targetselected = 0
-
- var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
- if(!procname)
- return
-
- //hascall() doesn't support proc paths (eg: /proc/gib(), it only supports "gib")
- var/testname = procname
- if(targetselected)
- //Find one of the 3 possible ways they could have written /proc/PROCNAME
- if(findtext(procname, "/proc/"))
- testname = replacetext(procname, "/proc/", "")
- else if(findtext(procname, "/proc"))
- testname = replacetext(procname, "/proc", "")
- else if(findtext(procname, "proc/"))
- testname = replacetext(procname, "proc/", "")
- //Clear out any parenthesis if they're a dummy
- testname = replacetext(testname, "()", "")
-
- if(targetselected && !hascall(target,testname))
- to_chat(usr, "Error: callproc(): type [target.type] has no proc named [procname].")
- return
- else
- var/procpath = text2path(procname)
- if (!procpath)
- to_chat(usr, "Error: callproc(): proc [procname] does not exist. (Did you forget the /proc/ part?)")
+ if(alert("Proc owned by something?",,"Yes","No") == "Yes")
+ targetselected = TRUE
+ var/list/value = vv_get_value(default_class = VV_ATOM_REFERENCE, classes = list(VV_ATOM_REFERENCE, VV_DATUM_REFERENCE, VV_MOB_REFERENCE, VV_CLIENT))
+ if (!value["class"] || !value["value"])
return
+ target = value["value"]
+
+ var/procpath = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
+ if(!procpath)
+ return
+
+ //strip away everything but the proc name
+ var/list/proclist = splittext(procpath, "/")
+ if (!length(proclist))
+ return
+
+ var/procname = proclist[proclist.len]
+ var/proctype = ("verb" in proclist) ? "verb" :"proc"
+
+ if(targetselected)
+ if(!hascall(target, procname))
+ to_chat(usr, "Error: callproc(): type [target.type] has no [proctype] named [procpath].")
+ return
+ else
+ procpath = "/[proctype]/[procname]"
+ if(!text2path(procpath))
+ to_chat(usr, "Error: callproc(): [procpath] does not exist.")
+ return
+
var/list/lst = get_callproc_args()
if(!lst)
return
if(targetselected)
if(!target)
- to_chat(usr, "Error: callproc(): owner of proc no longer exists.")
+ to_chat(usr, "Error: callproc(): owner of proc no longer exists.")
return
- var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
+ var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no argument"]."
log_admin(msg)
message_admins(msg)
admin_ticket_log(target, msg)
- returnval = WrapAdminProcCall(target, procname, lst) // Pass the lst as an argument list to the proc
+ returnval = WrapAdminProcCall(target, procname, lst)
else
- //this currently has no hascall protection. wasn't able to get it working.
- log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
- message_admins("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
- returnval = WrapAdminProcCall(GLOBAL_PROC, procname, lst) // Pass the lst as an argument list to the proc
+ var/msg = "[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no argument"]."
+ log_admin(msg)
+ message_admins(msg)
+ returnval = WrapAdminProcCall(GLOBAL_PROC, procpath, lst) //calling globals needs full qualified name (e.g /proc/foo)
. = get_callproc_returnval(returnval, procname)
if(.)
to_chat(usr, .)
@@ -111,8 +104,8 @@ GLOBAL_LIST_EMPTY(AdminProcCallSpamPrevention)
GLOBAL_PROTECT(AdminProcCallSpamPrevention)
/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
- if(target && procname == "Del")
- to_chat(usr, "Calling Del() is not allowed")
+ if(target != GLOBAL_PROC && procname == "Del")
+ to_chat(usr, "Calling Del() is not allowed")
return
if(target != GLOBAL_PROC && !target.CanProcCall(procname))
@@ -159,7 +152,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
/client/proc/callproc_datum(datum/A as null|area|mob|obj|turf)
set category = "Debug"
set name = "Atom ProcCall"
- set waitfor = 0
+ set waitfor = FALSE
if(!check_rights(R_DEBUG))
return
@@ -168,7 +161,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(!procname)
return
if(!hascall(A,procname))
- to_chat(usr, "Error: callproc_datum(): type [A.type] has no proc named [procname].")
+ to_chat(usr, "Error: callproc_datum(): type [A.type] has no proc named [procname].")
return
var/list/lst = get_callproc_args()
if(!lst)
@@ -177,8 +170,8 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(!A || !IsValidSrc(A))
to_chat(usr, "Error: callproc_datum(): owner of proc no longer exists.")
return
- log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
var/msg = "[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
+ log_admin(msg)
message_admins(msg)
admin_ticket_log(A, msg)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Atom ProcCall") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -188,8 +181,6 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(.)
to_chat(usr, .)
-
-
/client/proc/get_callproc_args()
var/argnum = input("Number of arguments","Number:",0) as num|null
if(isnull(argnum))
@@ -213,7 +204,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
. = ""
if(islist(returnval))
var/list/returnedlist = returnval
- . = ""
+ . = ""
if(returnedlist.len)
var/assoc_check = returnedlist[1]
if(istext(assoc_check) && (returnedlist[assoc_check] != null))
@@ -227,11 +218,10 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
. += "\n[elem]"
else
. = "[procname] returned an empty list"
- . += ""
+ . += ""
else
- . = "[procname] returned: [!isnull(returnval) ? returnval : "null"]"
-
+ . = "[procname] returned: [!isnull(returnval) ? returnval : "null"]"
/client/proc/Cell()
set category = "Debug"
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/abductor/machinery/console.dm b/code/modules/antagonists/abductor/machinery/console.dm
index a14b667069..52bda50b86 100644
--- a/code/modules/antagonists/abductor/machinery/console.dm
+++ b/code/modules/antagonists/abductor/machinery/console.dm
@@ -126,8 +126,20 @@
if(vest)
vest.flip_mode()
-/obj/machinery/abductor/console/proc/SelectDisguise(remote = 0)
- var/entry_name = input( "Choose Disguise", "Disguise") as null|anything in disguises
+/obj/machinery/abductor/console/proc/SelectDisguise(remote = FALSE)
+ var/list/disguises2 = list()
+ for(var/name in disguises)
+ var/datum/icon_snapshot/snap = disguises[name]
+ var/image/dummy = image(snap.icon, src, snap.icon_state)
+ dummy.overlays = snap.overlays
+ disguises2[name] = dummy
+
+ var/entry_name
+ if(remote)
+ entry_name = show_radial_menu(usr, camera.eyeobj, disguises2)
+ else
+ entry_name = show_radial_menu(usr, src, disguises2)
+
var/datum/icon_snapshot/chosen = disguises[entry_name]
if(chosen && vest && (remote || in_range(usr,src)))
vest.SetDisguise(chosen)
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/antagonists/changeling/powers/panacea.dm b/code/modules/antagonists/changeling/powers/panacea.dm
index 9f7a36f214..8d571d21e3 100644
--- a/code/modules/antagonists/changeling/powers/panacea.dm
+++ b/code/modules/antagonists/changeling/powers/panacea.dm
@@ -29,7 +29,7 @@
O.forceMove(get_turf(user))
user.reagents.add_reagent("mutadone", 10)
- user.reagents.add_reagent("pen_acid", 20)
+ user.reagents.add_reagent("pen_jelly", 20)
user.reagents.add_reagent("antihol", 10)
user.reagents.add_reagent("mannitol", 25)
diff --git a/code/modules/antagonists/cult/cult_comms.dm b/code/modules/antagonists/cult/cult_comms.dm
index 8452f78ed3..761412e9f8 100644
--- a/code/modules/antagonists/cult/cult_comms.dm
+++ b/code/modules/antagonists/cult/cult_comms.dm
@@ -342,10 +342,7 @@
if(cooldown>world.time)
to_chat(owner, "You aren't ready to place another blood mark yet!")
return
- if(owner.orbiting && owner.orbiting.orbiting)
- target = owner.orbiting.orbiting
- else
- target = get_turf(owner)
+ target = owner.orbiting?.parent || get_turf(owner)
if(!target)
return
C.cult_team.blood_target = target
diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm
index 923a224b81..1df81a797b 100644
--- a/code/modules/antagonists/devil/true_devil/_true_devil.dm
+++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm
@@ -94,7 +94,7 @@
visible_message("[src] easily breaks out of [p_their()] handcuffs!", \
"With just a thought your handcuffs fall off.")
-/mob/living/carbon/true_devil/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/carbon/true_devil/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated())
to_chat(src, "You can't do that right now!")
return FALSE
diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm
index 46ad4f26b7..ef0a422079 100644
--- a/code/modules/atmospherics/gasmixtures/reactions.dm
+++ b/code/modules/atmospherics/gasmixtures/reactions.dm
@@ -95,7 +95,7 @@
cached_gases[/datum/gas/oxygen] -= cached_gases[/datum/gas/tritium]
if(burned_fuel)
- energy_released += FIRE_HYDROGEN_ENERGY_RELEASED * burned_fuel
+ energy_released += (FIRE_HYDROGEN_ENERGY_RELEASED * burned_fuel)
if(location && prob(10) && burned_fuel > TRITIUM_MINIMUM_RADIATION_ENERGY) //woah there let's not crash the server
radiation_pulse(location, energy_released/TRITIUM_BURN_RADIOACTIVITY_FACTOR)
@@ -285,6 +285,7 @@
if(do_explosion)
explosion(location, 0, 0, 5, power_ratio, TRUE, TRUE) //large shockwave, the actual radius is quite small - people will recognize that you're doing fusion
radiation_pulse(location, radiation_power) //You mean causing a super-tier fusion reaction in the halls is a bad idea?
+ SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, 30000)//The science is cool though.
playsound(location, 'sound/effects/supermatter.ogg', 100, 0)
else
playsound(location, 'sound/effects/phasein.ogg', 75, 0)
@@ -350,12 +351,20 @@
var/old_heat_capacity = air.heat_capacity()
var/reaction_efficency = min(1/((pressure/(0.1*ONE_ATMOSPHERE))*(max(cached_gases[/datum/gas/plasma]/cached_gases[/datum/gas/nitrous_oxide],1))),cached_gases[/datum/gas/nitrous_oxide],cached_gases[/datum/gas/plasma]/2)
var/energy_released = 2*reaction_efficency*FIRE_CARBON_ENERGY_RELEASED
+ if(cached_gases[/datum/gas/miasma] && cached_gases[/datum/gas/miasma] > 0)
+ energy_released /= cached_gases[/datum/gas/miasma]*0.1
+ if(cached_gases[/datum/gas/bz] && cached_gases[/datum/gas/bz] > 0)
+ energy_released *= cached_gases[/datum/gas/bz]*0.1
if ((cached_gases[/datum/gas/nitrous_oxide] - reaction_efficency < 0 )|| (cached_gases[/datum/gas/plasma] - (2*reaction_efficency) < 0)) //Shouldn't produce gas from nothing.
return NO_REACTION
cached_gases[/datum/gas/bz] += reaction_efficency
+ if(reaction_efficency == cached_gases[/datum/gas/nitrous_oxide])
+ cached_gases[/datum/gas/bz] -= min(pressure,1)
+ cached_gases[/datum/gas/oxygen] += min(pressure,1)
cached_gases[/datum/gas/nitrous_oxide] -= reaction_efficency
cached_gases[/datum/gas/plasma] -= 2*reaction_efficency
+ SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, (reaction_efficency**0.5)*BZ_RESEARCH_AMOUNT)
if(energy_released > 0)
var/new_heat_capacity = air.heat_capacity()
@@ -390,6 +399,7 @@
cached_gases[/datum/gas/plasma] -= heat_scale
cached_gases[/datum/gas/nitryl] -= heat_scale
+ SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, STIMULUM_RESEARCH_AMOUNT*max(stim_energy_change,0))
if(stim_energy_change)
var/new_heat_capacity = air.heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
@@ -418,6 +428,7 @@
cached_gases[/datum/gas/nitrogen] -= 20*nob_formed
cached_gases[/datum/gas/hypernoblium]+= nob_formed
+ SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, nob_formed*NOBLIUM_RESEARCH_AMOUNT)
if (nob_formed)
var/new_heat_capacity = air.heat_capacity()
@@ -449,3 +460,4 @@
//Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable
air.temperature += cleaned_air * 0.002
+ SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, cleaned_air*MIASMA_RESEARCH_AMOUNT)//Turns out the burning of miasma is kinda interesting to scientists
\ 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/console.dm b/code/modules/cargo/console.dm
index 9e7de663d4..1a607b4b96 100644
--- a/code/modules/cargo/console.dm
+++ b/code/modules/cargo/console.dm
@@ -49,6 +49,7 @@
var/obj/item/circuitboard/computer/cargo/board = circuit
board.contraband = TRUE
board.obj_flags |= EMAGGED
+ req_access = list()
return TRUE
/obj/machinery/computer/cargo/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
diff --git a/code/modules/cargo/exports/large_objects.dm b/code/modules/cargo/exports/large_objects.dm
index b5f0e7a240..bf77d836fb 100644
--- a/code/modules/cargo/exports/large_objects.dm
+++ b/code/modules/cargo/exports/large_objects.dm
@@ -131,6 +131,24 @@
unit_name = "security barrier"
export_types = list(/obj/item/grenade/barrier, /obj/structure/barricade/security)
+/datum/export/large/gas_canister
+ cost = 10 //Base cost of canister. You get more for nice gases inside.
+ unit_name = "Gas Canister"
+ export_types = list(/obj/machinery/portable_atmospherics/canister)
+/datum/export/large/gas_canister/get_cost(obj/O)
+ var/obj/machinery/portable_atmospherics/canister/C = O
+ var/worth = 10
+ var/gases = C.air_contents.gases
+
+ worth += gases[/datum/gas/bz]*4
+ worth += gases[/datum/gas/stimulum]*25
+ worth += gases[/datum/gas/hypernoblium]*1000
+ worth += gases[/datum/gas/miasma]*15
+ worth += gases[/datum/gas/tritium]*7
+ worth += gases[/datum/gas/pluoxium]*6
+ worth += gases[/datum/gas/nitryl]*30
+ return worth
+
/datum/export/large/odysseus
cost = 5500
unit_name = "working odysseus"
diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm
index d9cde85d98..0097346a34 100644
--- a/code/modules/cargo/expressconsole.dm
+++ b/code/modules/cargo/expressconsole.dm
@@ -64,6 +64,7 @@
var/obj/item/circuitboard/computer/cargo/board = circuit
board.obj_flags |= EMAGGED
packin_up()
+ req_access = list()
return TRUE
/obj/machinery/computer/cargo/express/proc/packin_up() // oh shit, I'm sorry
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 7042913b0d..bde3021c76 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -755,13 +755,24 @@
/datum/supply_pack/engineering/engihardsuit
name = "Engineering Hardsuit"
- desc = "Poly 'Who stole all the hardsuits!' Well now you can get more hardsuits if needed! NOTE ONE HARDSUIT IS IN THIS CRATE, as well as one air tank and maks!"
+ desc = "Poly 'Who stole all the hardsuits!' Well now you can get more hardsuits if needed! NOTE ONE HARDSUIT IS IN THIS CRATE, as well as one air tank and mask!"
cost = 2500
contains = list(/obj/item/tank/internals/air,
/obj/item/clothing/mask/gas,
/obj/item/clothing/suit/space/hardsuit/engine)
crate_name = "engineering hardsuit"
+/datum/supply_pack/engineering/atmoshardsuit
+ name = "Atmospherics Hardsuit"
+ desc = "Too many techs and not enough hardsuits? Time to buy some more! Comes with gas mask and air tank. Ask the CE to open."
+ cost = 5000
+ access = ACCESS_CE
+ contains = list(/obj/item/tank/internals/air,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/suit/space/hardsuit/engine/atmos)
+ crate_name = "atmospherics hardsuit"
+ crate_type = /obj/structure/closet/crate/secure/engineering
+
/datum/supply_pack/engineering/industrialrcd
name = "Industrial RCD"
desc = "A industrial RCD in case the station has gone through more then one meteor storm and the CE needs to bring out the somthing a bit more reliable. Dose not contain spare ammo for the industrial RCD or any other RCD modles."
@@ -1146,7 +1157,7 @@
/datum/supply_pack/materials/bz
name = "BZ Canister Crate"
desc = "Contains a canister of BZ. Requires Toxins access to open."
- cost = 5000
+ cost = 7500 // Costs 3 credits more than what you can get for selling it.
access = ACCESS_TOX_STORAGE
contains = list(/obj/machinery/portable_atmospherics/canister/bz)
crate_name = "BZ canister crate"
@@ -1949,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!"
@@ -2241,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 a0eea344a3..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")
@@ -2236,8 +2246,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.hair_style = hair_style
character.facial_hair_style = facial_hair_style
character.underwear = underwear
+ character.saved_underwear = underwear
character.undershirt = undershirt
+ character.saved_undershirt = undershirt
character.socks = socks
+ character.saved_socks = socks
character.backbag = backbag
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/clothing.dm b/code/modules/clothing/clothing.dm
index 746d5da60d..767b700051 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -216,6 +216,34 @@ BLIND // can't see anything
..()
+/obj/item/clothing/under/CtrlClick(mob/user)
+ . = ..()
+
+ if (!(item_flags & IN_INVENTORY))
+ return
+
+ if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ return
+
+ if(has_sensor == LOCKED_SENSORS)
+ to_chat(user, "The controls are locked.")
+ return
+ if(has_sensor == BROKEN_SENSORS)
+ to_chat(user, "The sensors have shorted out!")
+ return
+ if(has_sensor <= NO_SENSORS)
+ to_chat(user, "This suit does not have any sensors.")
+ return
+
+ sensor_mode = SENSOR_COORDS
+
+ to_chat(user, "Your suit will now report your exact vital lifesigns as well as your coordinate position.")
+
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(H.w_uniform == src)
+ H.update_suit_sensors()
+
/obj/item/clothing/under/AltClick(mob/user)
if(..())
return 1
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/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm
index deaedfec18..bf11d40caf 100644
--- a/code/modules/clothing/suits/jobs.dm
+++ b/code/modules/clothing/suits/jobs.dm
@@ -124,6 +124,9 @@
icon_state = "suitjacket_black"
item_state = "ro_suit"
+/obj/item/clothing/suit/toggle/lawyer/black/syndie
+ desc = "A snappy dress jacket. Suspiciously has no tags or branding."
+ armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 10, "rad" = 10, "fire" = 40, "acid" = 40)
//Mime
/obj/item/clothing/suit/suspenders
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index 97e9a8f8ca..91fde0dbd0 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -1,759 +1,758 @@
-/obj/item/clothing/under/pj/red
- name = "red pj's"
- desc = "Sleepwear."
- icon_state = "red_pyjamas"
- item_color = "red_pyjamas"
- item_state = "w_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/pj/blue
- name = "blue pj's"
- desc = "Sleepwear."
- icon_state = "blue_pyjamas"
- item_color = "blue_pyjamas"
- item_state = "w_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/patriotsuit
- name = "Patriotic Suit"
- desc = "Motorcycle not included."
- icon_state = "ek"
- item_state = "ek"
- item_color = "ek"
- can_adjust = FALSE
-
-/obj/item/clothing/under/scratch
- name = "white suit"
- desc = "A white suit, suitable for an excellent host."
- icon_state = "scratch"
- item_state = "scratch"
- item_color = "scratch"
- can_adjust = FALSE
-
-/obj/item/clothing/under/sl_suit
- desc = "It's a very amish looking suit."
- name = "amish suit"
- icon_state = "sl_suit"
- item_color = "sl_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/roman
- name = "\improper Roman armor"
- desc = "Ancient Roman armor. Made of metallic and leather straps."
- icon_state = "roman"
- item_color = "roman"
- item_state = "armor"
- can_adjust = FALSE
- strip_delay = 100
- resistance_flags = NONE
-
-/obj/item/clothing/under/waiter
- name = "waiter's outfit"
- desc = "It's a very smart uniform with a special pocket for tip."
- icon_state = "waiter"
- item_state = "waiter"
- item_color = "waiter"
- can_adjust = FALSE
-
-/obj/item/clothing/under/rank/prisoner
- name = "prison jumpsuit"
- desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position."
- icon_state = "prisoner"
- item_state = "o_suit"
- item_color = "prisoner"
- has_sensor = LOCKED_SENSORS
- sensor_mode = SENSOR_COORDS
- random_sensor = FALSE
-
-/obj/item/clothing/under/rank/mailman
- name = "mailman's jumpsuit"
- desc = "'Special delivery!'"
- icon_state = "mailman"
- item_state = "b_suit"
- item_color = "mailman"
-
-/obj/item/clothing/under/rank/psyche
- name = "psychedelic jumpsuit"
- desc = "Groovy!"
- icon_state = "psyche"
- item_state = "p_suit"
- item_color = "psyche"
-
-/obj/item/clothing/under/rank/clown/sexy
- name = "sexy-clown suit"
- desc = "It makes you look HONKable!"
- icon_state = "sexyclown"
- item_state = "sexyclown"
- item_color = "sexyclown"
- can_adjust = FALSE
-
-/obj/item/clothing/under/jabroni
- name = "Jabroni Outfit"
- desc = "The leather club is two sectors down."
- icon_state = "darkholme"
- item_state = "darkholme"
- item_color = "darkholme"
- can_adjust = FALSE
-
-/obj/item/clothing/under/rank/vice
- name = "vice officer's jumpsuit"
- desc = "It's the standard issue pretty-boy outfit, as seen on Holo-Vision."
- icon_state = "vice"
- item_state = "gy_suit"
- item_color = "vice"
- can_adjust = FALSE
-
-/obj/item/clothing/under/rank/centcom_officer
- desc = "It's a jumpsuit worn by CentCom Officers."
- name = "\improper CentCom officer's jumpsuit"
- icon_state = "officer"
- item_state = "g_suit"
- item_color = "officer"
- alt_covers_chest = TRUE
-
-/obj/item/clothing/under/rank/centcom_commander
- desc = "It's a jumpsuit worn by CentCom's highest-tier Commanders."
- name = "\improper CentCom officer's jumpsuit"
- icon_state = "centcom"
- item_state = "dg_suit"
- item_color = "centcom"
-
-/obj/item/clothing/under/space
- name = "\improper NASA jumpsuit"
- desc = "It has a NASA logo on it and is made of space-proofed materials."
- icon_state = "black"
- item_state = "bl_suit"
- item_color = "black"
- w_class = WEIGHT_CLASS_BULKY
- gas_transfer_coefficient = 0.01
- permeability_coefficient = 0.02
- body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- cold_protection = CHEST | GROIN | LEGS | ARMS //Needs gloves and shoes with cold protection to be fully protected.
- min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
- heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
- can_adjust = FALSE
- resistance_flags = NONE
-
-/obj/item/clothing/under/acj
- name = "administrative cybernetic jumpsuit"
- icon_state = "syndicate"
- item_state = "bl_suit"
- item_color = "syndicate"
- desc = "A cybernetically enhanced jumpsuit used for administrative duties."
- gas_transfer_coefficient = 0.01
- permeability_coefficient = 0.01
- body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- armor = list("melee" = 100, "bullet" = 100, "laser" = 100,"energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
- cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS
- min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
- heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
- can_adjust = FALSE
- resistance_flags = FIRE_PROOF | ACID_PROOF
-
-/obj/item/clothing/under/owl
- name = "owl uniform"
- desc = "A soft brown jumpsuit made of synthetic feathers and strong conviction."
- icon_state = "owl"
- item_color = "owl"
- can_adjust = FALSE
-
-/obj/item/clothing/under/griffin
- name = "griffon uniform"
- desc = "A soft brown jumpsuit with a white feather collar made of synthetic feathers and a lust for mayhem."
- icon_state = "griffin"
- item_color = "griffin"
- can_adjust = FALSE
-
-/obj/item/clothing/under/cloud
- name = "cloud"
- desc = "cloud"
- icon_state = "cloud"
- item_color = "cloud"
- can_adjust = FALSE
-
-/obj/item/clothing/under/gimmick/rank/captain/suit
- name = "captain's suit"
- desc = "A green suit and yellow necktie. Exemplifies authority."
- icon_state = "green_suit"
- item_state = "dg_suit"
- item_color = "green_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/gimmick/rank/head_of_personnel/suit
- name = "head of personnel's suit"
- desc = "A teal suit and yellow necktie. An authoritative yet tacky ensemble."
- icon_state = "teal_suit"
- item_state = "g_suit"
- item_color = "teal_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/suit_jacket
- name = "black suit"
- desc = "A black suit and red tie. Very formal."
- icon_state = "black_suit"
- item_state = "bl_suit"
- item_color = "black_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/suit_jacket/really_black
- name = "executive suit"
- desc = "A formal black suit and red tie, intended for the station's finest."
- icon_state = "really_black_suit"
- item_state = "bl_suit"
- item_color = "black_suit"
-
-/obj/item/clothing/under/suit_jacket/female
- name = "executive suit"
- desc = "A formal trouser suit for women, intended for the station's finest."
- icon_state = "black_suit_fem"
- item_state = "black_suit_fem"
- item_color = "black_suit_fem"
-
-/obj/item/clothing/under/suit_jacket/green
- name = "green suit"
- desc = "A green suit and yellow necktie. Baller."
- icon_state = "green_suit"
- item_state = "dg_suit"
- item_color = "green_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/suit_jacket/red
- name = "red suit"
- desc = "A red suit and blue tie. Somewhat formal."
- icon_state = "red_suit"
- item_state = "r_suit"
- item_color = "red_suit"
-
-/obj/item/clothing/under/suit_jacket/charcoal
- name = "charcoal suit"
- desc = "A charcoal suit and red tie. Very professional."
- icon_state = "charcoal_suit"
- item_state = "charcoal_suit"
- item_color = "charcoal_suit"
-
-/obj/item/clothing/under/suit_jacket/navy
- name = "navy suit"
- desc = "A navy suit and red tie, intended for the station's finest."
- icon_state = "navy_suit"
- item_state = "navy_suit"
- item_color = "navy_suit"
-
-/obj/item/clothing/under/suit_jacket/burgundy
- name = "burgundy suit"
- desc = "A burgundy suit and black tie. Somewhat formal."
- icon_state = "burgundy_suit"
- item_state = "burgundy_suit"
- item_color = "burgundy_suit"
-
-/obj/item/clothing/under/suit_jacket/checkered
- name = "checkered suit"
- desc = "That's a very nice suit you have there. Shame if something were to happen to it, eh?"
- icon_state = "checkered_suit"
- item_state = "checkered_suit"
- item_color = "checkered_suit"
-
-/obj/item/clothing/under/suit_jacket/tan
- name = "tan suit"
- desc = "A tan suit with a yellow tie. Smart, but casual."
- icon_state = "tan_suit"
- item_state = "tan_suit"
- item_color = "tan_suit"
-
-/obj/item/clothing/under/suit_jacket/white
- name = "white suit"
- desc = "A white suit and jacket with a blue shirt. You wanna play rough? OKAY!"
- icon_state = "white_suit"
- item_state = "white_suit"
- item_color = "white_suit"
-
-/obj/item/clothing/under/burial
- name = "burial garments"
- desc = "Traditional burial garments from the early 22nd century."
- icon_state = "burial"
- item_state = "burial"
- item_color = "burial"
- has_sensor = NO_SENSORS
-
-/obj/item/clothing/under/skirt/black
- name = "black skirt"
- desc = "A black skirt, very fancy!"
- icon_state = "blackskirt"
- item_color = "blackskirt"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/skirt/blue
- name = "blue skirt"
- desc = "A blue, casual skirt."
- icon_state = "blueskirt"
- item_color = "blueskirt"
- item_state = "b_suit"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/skirt/red
- name = "red skirt"
- desc = "A red, casual skirt."
- icon_state = "redskirt"
- item_color = "redskirt"
- item_state = "r_suit"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/skirt/purple
- name = "purple skirt"
- desc = "A purple, casual skirt."
- icon_state = "purpleskirt"
- item_color = "purpleskirt"
- item_state = "p_suit"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-
-/obj/item/clothing/under/schoolgirl
- name = "blue schoolgirl uniform"
- desc = "It's just like one of my Japanese animes!"
- icon_state = "schoolgirl"
- item_state = "schoolgirl"
- item_color = "schoolgirl"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/schoolgirl/red
- name = "red schoolgirl uniform"
- icon_state = "schoolgirlred"
- item_state = "schoolgirlred"
- item_color = "schoolgirlred"
-
-/obj/item/clothing/under/schoolgirl/green
- name = "green schoolgirl uniform"
- icon_state = "schoolgirlgreen"
- item_state = "schoolgirlgreen"
- item_color = "schoolgirlgreen"
-
-/obj/item/clothing/under/schoolgirl/orange
- name = "orange schoolgirl uniform"
- icon_state = "schoolgirlorange"
- item_state = "schoolgirlorange"
- item_color = "schoolgirlorange"
-
-/obj/item/clothing/under/overalls
- name = "laborer's overalls"
- desc = "A set of durable overalls for getting the job done."
- icon_state = "overalls"
- item_state = "lb_suit"
- item_color = "overalls"
- can_adjust = FALSE
-
-/obj/item/clothing/under/pirate
- name = "pirate outfit"
- desc = "Yarr."
- icon_state = "pirate"
- item_state = "pirate"
- item_color = "pirate"
- can_adjust = FALSE
-
-/obj/item/clothing/under/soviet
- name = "soviet uniform"
- desc = "For the Motherland!"
- icon_state = "soviet"
- item_state = "soviet"
- item_color = "soviet"
- can_adjust = FALSE
-
-/obj/item/clothing/under/redcoat
- name = "redcoat uniform"
- desc = "Looks old."
- icon_state = "redcoat"
- item_state = "redcoat"
- item_color = "redcoat"
- can_adjust = FALSE
-
-/obj/item/clothing/under/kilt
- name = "kilt"
- desc = "Includes shoes and plaid."
- icon_state = "kilt"
- item_state = "kilt"
- item_color = "kilt"
- body_parts_covered = CHEST|GROIN|LEGS|FEET
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/kilt/highlander
- desc = "You're the only one worthy of this kilt."
- item_flags = NODROP
-
-/obj/item/clothing/under/sexymime
- name = "sexy mime outfit"
- desc = "The only time when you DON'T enjoy looking at someone's rack."
- icon_state = "sexymime"
- item_state = "sexymime"
- item_color = "sexymime"
- body_parts_covered = CHEST|GROIN|LEGS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/gladiator
- name = "gladiator uniform"
- desc = "Are you not entertained? Is that not why you are here?"
- icon_state = "gladiator"
- item_state = "gladiator"
- item_color = "gladiator"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = NO_FEMALE_UNIFORM
- can_adjust = FALSE
- resistance_flags = NONE
-
-/obj/item/clothing/under/gladiator/ash_walker
- desc = "This gladiator uniform appears to be covered in ash and fairly dated."
- has_sensor = NO_SENSORS
-
-/obj/item/clothing/under/sundress
- name = "sundress"
- desc = "Makes you want to frolic in a field of daisies."
- icon_state = "sundress"
- item_state = "sundress"
- item_color = "sundress"
- body_parts_covered = CHEST|GROIN
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/captainparade
- name = "captain's parade uniform"
- desc = "A captain's luxury-wear, for special occasions."
- icon_state = "captain_parade"
- item_state = "by_suit"
- item_color = "captain_parade"
- can_adjust = FALSE
-
-/obj/item/clothing/under/hosparademale
- name = "head of security's parade uniform"
- desc = "A male head of security's luxury-wear, for special occasions."
- icon_state = "hos_parade_male"
- item_state = "r_suit"
- item_color = "hos_parade_male"
- can_adjust = FALSE
-
-/obj/item/clothing/under/hosparadefem
- name = "head of security's parade uniform"
- desc = "A female head of security's luxury-wear, for special occasions."
- icon_state = "hos_parade_fem"
- item_state = "r_suit"
- item_color = "hos_parade_fem"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/assistantformal
- name = "assistant's formal uniform"
- desc = "An assistant's formal-wear. Why an assistant needs formal-wear is still unknown."
- icon_state = "assistant_formal"
- item_state = "gy_suit"
- item_color = "assistant_formal"
- can_adjust = FALSE
-
-/obj/item/clothing/under/blacktango
- name = "black tango dress"
- desc = "Filled with Latin fire."
- icon_state = "black_tango"
- item_state = "wcoat"
- item_color = "black_tango"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
- body_parts_covered = CHEST|GROIN
-
-/obj/item/clothing/under/stripeddress
- name = "striped dress"
- desc = "Fashion in space."
- icon_state = "striped_dress"
- item_state = "stripeddress"
- item_color = "striped_dress"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_FULL
- can_adjust = FALSE
-
-/obj/item/clothing/under/sailordress
- name = "sailor dress"
- desc = "Formal wear for a leading lady."
- icon_state = "sailor_dress"
- item_state = "sailordress"
- item_color = "sailor_dress"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/redeveninggown
- name = "red evening gown"
- desc = "Fancy dress for space bar singers."
- icon_state = "red_evening_gown"
- item_state = "redeveninggown"
- item_color = "red_evening_gown"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/maid
- name = "maid costume"
- desc = "Maid in China."
- icon_state = "maid"
- item_state = "maid"
- item_color = "maid"
- body_parts_covered = CHEST|GROIN
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/maid/Initialize()
- . = ..()
- var/obj/item/clothing/accessory/maidapron/A = new (src)
- attach_accessory(A)
-
-/obj/item/clothing/under/janimaid
- name = "maid uniform"
- desc = "A simple maid uniform for housekeeping."
- icon_state = "janimaid"
- item_state = "janimaid"
- item_color = "janimaid"
- body_parts_covered = CHEST|GROIN
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/plaid_skirt
- name = "red plaid skirt"
- desc = "A preppy red skirt with a white blouse."
- icon_state = "plaid_red"
- item_state = "plaid_red"
- item_color = "plaid_red"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = TRUE
- alt_covers_chest = TRUE
-
-/obj/item/clothing/under/plaid_skirt/blue
- name = "blue plaid skirt"
- desc = "A preppy blue skirt with a white blouse."
- icon_state = "plaid_blue"
- item_state = "plaid_blue"
- item_color = "plaid_blue"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = TRUE
- alt_covers_chest = TRUE
-
-/obj/item/clothing/under/plaid_skirt/purple
- name = "purple plaid skirt"
- desc = "A preppy purple skirt with a white blouse."
- icon_state = "plaid_purple"
- item_state = "plaid_purple"
- item_color = "plaid_purple"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = TRUE
- alt_covers_chest = TRUE
-
-/obj/item/clothing/under/singery
- name = "yellow performer's outfit"
- desc = "Just looking at this makes you want to sing."
- icon_state = "ysing"
- item_state = "ysing"
- item_color = "ysing"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = NO_FEMALE_UNIFORM
- alternate_worn_layer = ABOVE_SHOES_LAYER
- can_adjust = FALSE
-
-/obj/item/clothing/under/singerb
- name = "blue performer's outfit"
- desc = "Just looking at this makes you want to sing."
- icon_state = "bsing"
- item_state = "bsing"
- item_color = "bsing"
- body_parts_covered = CHEST|GROIN|ARMS
- alternate_worn_layer = ABOVE_SHOES_LAYER
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/plaid_skirt/green
- name = "green plaid skirt"
- desc = "A preppy green skirt with a white blouse."
- icon_state = "plaid_green"
- item_state = "plaid_green"
- item_color = "plaid_green"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = TRUE
- alt_covers_chest = TRUE
-
-/obj/item/clothing/under/jester
- name = "jester suit"
- desc = "A jolly dress, well suited to entertain your master, nuncle."
- icon_state = "jester"
- item_color = "jester"
- can_adjust = FALSE
-
-/obj/item/clothing/under/jester/alt
- icon_state = "jester2"
-
-/obj/item/clothing/under/geisha
- name = "geisha suit"
- desc = "Cute space ninja senpai not included."
- icon_state = "geisha"
- item_color = "geisha"
- body_parts_covered = CHEST|GROIN|ARMS
- can_adjust = FALSE
-
-/obj/item/clothing/under/villain
- name = "villain suit"
- desc = "A change of wardrobe is necessary if you ever want to catch a real superhero."
- icon_state = "villain"
- item_color = "villain"
- can_adjust = FALSE
-
-/obj/item/clothing/under/sailor
- name = "sailor suit"
- desc = "Skipper's in the wardroom drinkin gin'."
- icon_state = "sailor"
- item_state = "b_suit"
- item_color = "sailor"
- can_adjust = FALSE
-
-/obj/item/clothing/under/plasmaman
- name = "plasma envirosuit"
- desc = "A special containment suit that allows plasma-based lifeforms to exist safely in an oxygenated environment, and automatically extinguishes them in a crisis. Despite being airtight, it's not spaceworthy."
- icon_state = "plasmaman"
- item_state = "plasmaman"
- item_color = "plasmaman"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95)
- body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- can_adjust = FALSE
- strip_delay = 80
- var/next_extinguish = 0
- var/extinguish_cooldown = 100
- var/extinguishes_left = 5
-
-
-/obj/item/clothing/under/plasmaman/examine(mob/user)
- ..()
- to_chat(user, "There are [extinguishes_left] extinguisher charges left in this suit.")
-
-
-/obj/item/clothing/under/plasmaman/proc/Extinguish(mob/living/carbon/human/H)
- if(!istype(H))
- return
-
- if(H.on_fire)
- if(extinguishes_left)
- if(next_extinguish > world.time)
- return
- next_extinguish = world.time + extinguish_cooldown
- extinguishes_left--
- H.visible_message("[H]'s suit automatically extinguishes [H.p_them()]!","Your suit automatically extinguishes you.")
- H.ExtinguishMob()
- new /obj/effect/particle_effect/water(get_turf(H))
- return 0
-
-/obj/item/clothing/under/plasmaman/attackby(obj/item/E, mob/user, params)
- ..()
- if (istype(E, /obj/item/extinguisher_refill))
- if (extinguishes_left == 5)
- to_chat(user, "The inbuilt extinguisher is full.")
- return
- else
- extinguishes_left = 5
- to_chat(user, "You refill the suit's built-in extinguisher, using up the cartridge.")
- qdel(E)
- return
- return
- return
-
-/obj/item/extinguisher_refill
- name = "envirosuit extinguisher cartridge"
- desc = "A cartridge loaded with a compressed extinguisher mix, used to refill the automatic extinguisher on plasma envirosuits."
- icon_state = "plasmarefill"
- icon = 'icons/obj/device.dmi'
-
-/obj/item/clothing/under/rank/security/navyblue/russian
- name = "\improper Russian officer's uniform"
- desc = "The latest in fashionable russian outfits."
- icon_state = "hostanclothes"
- item_state = "hostanclothes"
- item_color = "hostanclothes"
-
-/obj/item/clothing/under/mummy
- name = "mummy wrapping"
- desc = "Return the slab or suffer my stale references."
- icon_state = "mummy"
- item_state = "mummy"
- item_color = "mummy"
- body_parts_covered = CHEST|GROIN|ARMS|LEGS
- fitted = NO_FEMALE_UNIFORM
- can_adjust = FALSE
- resistance_flags = NONE
-
-/obj/item/clothing/under/scarecrow
- name = "scarecrow clothes"
- desc = "Perfect camouflage for hiding in botany."
- icon_state = "scarecrow"
- item_state = "scarecrow"
- item_color = "scarecrow"
- body_parts_covered = CHEST|GROIN|ARMS|LEGS
- fitted = NO_FEMALE_UNIFORM
- can_adjust = FALSE
- resistance_flags = NONE
-
-/obj/item/clothing/under/draculass
- name = "draculass coat"
- desc = "A dress inspired by the ancient \"Victorian\" era."
- icon_state = "draculass"
- item_state = "draculass"
- item_color = "draculass"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
- mutantrace_variation = NO_MUTANTRACE_VARIATION
-
-/obj/item/clothing/under/drfreeze
- name = "doctor freeze's jumpsuit"
- desc = "A modified scientist jumpsuit to look extra cool."
- icon_state = "drfreeze"
- item_state = "drfreeze"
- item_color = "drfreeze"
- can_adjust = FALSE
- mutantrace_variation = NO_MUTANTRACE_VARIATION
-
-/obj/item/clothing/under/lobster
- name = "foam lobster suit"
- desc = "Who beheaded the college mascot?"
- icon_state = "lobster"
- item_state = "lobster"
- item_color = "lobster"
- fitted = NO_FEMALE_UNIFORM
- can_adjust = FALSE
- mutantrace_variation = NO_MUTANTRACE_VARIATION
-
-/obj/item/clothing/under/gondola
- name = "gondola hide suit"
- desc = "Now you're cooking."
- icon_state = "gondola"
- item_state = "lb_suit"
- item_color = "gondola"
- can_adjust = FALSE
-
-/obj/item/clothing/under/skeleton
- name = "skeleton jumpsuit"
- desc = "A black jumpsuit with a white bone pattern printed on it. Spooky!"
- icon_state = "skeleton"
- item_state = "skeleton"
- item_color = "skeleton"
- body_parts_covered = CHEST|GROIN|ARMS|LEGS
- fitted = NO_FEMALE_UNIFORM
- can_adjust = FALSE
- resistance_flags = NONE
-
-/obj/item/clothing/under/permit
- name = "public nudity permit"
- desc = "This permit entitles the bearer to conduct their duties without a uniform. Normally issued to furred crewmembers or those with nothing to hide."
- icon = 'icons/obj/card.dmi'
- icon_state = "fingerprint1"
- item_state = "golem" //This is dumb and hacky but was here when I got here.//No, it really isn't. Why make a new blank clothing sprite if we already have one?
- body_parts_covered = CHEST|GROIN
+/obj/item/clothing/under/pj/red
+ name = "red pj's"
+ desc = "Sleepwear."
+ icon_state = "red_pyjamas"
+ item_color = "red_pyjamas"
+ item_state = "w_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/pj/blue
+ name = "blue pj's"
+ desc = "Sleepwear."
+ icon_state = "blue_pyjamas"
+ item_color = "blue_pyjamas"
+ item_state = "w_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/patriotsuit
+ name = "Patriotic Suit"
+ desc = "Motorcycle not included."
+ icon_state = "ek"
+ item_state = "ek"
+ item_color = "ek"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/scratch
+ name = "white suit"
+ desc = "A white suit, suitable for an excellent host."
+ icon_state = "scratch"
+ item_state = "scratch"
+ item_color = "scratch"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/sl_suit
+ desc = "It's a very amish looking suit."
+ name = "amish suit"
+ icon_state = "sl_suit"
+ item_color = "sl_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/roman
+ name = "\improper Roman armor"
+ desc = "Ancient Roman armor. Made of metallic and leather straps."
+ icon_state = "roman"
+ item_color = "roman"
+ item_state = "armor"
+ can_adjust = FALSE
+ strip_delay = 100
+ resistance_flags = NONE
+
+/obj/item/clothing/under/waiter
+ name = "waiter's outfit"
+ desc = "It's a very smart uniform with a special pocket for tip."
+ icon_state = "waiter"
+ item_state = "waiter"
+ item_color = "waiter"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/rank/prisoner
+ name = "prison jumpsuit"
+ desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position."
+ icon_state = "prisoner"
+ item_state = "o_suit"
+ item_color = "prisoner"
+ has_sensor = LOCKED_SENSORS
+ sensor_mode = SENSOR_COORDS
+ random_sensor = FALSE
+
+/obj/item/clothing/under/rank/mailman
+ name = "mailman's jumpsuit"
+ desc = "'Special delivery!'"
+ icon_state = "mailman"
+ item_state = "b_suit"
+ item_color = "mailman"
+
+/obj/item/clothing/under/rank/psyche
+ name = "psychedelic jumpsuit"
+ desc = "Groovy!"
+ icon_state = "psyche"
+ item_state = "p_suit"
+ item_color = "psyche"
+
+/obj/item/clothing/under/rank/clown/sexy
+ name = "sexy-clown suit"
+ desc = "It makes you look HONKable!"
+ icon_state = "sexyclown"
+ item_state = "sexyclown"
+ item_color = "sexyclown"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/jabroni
+ name = "Jabroni Outfit"
+ desc = "The leather club is two sectors down."
+ icon_state = "darkholme"
+ item_state = "darkholme"
+ item_color = "darkholme"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/rank/vice
+ name = "vice officer's jumpsuit"
+ desc = "It's the standard issue pretty-boy outfit, as seen on Holo-Vision."
+ icon_state = "vice"
+ item_state = "gy_suit"
+ item_color = "vice"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/rank/centcom_officer
+ desc = "It's a jumpsuit worn by CentCom Officers."
+ name = "\improper CentCom officer's jumpsuit"
+ icon_state = "officer"
+ item_state = "g_suit"
+ item_color = "officer"
+ alt_covers_chest = TRUE
+
+/obj/item/clothing/under/rank/centcom_commander
+ desc = "It's a jumpsuit worn by CentCom's highest-tier Commanders."
+ name = "\improper CentCom officer's jumpsuit"
+ icon_state = "centcom"
+ item_state = "dg_suit"
+ item_color = "centcom"
+
+/obj/item/clothing/under/space
+ name = "\improper NASA jumpsuit"
+ desc = "It has a NASA logo on it and is made of space-proofed materials."
+ icon_state = "black"
+ item_state = "bl_suit"
+ item_color = "black"
+ w_class = WEIGHT_CLASS_BULKY
+ gas_transfer_coefficient = 0.01
+ permeability_coefficient = 0.02
+ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ cold_protection = CHEST | GROIN | LEGS | ARMS //Needs gloves and shoes with cold protection to be fully protected.
+ min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
+ heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
+ can_adjust = FALSE
+ resistance_flags = NONE
+
+/obj/item/clothing/under/acj
+ name = "administrative cybernetic jumpsuit"
+ icon_state = "syndicate"
+ item_state = "bl_suit"
+ item_color = "syndicate"
+ desc = "A cybernetically enhanced jumpsuit used for administrative duties."
+ gas_transfer_coefficient = 0.01
+ permeability_coefficient = 0.01
+ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ armor = list("melee" = 100, "bullet" = 100, "laser" = 100,"energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
+ cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS
+ min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
+ heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
+ can_adjust = FALSE
+ resistance_flags = FIRE_PROOF | ACID_PROOF
+
+/obj/item/clothing/under/owl
+ name = "owl uniform"
+ desc = "A soft brown jumpsuit made of synthetic feathers and strong conviction."
+ icon_state = "owl"
+ item_color = "owl"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/griffin
+ name = "griffon uniform"
+ desc = "A soft brown jumpsuit with a white feather collar made of synthetic feathers and a lust for mayhem."
+ icon_state = "griffin"
+ item_color = "griffin"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/cloud
+ name = "cloud"
+ desc = "cloud"
+ icon_state = "cloud"
+ item_color = "cloud"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/gimmick/rank/captain/suit
+ name = "captain's suit"
+ desc = "A green suit and yellow necktie. Exemplifies authority."
+ icon_state = "green_suit"
+ item_state = "dg_suit"
+ item_color = "green_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/gimmick/rank/head_of_personnel/suit
+ name = "head of personnel's suit"
+ desc = "A teal suit and yellow necktie. An authoritative yet tacky ensemble."
+ icon_state = "teal_suit"
+ item_state = "g_suit"
+ item_color = "teal_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/suit_jacket
+ name = "black suit"
+ desc = "A black suit and red tie. Very formal."
+ icon_state = "black_suit"
+ item_state = "bl_suit"
+ item_color = "black_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/suit_jacket/really_black
+ name = "executive suit"
+ desc = "A formal black suit and red tie, intended for the station's finest."
+ icon_state = "really_black_suit"
+ item_state = "bl_suit"
+ item_color = "black_suit"
+
+/obj/item/clothing/under/suit_jacket/female
+ name = "executive suit"
+ desc = "A formal trouser suit for women, intended for the station's finest."
+ icon_state = "black_suit_fem"
+ item_state = "black_suit_fem"
+ item_color = "black_suit_fem"
+
+/obj/item/clothing/under/suit_jacket/green
+ name = "green suit"
+ desc = "A green suit and yellow necktie. Baller."
+ icon_state = "green_suit"
+ item_state = "dg_suit"
+ item_color = "green_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/suit_jacket/red
+ name = "red suit"
+ desc = "A red suit and blue tie. Somewhat formal."
+ icon_state = "red_suit"
+ item_state = "r_suit"
+ item_color = "red_suit"
+
+/obj/item/clothing/under/suit_jacket/charcoal
+ name = "charcoal suit"
+ desc = "A charcoal suit and red tie. Very professional."
+ icon_state = "charcoal_suit"
+ item_state = "charcoal_suit"
+ item_color = "charcoal_suit"
+
+/obj/item/clothing/under/suit_jacket/navy
+ name = "navy suit"
+ desc = "A navy suit and red tie, intended for the station's finest."
+ icon_state = "navy_suit"
+ item_state = "navy_suit"
+ item_color = "navy_suit"
+
+/obj/item/clothing/under/suit_jacket/burgundy
+ name = "burgundy suit"
+ desc = "A burgundy suit and black tie. Somewhat formal."
+ icon_state = "burgundy_suit"
+ item_state = "burgundy_suit"
+ item_color = "burgundy_suit"
+
+/obj/item/clothing/under/suit_jacket/checkered
+ name = "checkered suit"
+ desc = "That's a very nice suit you have there. Shame if something were to happen to it, eh?"
+ icon_state = "checkered_suit"
+ item_state = "checkered_suit"
+ item_color = "checkered_suit"
+
+/obj/item/clothing/under/suit_jacket/tan
+ name = "tan suit"
+ desc = "A tan suit with a yellow tie. Smart, but casual."
+ icon_state = "tan_suit"
+ item_state = "tan_suit"
+ item_color = "tan_suit"
+
+/obj/item/clothing/under/suit_jacket/white
+ name = "white suit"
+ desc = "A white suit and jacket with a blue shirt. You wanna play rough? OKAY!"
+ icon_state = "white_suit"
+ item_state = "white_suit"
+ item_color = "white_suit"
+
+/obj/item/clothing/under/burial
+ name = "burial garments"
+ desc = "Traditional burial garments from the early 22nd century."
+ icon_state = "burial"
+ item_state = "burial"
+ item_color = "burial"
+ has_sensor = NO_SENSORS
+
+/obj/item/clothing/under/skirt/black
+ name = "black skirt"
+ desc = "A black skirt, very fancy!"
+ icon_state = "blackskirt"
+ item_color = "blackskirt"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/skirt/blue
+ name = "blue skirt"
+ desc = "A blue, casual skirt."
+ icon_state = "blueskirt"
+ item_color = "blueskirt"
+ item_state = "b_suit"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/skirt/red
+ name = "red skirt"
+ desc = "A red, casual skirt."
+ icon_state = "redskirt"
+ item_color = "redskirt"
+ item_state = "r_suit"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/skirt/purple
+ name = "purple skirt"
+ desc = "A purple, casual skirt."
+ icon_state = "purpleskirt"
+ item_color = "purpleskirt"
+ item_state = "p_suit"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+
+/obj/item/clothing/under/schoolgirl
+ name = "blue schoolgirl uniform"
+ desc = "It's just like one of my Japanese animes!"
+ icon_state = "schoolgirl"
+ item_state = "schoolgirl"
+ item_color = "schoolgirl"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/schoolgirl/red
+ name = "red schoolgirl uniform"
+ icon_state = "schoolgirlred"
+ item_state = "schoolgirlred"
+ item_color = "schoolgirlred"
+
+/obj/item/clothing/under/schoolgirl/green
+ name = "green schoolgirl uniform"
+ icon_state = "schoolgirlgreen"
+ item_state = "schoolgirlgreen"
+ item_color = "schoolgirlgreen"
+
+/obj/item/clothing/under/schoolgirl/orange
+ name = "orange schoolgirl uniform"
+ icon_state = "schoolgirlorange"
+ item_state = "schoolgirlorange"
+ item_color = "schoolgirlorange"
+
+/obj/item/clothing/under/overalls
+ name = "laborer's overalls"
+ desc = "A set of durable overalls for getting the job done."
+ icon_state = "overalls"
+ item_state = "lb_suit"
+ item_color = "overalls"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/pirate
+ name = "pirate outfit"
+ desc = "Yarr."
+ icon_state = "pirate"
+ item_state = "pirate"
+ item_color = "pirate"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/soviet
+ name = "soviet uniform"
+ desc = "For the Motherland!"
+ icon_state = "soviet"
+ item_state = "soviet"
+ item_color = "soviet"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/redcoat
+ name = "redcoat uniform"
+ desc = "Looks old."
+ icon_state = "redcoat"
+ item_state = "redcoat"
+ item_color = "redcoat"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/kilt
+ name = "kilt"
+ desc = "Includes shoes and plaid."
+ icon_state = "kilt"
+ item_state = "kilt"
+ item_color = "kilt"
+ body_parts_covered = CHEST|GROIN|LEGS|FEET
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/kilt/highlander
+ desc = "You're the only one worthy of this kilt."
+ item_flags = NODROP
+
+/obj/item/clothing/under/sexymime
+ name = "sexy mime outfit"
+ desc = "The only time when you DON'T enjoy looking at someone's rack."
+ icon_state = "sexymime"
+ item_state = "sexymime"
+ item_color = "sexymime"
+ body_parts_covered = CHEST|GROIN|LEGS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/gladiator
+ name = "gladiator uniform"
+ desc = "Are you not entertained? Is that not why you are here?"
+ icon_state = "gladiator"
+ item_state = "gladiator"
+ item_color = "gladiator"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = NO_FEMALE_UNIFORM
+ can_adjust = FALSE
+ resistance_flags = NONE
+
+/obj/item/clothing/under/gladiator/ash_walker
+ desc = "This gladiator uniform appears to be covered in ash and fairly dated."
+ has_sensor = NO_SENSORS
+
+/obj/item/clothing/under/sundress
+ name = "sundress"
+ desc = "Makes you want to frolic in a field of daisies."
+ icon_state = "sundress"
+ item_state = "sundress"
+ item_color = "sundress"
+ body_parts_covered = CHEST|GROIN
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/captainparade
+ name = "captain's parade uniform"
+ desc = "A captain's luxury-wear, for special occasions."
+ icon_state = "captain_parade"
+ item_state = "by_suit"
+ item_color = "captain_parade"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/hosparademale
+ name = "head of security's parade uniform"
+ desc = "A male head of security's luxury-wear, for special occasions."
+ icon_state = "hos_parade_male"
+ item_state = "r_suit"
+ item_color = "hos_parade_male"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/hosparadefem
+ name = "head of security's parade uniform"
+ desc = "A female head of security's luxury-wear, for special occasions."
+ icon_state = "hos_parade_fem"
+ item_state = "r_suit"
+ item_color = "hos_parade_fem"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/assistantformal
+ name = "assistant's formal uniform"
+ desc = "An assistant's formal-wear. Why an assistant needs formal-wear is still unknown."
+ icon_state = "assistant_formal"
+ item_state = "gy_suit"
+ item_color = "assistant_formal"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/blacktango
+ name = "black tango dress"
+ desc = "Filled with Latin fire."
+ icon_state = "black_tango"
+ item_state = "wcoat"
+ item_color = "black_tango"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+ body_parts_covered = CHEST|GROIN
+
+/obj/item/clothing/under/stripeddress
+ name = "striped dress"
+ desc = "Fashion in space."
+ icon_state = "striped_dress"
+ item_state = "stripeddress"
+ item_color = "striped_dress"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_FULL
+ can_adjust = FALSE
+
+/obj/item/clothing/under/sailordress
+ name = "sailor dress"
+ desc = "Formal wear for a leading lady."
+ icon_state = "sailor_dress"
+ item_state = "sailordress"
+ item_color = "sailor_dress"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/redeveninggown
+ name = "red evening gown"
+ desc = "Fancy dress for space bar singers."
+ icon_state = "red_evening_gown"
+ item_state = "redeveninggown"
+ item_color = "red_evening_gown"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/maid
+ name = "maid costume"
+ desc = "Maid in China."
+ icon_state = "maid"
+ item_state = "maid"
+ item_color = "maid"
+ body_parts_covered = CHEST|GROIN
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/maid/Initialize()
+ . = ..()
+ var/obj/item/clothing/accessory/maidapron/A = new (src)
+ attach_accessory(A)
+
+/obj/item/clothing/under/janimaid
+ name = "maid uniform"
+ desc = "A simple maid uniform for housekeeping."
+ icon_state = "janimaid"
+ item_state = "janimaid"
+ item_color = "janimaid"
+ body_parts_covered = CHEST|GROIN
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/plaid_skirt
+ name = "red plaid skirt"
+ desc = "A preppy red skirt with a white blouse."
+ icon_state = "plaid_red"
+ item_state = "plaid_red"
+ item_color = "plaid_red"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = TRUE
+ alt_covers_chest = TRUE
+
+/obj/item/clothing/under/plaid_skirt/blue
+ name = "blue plaid skirt"
+ desc = "A preppy blue skirt with a white blouse."
+ icon_state = "plaid_blue"
+ item_state = "plaid_blue"
+ item_color = "plaid_blue"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = TRUE
+ alt_covers_chest = TRUE
+
+/obj/item/clothing/under/plaid_skirt/purple
+ name = "purple plaid skirt"
+ desc = "A preppy purple skirt with a white blouse."
+ icon_state = "plaid_purple"
+ item_state = "plaid_purple"
+ item_color = "plaid_purple"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = TRUE
+ alt_covers_chest = TRUE
+
+/obj/item/clothing/under/singery
+ name = "yellow performer's outfit"
+ desc = "Just looking at this makes you want to sing."
+ icon_state = "ysing"
+ item_state = "ysing"
+ item_color = "ysing"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = NO_FEMALE_UNIFORM
+ alternate_worn_layer = ABOVE_SHOES_LAYER
+ can_adjust = FALSE
+
+/obj/item/clothing/under/singerb
+ name = "blue performer's outfit"
+ desc = "Just looking at this makes you want to sing."
+ icon_state = "bsing"
+ item_state = "bsing"
+ item_color = "bsing"
+ body_parts_covered = CHEST|GROIN|ARMS
+ alternate_worn_layer = ABOVE_SHOES_LAYER
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/plaid_skirt/green
+ name = "green plaid skirt"
+ desc = "A preppy green skirt with a white blouse."
+ icon_state = "plaid_green"
+ item_state = "plaid_green"
+ item_color = "plaid_green"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = TRUE
+ alt_covers_chest = TRUE
+
+/obj/item/clothing/under/jester
+ name = "jester suit"
+ desc = "A jolly dress, well suited to entertain your master, nuncle."
+ icon_state = "jester"
+ item_color = "jester"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/jester/alt
+ icon_state = "jester2"
+
+/obj/item/clothing/under/geisha
+ name = "geisha suit"
+ desc = "Cute space ninja senpai not included."
+ icon_state = "geisha"
+ item_color = "geisha"
+ body_parts_covered = CHEST|GROIN|ARMS
+ can_adjust = FALSE
+
+/obj/item/clothing/under/villain
+ name = "villain suit"
+ desc = "A change of wardrobe is necessary if you ever want to catch a real superhero."
+ icon_state = "villain"
+ item_color = "villain"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/sailor
+ name = "sailor suit"
+ desc = "Skipper's in the wardroom drinkin gin'."
+ icon_state = "sailor"
+ item_state = "b_suit"
+ item_color = "sailor"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/plasmaman
+ name = "plasma envirosuit"
+ desc = "A special containment suit that allows plasma-based lifeforms to exist safely in an oxygenated environment, and automatically extinguishes them in a crisis. Despite being airtight, it's not spaceworthy."
+ icon_state = "plasmaman"
+ item_state = "plasmaman"
+ item_color = "plasmaman"
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95)
+ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ can_adjust = FALSE
+ strip_delay = 80
+ var/next_extinguish = 0
+ var/extinguish_cooldown = 100
+ var/extinguishes_left = 5
+
+
+/obj/item/clothing/under/plasmaman/examine(mob/user)
+ ..()
+ to_chat(user, "There are [extinguishes_left] extinguisher charges left in this suit.")
+
+
+/obj/item/clothing/under/plasmaman/proc/Extinguish(mob/living/carbon/human/H)
+ if(!istype(H))
+ return
+
+ if(H.on_fire)
+ if(extinguishes_left)
+ if(next_extinguish > world.time)
+ return
+ next_extinguish = world.time + extinguish_cooldown
+ extinguishes_left--
+ H.visible_message("[H]'s suit automatically extinguishes [H.p_them()]!","Your suit automatically extinguishes you.")
+ H.ExtinguishMob()
+ new /obj/effect/particle_effect/water(get_turf(H))
+ return 0
+
+/obj/item/clothing/under/plasmaman/attackby(obj/item/E, mob/user, params)
+ ..()
+ if (istype(E, /obj/item/extinguisher_refill))
+ if (extinguishes_left == 5)
+ to_chat(user, "The inbuilt extinguisher is full.")
+ return
+ else
+ extinguishes_left = 5
+ to_chat(user, "You refill the suit's built-in extinguisher, using up the cartridge.")
+ qdel(E)
+ return
+ return
+ return
+
+/obj/item/extinguisher_refill
+ name = "envirosuit extinguisher cartridge"
+ desc = "A cartridge loaded with a compressed extinguisher mix, used to refill the automatic extinguisher on plasma envirosuits."
+ icon_state = "plasmarefill"
+ icon = 'icons/obj/device.dmi'
+
+/obj/item/clothing/under/rank/security/navyblue/russian
+ name = "\improper Russian officer's uniform"
+ desc = "The latest in fashionable russian outfits."
+ icon_state = "hostanclothes"
+ item_state = "hostanclothes"
+ item_color = "hostanclothes"
+
+/obj/item/clothing/under/mummy
+ name = "mummy wrapping"
+ desc = "Return the slab or suffer my stale references."
+ icon_state = "mummy"
+ item_state = "mummy"
+ item_color = "mummy"
+ body_parts_covered = CHEST|GROIN|ARMS|LEGS
+ fitted = NO_FEMALE_UNIFORM
+ can_adjust = FALSE
+ resistance_flags = NONE
+
+/obj/item/clothing/under/scarecrow
+ name = "scarecrow clothes"
+ desc = "Perfect camouflage for hiding in botany."
+ icon_state = "scarecrow"
+ item_state = "scarecrow"
+ item_color = "scarecrow"
+ body_parts_covered = CHEST|GROIN|ARMS|LEGS
+ fitted = NO_FEMALE_UNIFORM
+ can_adjust = FALSE
+ resistance_flags = NONE
+
+/obj/item/clothing/under/draculass
+ name = "draculass coat"
+ desc = "A dress inspired by the ancient \"Victorian\" era."
+ icon_state = "draculass"
+ item_state = "draculass"
+ item_color = "draculass"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
+
+/obj/item/clothing/under/drfreeze
+ name = "doctor freeze's jumpsuit"
+ desc = "A modified scientist jumpsuit to look extra cool."
+ icon_state = "drfreeze"
+ item_state = "drfreeze"
+ item_color = "drfreeze"
+ can_adjust = FALSE
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
+
+/obj/item/clothing/under/lobster
+ name = "foam lobster suit"
+ desc = "Who beheaded the college mascot?"
+ icon_state = "lobster"
+ item_state = "lobster"
+ item_color = "lobster"
+ fitted = NO_FEMALE_UNIFORM
+ can_adjust = FALSE
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
+
+/obj/item/clothing/under/gondola
+ name = "gondola hide suit"
+ desc = "Now you're cooking."
+ icon_state = "gondola"
+ item_state = "lb_suit"
+ item_color = "gondola"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/skeleton
+ name = "skeleton jumpsuit"
+ desc = "A black jumpsuit with a white bone pattern printed on it. Spooky!"
+ icon_state = "skeleton"
+ item_state = "skeleton"
+ item_color = "skeleton"
+ body_parts_covered = CHEST|GROIN|ARMS|LEGS
+ fitted = NO_FEMALE_UNIFORM
+ can_adjust = FALSE
+ resistance_flags = NONE
+
+/obj/item/clothing/under/gear_harness
+ name = "gear harness"
+ desc = "A simple, inconspicuous harness replacement for a jumpsuit."
+ icon_state = "gear_harness"
+ item_state = "gear_harness" //We dont use golem do to being a item, item without faces making it default to error suit sprites.
+ body_parts_covered = CHEST|GROIN
\ No newline at end of file
diff --git a/code/modules/crafting/craft.dm b/code/modules/crafting/craft.dm
index ba2a27af77..3e96512bb8 100644
--- a/code/modules/crafting/craft.dm
+++ b/code/modules/crafting/craft.dm
@@ -21,7 +21,7 @@
CAT_BURGER,
CAT_CAKE,
CAT_EGG,
- CAT_SUSHI, //Called Fish
+ CAT_FISH,
CAT_ICE, //Called Frozen
CAT_MEAT,
CAT_MISCFOOD,
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
index dbff7988c1..a76be1ff45 100644
--- a/code/modules/crafting/recipes.dm
+++ b/code/modules/crafting/recipes.dm
@@ -365,28 +365,6 @@
parts = list(/obj/item/camera = 1)
category = CAT_MISC
-/datum/crafting_recipe/lizardhat
- name = "Lizard Cloche Hat"
- result = /obj/item/clothing/head/lizard
- time = 10
- reqs = list(/obj/item/organ/tail/lizard = 1)
- category = CAT_MISC
-
-/datum/crafting_recipe/lizardhat_alternate
- name = "Lizard Cloche Hat"
- result = /obj/item/clothing/head/lizard
- time = 10
- reqs = list(/obj/item/stack/sheet/animalhide/lizard = 1)
- category = CAT_MISC
-
-/datum/crafting_recipe/kittyears
- name = "Kitty Ears"
- result = /obj/item/clothing/head/kitty/genuine
- time = 10
- reqs = list(/obj/item/organ/tail/cat = 1,
- /obj/item/organ/ears/cat = 1)
- category = CAT_MISC
-
/datum/crafting_recipe/skateboard
name = "Skateboard"
result = /obj/vehicle/ridden/scooter/skateboard
@@ -641,6 +619,15 @@
/obj/item/assembly/igniter = 1)
category = CAT_MISC
+
+/datum/crafting_recipe/wheelchair
+ name = "Wheelchair"
+ result = /obj/vehicle/ridden/wheelchair
+ reqs = list(/obj/item/stack/sheet/plasteel = 2,
+ /obj/item/stack/rods = 8)
+ time = 100
+ category = CAT_MISC
+
/datum/crafting_recipe/rcl
name = "Makeshift Rapid Cable Layer"
result = /obj/item/twohanded/rcl/ghetto
@@ -672,6 +659,28 @@
tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
category = CAT_MISC
+/datum/crafting_recipe/lizardhat
+ name = "Lizard Cloche Hat"
+ result = /obj/item/clothing/head/lizard
+ time = 10
+ reqs = list(/obj/item/organ/tail/lizard = 1)
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/lizardhat_alternate
+ name = "Lizard Cloche Hat"
+ result = /obj/item/clothing/head/lizard
+ time = 10
+ reqs = list(/obj/item/stack/sheet/animalhide/lizard = 1)
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/kittyears
+ name = "Kitty Ears"
+ result = /obj/item/clothing/head/kitty/genuine
+ time = 10
+ reqs = list(/obj/item/organ/tail/cat = 1,
+ /obj/item/organ/ears/cat = 1)
+ category = CAT_CLOTHING
+
/datum/crafting_recipe/hudsunsec
name = "Security HUDsunglasses"
result = /obj/item/clothing/glasses/hud/security/sunglasses
@@ -781,3 +790,36 @@
/datum/reagent/water = 15)
time = 40
category = CAT_MISC
+
+/datum/crafting_recipe/smartdart
+ name = "Medical smartdart"
+ result = /obj/item/reagent_containers/syringe/dart
+ reqs = list(/obj/item/stack/sheet/metal = 1,
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/stack/sheet/plastic = 1)
+ time = 10
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
+
+/datum/crafting_recipe/medolier
+ name = "Medolier"
+ result = /obj/item/storage/belt/medolier
+ reqs = list(/obj/item/stack/sheet/metal = 2,
+ /obj/item/stack/sheet/cloth = 3,
+ /obj/item/stack/sheet/plastic = 4)
+ time = 30
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
+
+/datum/crafting_recipe/smartdartgun
+ name = "Smart dartgun"
+ result = /obj/item/gun/syringe/dart
+ reqs = list(/obj/item/stack/sheet/metal = 15,
+ /obj/item/stack/sheet/glass = 10,
+ /obj/item/tank/internals = 1,
+ /obj/item/reagent_containers/glass/beaker = 1,
+ /obj/item/stack/sheet/plastic = 10,
+ /obj/item/stack/cable_coil = 2)
+ time = 150 //It's a gun
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm
index a6b7de0330..64edd69e17 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/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
index deba080ca2..483055cb0d 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
@@ -15,6 +15,7 @@
var/max_n_of_items = 1500
var/allow_ai_retrieve = FALSE
var/list/initial_contents
+ var/visible_contents = TRUE
/obj/machinery/smartfridge/Initialize()
. = ..()
@@ -37,11 +38,21 @@
update_icon()
/obj/machinery/smartfridge/update_icon()
- var/startstate = initial(icon_state)
if(!stat)
- icon_state = startstate
+ if(visible_contents)
+ switch(contents.len)
+ if(0)
+ icon_state = "[initial(icon_state)]"
+ if(1 to 25)
+ icon_state = "[initial(icon_state)]1"
+ if(26 to 75)
+ icon_state = "[initial(icon_state)]2"
+ if(76 to INFINITY)
+ icon_state = "[initial(icon_state)]3"
+ else
+ icon_state = "[initial(icon_state)]"
else
- icon_state = "[startstate]-off"
+ icon_state = "[initial(icon_state)]-off"
@@ -50,7 +61,14 @@
********************/
/obj/machinery/smartfridge/attackby(obj/item/O, mob/user, params)
- if(default_deconstruction_screwdriver(user, "smartfridge_open", "smartfridge", O))
+ if(user.a_intent == INTENT_HARM)
+ return ..()
+
+ if(default_deconstruction_screwdriver(user, icon_state, icon_state, O))
+ cut_overlays()
+ if(panel_open)
+ add_overlay("[initial(icon_state)]-panel")
+ updateUsrDialog()
return
if(default_pry_open(O))
@@ -64,49 +82,46 @@
updateUsrDialog()
return
- if(!stat)
-
- if(contents.len >= max_n_of_items)
- to_chat(user, "\The [src] is full!")
- return FALSE
-
- if(accept_check(O))
- load(O)
- user.visible_message("[user] has added \the [O] to \the [src].", "You add \the [O] to \the [src].")
- updateUsrDialog()
- return TRUE
-
- if(istype(O, /obj/item/storage/bag))
- var/obj/item/storage/P = O
- var/loaded = 0
- for(var/obj/G in P.contents)
- if(contents.len >= max_n_of_items)
- break
- if(accept_check(G))
- load(G)
- loaded++
- updateUsrDialog()
-
- if(loaded)
- if(contents.len >= max_n_of_items)
- user.visible_message("[user] loads \the [src] with \the [O].", \
- "You fill \the [src] with \the [O].")
- else
- user.visible_message("[user] loads \the [src] with \the [O].", \
- "You load \the [src] with \the [O].")
- if(O.contents.len > 0)
- to_chat(user, "Some items are refused.")
- return TRUE
- else
- to_chat(user, "There is nothing in [O] to put in [src]!")
- return FALSE
-
- if(user.a_intent != INTENT_HARM)
- to_chat(user, "\The [src] smartly refuses [O].")
+ if(stat)
updateUsrDialog()
return FALSE
- else
- return ..()
+
+ if(contents.len >= max_n_of_items)
+ to_chat(user, "\The [src] is full!")
+ return FALSE
+
+ if(accept_check(O))
+ load(O)
+ user.visible_message("[user] has added \the [O] to \the [src].", "You add \the [O] to \the [src].")
+ updateUsrDialog()
+ if (visible_contents)
+ update_icon()
+ return TRUE
+
+ if(istype(O, /obj/item/storage/bag))
+ var/obj/item/storage/P = O
+ var/loaded = 0
+ for(var/obj/G in P.contents)
+ if(contents.len >= max_n_of_items)
+ break
+ if(accept_check(G))
+ load(G)
+ loaded++
+ updateUsrDialog()
+
+ if(loaded)
+ user.visible_message("[user] loads \the [src] with \the [O].", \
+ "You [contents.len >= max_n_of_items ? "fill" : "load"] \the [src] with \the [O].")
+ if(O.contents.len > 0)
+ to_chat(user, "Some items are refused.")
+ return TRUE
+ else
+ to_chat(user, "There is nothing in [O] to put in [src]!")
+ return FALSE
+
+ to_chat(user, "\The [src] smartly refuses [O].")
+ updateUsrDialog()
+ return FALSE
@@ -186,6 +201,8 @@
O.forceMove(drop_location())
adjust_item_drop_location(O)
break
+ if (visible_contents)
+ update_icon()
return TRUE
for(var/obj/item/O in src)
@@ -195,6 +212,8 @@
O.forceMove(drop_location())
adjust_item_drop_location(O)
desired--
+ if (visible_contents)
+ update_icon()
return TRUE
return FALSE
@@ -210,6 +229,7 @@
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 200
+ visible_contents = FALSE
var/drying = FALSE
/obj/machinery/smartfridge/drying_rack/Initialize()
@@ -414,6 +434,7 @@
name = "disk compartmentalizer"
desc = "A machine capable of storing a variety of disks. Denoted by most as the DSU (disk storage unit)."
icon_state = "disktoaster"
+ visible_contents = FALSE
pass_flags = PASSTABLE
/obj/machinery/smartfridge/disks/accept_check(obj/item/O)
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/food_and_drinks/recipes/tablecraft/recipes_meat.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm
index c16c7268b9..7eff2820c5 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm
@@ -38,37 +38,6 @@
// see code/module/crafting/table.dm
-////////////////////////////////////////////////FISH////////////////////////////////////////////////
-
-/datum/crafting_recipe/food/cubancarp
- name = "Cuban carp"
- reqs = list(
- /datum/reagent/consumable/flour = 5,
- /obj/item/reagent_containers/food/snacks/grown/chili = 1,
- /obj/item/reagent_containers/food/snacks/carpmeat = 1
- )
- result = /obj/item/reagent_containers/food/snacks/cubancarp
- subcategory = CAT_MEAT
-
-/datum/crafting_recipe/food/fishandchips
- name = "Fish and chips"
- reqs = list(
- /obj/item/reagent_containers/food/snacks/fries = 1,
- /obj/item/reagent_containers/food/snacks/carpmeat = 1
- )
- result = /obj/item/reagent_containers/food/snacks/fishandchips
- subcategory = CAT_MEAT
-
-/datum/crafting_recipe/food/fishfingers
- name = "Fish fingers"
- reqs = list(
- /datum/reagent/consumable/flour = 5,
- /obj/item/reagent_containers/food/snacks/bun = 1,
- /obj/item/reagent_containers/food/snacks/carpmeat = 1
- )
- result = /obj/item/reagent_containers/food/snacks/fishfingers
- subcategory = CAT_MEAT
-
////////////////////////////////////////////////MR SPIDER////////////////////////////////////////////////
/datum/crafting_recipe/food/spidereggsham
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
index 4b76ca120b..2246d12df4 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
@@ -22,7 +22,7 @@
)
result = /obj/item/reagent_containers/food/snacks/donut
subcategory = CAT_PASTRY
-
+
/datum/crafting_recipe/food/donut
time = 15
name = "Semen donut"
@@ -104,7 +104,7 @@ datum/crafting_recipe/food/donut/meat
/datum/crafting_recipe/food/rofflewaffles
name = "Roffle waffles"
reqs = list(
- /datum/reagent/mushroomhallucinogen = 5,
+ /datum/reagent/drug/mushroomhallucinogen = 5,
/obj/item/reagent_containers/food/snacks/pastrybase = 2
)
result = /obj/item/reagent_containers/food/snacks/rofflewaffles
@@ -205,16 +205,6 @@ datum/crafting_recipe/food/donut/meat
////////////////////////////////////////////OTHER////////////////////////////////////////////
-/datum/crafting_recipe/food/hotdog
- name = "Hot dog"
- reqs = list(
- /datum/reagent/consumable/ketchup = 5,
- /obj/item/reagent_containers/food/snacks/bun = 1,
- /obj/item/reagent_containers/food/snacks/sausage = 1
- )
- result = /obj/item/reagent_containers/food/snacks/hotdog
- subcategory = CAT_PASTRY
-
/datum/crafting_recipe/food/meatbun
name = "Meat bun"
reqs = list(
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_sandwich.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_sandwich.dm
index 0f1c40da3f..133713ac75 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_sandwich.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_sandwich.dm
@@ -52,7 +52,7 @@
result = /obj/item/reagent_containers/food/snacks/notasandwich
subcategory = CAT_SANDWICH
-/datum/crafting_recipe/food/notasandwich
+/datum/crafting_recipe/food/tunasandwich
name = "Tuna sandwich"
reqs = list(
/obj/item/reagent_containers/food/snacks/breadslice/plain = 2,
@@ -62,3 +62,13 @@
)
result = /obj/item/reagent_containers/food/snacks/tuna_sandwich
subcategory = CAT_SANDWICH
+
+/datum/crafting_recipe/food/hotdog
+ name = "Hot dog"
+ reqs = list(
+ /datum/reagent/consumable/ketchup = 5,
+ /obj/item/reagent_containers/food/snacks/bun = 1,
+ /obj/item/reagent_containers/food/snacks/sausage = 1
+ )
+ result = /obj/item/reagent_containers/food/snacks/hotdog
+ subcategory = CAT_SANDWICH
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_sushi.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_sushi.dm
index 99d48cf69d..9dbf1d684b 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_sushi.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_sushi.dm
@@ -7,7 +7,7 @@
/datum/reagent/consumable/rice = 10
)
result = /obj/item/reagent_containers/food/snacks/sushi_rice
- subcategory = CAT_SUSHI
+ subcategory = CAT_FISH
/datum/crafting_recipe/food/sea_weed
name = "Sea Weed Sheet"
@@ -17,7 +17,7 @@
/obj/item/reagent_containers/food/snacks/grown/kudzupod = 1,
)
result = /obj/item/reagent_containers/food/snacks/sea_weed
- subcategory = CAT_SUSHI
+ subcategory = CAT_FISH
/datum/crafting_recipe/food/tuna_can
name = "Can of Tuna"
@@ -27,7 +27,7 @@
/obj/item/reagent_containers/food/snacks/carpmeat = 1,
)
result = /obj/item/reagent_containers/food/snacks/tuna
- subcategory = CAT_SUSHI
+ subcategory = CAT_FISH
//////////////////////////Sushi/////////////////////////////////
@@ -39,7 +39,7 @@
/obj/item/reagent_containers/food/snacks/carpmeat = 1
)
result = /obj/item/reagent_containers/food/snacks/sashimi
- subcategory = CAT_SUSHI
+ subcategory = CAT_FISH
/datum/crafting_recipe/food/riceball
name = "Onigiri"
@@ -49,7 +49,7 @@
/obj/item/reagent_containers/food/snacks/sushi_rice = 1
)
result = /obj/item/reagent_containers/food/snacks/riceball
- subcategory = CAT_SUSHI
+ subcategory = CAT_FISH
/datum/crafting_recipe/food/sushie_egg
name = "Tobiko"
@@ -59,7 +59,7 @@
/obj/item/reagent_containers/food/snacks/sea_weed = 2,
)
result = /obj/item/reagent_containers/food/snacks/tobiko
- subcategory = CAT_SUSHI
+ subcategory = CAT_FISH
/datum/crafting_recipe/food/sushie_basic
name = "Funa Hosomaki"
@@ -70,7 +70,7 @@
/obj/item/reagent_containers/food/snacks/sea_weed = 3,
)
result = /obj/item/reagent_containers/food/snacks/sushie_basic
- subcategory = CAT_SUSHI
+ subcategory = CAT_FISH
/datum/crafting_recipe/food/sushie_adv
name = "Funa Nigiri"
@@ -80,7 +80,7 @@
/obj/item/reagent_containers/food/snacks/carpmeat = 1
)
result = /obj/item/reagent_containers/food/snacks/sushie_adv
- subcategory = CAT_SUSHI
+ subcategory = CAT_FISH
/datum/crafting_recipe/food/sushie_pro
name = "Well made Funa Nigiri"
@@ -91,4 +91,35 @@
/obj/item/reagent_containers/food/snacks/sea_weed = 1
)
result = /obj/item/reagent_containers/food/snacks/sushie_pro
- subcategory = CAT_SUSHI
+ subcategory = CAT_FISH
+
+///////////////Gaijin junk/////////////////////////////////////
+
+/datum/crafting_recipe/food/fishfingers
+ name = "Fish fingers"
+ reqs = list(
+ /datum/reagent/consumable/flour = 5,
+ /obj/item/reagent_containers/food/snacks/bun = 1,
+ /obj/item/reagent_containers/food/snacks/carpmeat = 1
+ )
+ result = /obj/item/reagent_containers/food/snacks/fishfingers
+ subcategory = CAT_FISH
+
+/datum/crafting_recipe/food/cubancarp
+ name = "Cuban carp"
+ reqs = list(
+ /datum/reagent/consumable/flour = 5,
+ /obj/item/reagent_containers/food/snacks/grown/chili = 1,
+ /obj/item/reagent_containers/food/snacks/carpmeat = 1
+ )
+ result = /obj/item/reagent_containers/food/snacks/cubancarp
+ subcategory = CAT_FISH
+
+/datum/crafting_recipe/food/fishandchips
+ name = "Fish and chips"
+ reqs = list(
+ /obj/item/reagent_containers/food/snacks/fries = 1,
+ /obj/item/reagent_containers/food/snacks/carpmeat = 1
+ )
+ result = /obj/item/reagent_containers/food/snacks/fishandchips
+ subcategory = CAT_FISH
\ No newline at end of file
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/goonchat/browserassets/js/browserOutput.js b/code/modules/goonchat/browserassets/js/browserOutput.js
index 64b41a5921..33553d765e 100644
--- a/code/modules/goonchat/browserassets/js/browserOutput.js
+++ b/code/modules/goonchat/browserassets/js/browserOutput.js
@@ -471,15 +471,6 @@ function ehjaxCallback(data) {
handleClientData(data.clientData.ckey, data.clientData.ip, data.clientData.compid);
}
sendVolumeUpdate();
- } else if (data.firebug) {
- if (data.trigger) {
- internalOutput('Loading firebug console, triggered by '+data.trigger+'...', 'internal');
- } else {
- internalOutput('Loading firebug console...', 'internal');
- }
- var firebugEl = document.createElement('script');
- firebugEl.src = 'https://getfirebug.com/firebug-lite-debug.js';
- document.body.appendChild(firebugEl);
} else if (data.adminMusic) {
if (typeof data.adminMusic === 'string') {
var adminMusic = byondDecode(data.adminMusic);
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 eb7756514a..ef58943731 100644
--- a/code/modules/library/lib_machines.dm
+++ b/code/modules/library/lib_machines.dm
@@ -488,11 +488,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/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 0990ca961a..eaac1984e3 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -273,23 +273,12 @@
to_chat(user, "You release the wisp. It begins to bob around your head.")
icon_state = "lantern"
wisp.orbit(user, 20)
- user.update_sight()
SSblackbox.record_feedback("tally", "wisp_lantern", 1, "Freed")
else
to_chat(user, "You return the wisp to the lantern.")
-
- var/mob/target
- if(wisp.orbiting)
- target = wisp.orbiting.orbiting
- wisp.stop_orbit()
- wisp.forceMove(src)
-
- if (istype(target))
- target.update_sight()
- to_chat(target, "Your vision returns to normal.")
-
icon_state = "lantern-blue"
+ wisp.forceMove(src)
SSblackbox.record_feedback("tally", "wisp_lantern", 1, "Returned")
/obj/item/wisp_lantern/Initialize()
@@ -302,7 +291,7 @@
qdel(wisp)
else
wisp.visible_message("[wisp] has a sad feeling for a moment, then it passes.")
- ..()
+ return ..()
/obj/effect/wisp
name = "friendly wisp"
@@ -314,6 +303,25 @@
var/sight_flags = SEE_MOBS
var/lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
+/obj/effect/wisp/orbit(atom/thing, radius, clockwise, rotation_speed, rotation_segments, pre_rotation, lockinorbit)
+ . = ..()
+ if(ismob(thing))
+ RegisterSignal(thing, COMSIG_MOB_UPDATE_SIGHT, .proc/update_user_sight)
+ var/mob/being = thing
+ being.update_sight()
+ to_chat(thing, "The wisp enhances your vision.")
+
+/obj/effect/wisp/stop_orbit(datum/component/orbiter/orbits)
+ . = ..()
+ if(ismob(orbits.parent))
+ UnregisterSignal(orbits.parent, COMSIG_MOB_UPDATE_SIGHT)
+ to_chat(orbits.parent, "Your vision returns to normal.")
+
+/obj/effect/wisp/proc/update_user_sight(mob/user)
+ user.sight |= sight_flags
+ if(!isnull(lighting_alpha))
+ user.lighting_alpha = min(user.lighting_alpha, lighting_alpha)
+
//Red/Blue Cubes
/obj/item/warp_cube
name = "blue cube"
@@ -781,19 +789,17 @@
var/turf/T = get_turf(src)
var/list/contents = T.GetAllContents()
var/mob/dead/observer/current_spirits = list()
- var/list/orbiters = list()
for(var/thing in contents)
var/atom/A = thing
- if (A.orbiters)
- orbiters += A.orbiters
+ A.transfer_observers_to(src)
- for(var/thing in orbiters)
- var/datum/orbit/O = thing
- if (isobserver(O.orbiter))
- var/mob/dead/observer/G = O.orbiter
- ghost_counter++
- G.invisibility = 0
- current_spirits |= G
+ for(var/i in orbiters?.orbiters)
+ if(!isobserver(i))
+ continue
+ var/mob/dead/observer/G = i
+ ghost_counter++
+ G.invisibility = 0
+ current_spirits |= G
for(var/mob/dead/observer/G in spirits - current_spirits)
G.invisibility = GLOB.observer_default_invisibility
diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm
index 883f5a034f..c780d57810 100644
--- a/code/modules/mob/camera/camera.dm
+++ b/code/modules/mob/camera/camera.dm
@@ -26,7 +26,9 @@
return
/mob/camera/forceMove(atom/destination)
+ var/oldloc = loc
loc = destination
+ Moved(oldloc, NONE, TRUE)
/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE)
return
diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm
index d886a41b0f..381dc131e7 100644
--- a/code/modules/mob/dead/dead.dm
+++ b/code/modules/mob/dead/dead.dm
@@ -34,7 +34,9 @@ INITIALIZE_IMMEDIATE(/mob/dead)
var/turf/new_turf = get_turf(destination)
if (old_turf?.z != new_turf?.z)
onTransitZ(old_turf?.z, new_turf?.z)
+ var/oldloc = loc
loc = destination
+ Moved(oldloc, NONE, TRUE)
/mob/dead/Stat()
..()
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 5a5d37d4e7..3384f3754b 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/socks.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/socks.dm
@@ -11,6 +11,10 @@
// please make sure they're sorted alphabetically and categorized
+/datum/sprite_accessory/socks/bee_knee
+ name = "Knee-high (Bee)"
+ icon_state = "bee_knee"
+
/datum/sprite_accessory/socks/black_knee
name = "Knee-high (Black)"
icon_state = "black_knee"
@@ -63,6 +67,42 @@
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"
+
/datum/sprite_accessory/socks/black_thigh
name = "Thigh-high (Black)"
icon_state = "black_thigh"
@@ -93,4 +133,4 @@
/datum/sprite_accessory/socks/white_thigh
name = "Thigh-high (White)"
- icon_state = "white_thigh"
\ No newline at end of file
+ icon_state = "white_thigh"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/undershirt.dm b/code/modules/mob/dead/new_player/sprite_accessories/undershirt.dm
index 7c66ef51e3..f5af9a3849 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/undershirt.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/undershirt.dm
@@ -248,9 +248,13 @@
icon_state = "bra_commie"
/datum/sprite_accessory/undershirt/female_babyblue
- name = "Bra, Baby Blue"
+ name = "Bra - Baby Blue"
icon_state = "bra_babyblue"
+/datum/sprite_accessory/undershirt/female_beekini
+ name = "Bra - Bee-kini"
+ icon_state = "bra_bee-kini"
+
/datum/sprite_accessory/undershirt/female_black
name = "Bra - Black"
icon_state = "bra_black"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/underwear.dm b/code/modules/mob/dead/new_player/sprite_accessories/underwear.dm
index 6beed231aa..e7179eeb87 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/underwear.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/underwear.dm
@@ -90,6 +90,9 @@
name = "Boxer Briefs - Yellow"
icon_state = "boxer_briefs_yellow"
+/datum/sprite_accessory/underwear/female_beekini
+ name = "Panties - Bee-kini"
+ icon_state = "panties_bee-kini"
/datum/sprite_accessory/underwear/female_black
name = "Panties - Black"
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 55b8891534..fefa032e4f 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -429,9 +429,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/orbitsize = (I.Width()+I.Height())*0.5
orbitsize -= (orbitsize/world.icon_size)*(world.icon_size*0.25)
- if(orbiting && orbiting.orbiting != target)
- to_chat(src, "Now orbiting [target].")
-
var/rot_seg
switch(ghost_orbit)
@@ -450,10 +447,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/orbit()
setDir(2)//reset dir so the right directional sprites show up
- ..()
+ return ..()
-/mob/dead/observer/stop_orbit()
- ..()
+/mob/dead/observer/stop_orbit(datum/component/orbiter/orbits)
+ . = ..()
//restart our floating animation after orbit is done.
pixel_y = 0
animate(src, pixel_y = 2, time = 10, loop = -1)
@@ -753,7 +750,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
update_icon()
-/mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
return IsAdminGhost(usr)
/mob/dead/observer/is_literate()
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index fb09de7ec2..51ee5b372b 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -895,6 +895,11 @@
var/obj/item/organ/I = X
I.Insert(src)
+/mob/living/carbon/proc/update_disabled_bodyparts()
+ for(var/B in bodyparts)
+ var/obj/item/bodypart/BP = B
+ BP.update_disabled()
+
/mob/living/carbon/vv_get_dropdown()
. = ..()
. += "---"
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index d814893053..8550a0887f 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -294,7 +294,7 @@
if(mood.sanity <= SANITY_DISTURBED)
msg += "[t_He] seem[p_s()] distressed.\n"
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "empath", /datum/mood_event/sad_empath, src)
- if(mood.mood >= 5) //So roundstart people aren't all "happy"
+ if(mood.shown_mood >= 6) //So roundstart people aren't all "happy" and that antags don't show their true happiness.
msg += "[t_He] seem[p_s()] to have had something nice happen to them recently.\n"
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "empathH", /datum/mood_event/happy_empath, src)
if (HAS_TRAIT(src, TRAIT_BLIND))
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 129e600b00..a4fca9dd78 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -8,6 +8,7 @@
/mob/living/carbon/human/Initialize()
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
+ verbs += /mob/living/carbon/human/proc/underwear_toggle //fwee
//initialize limbs first
create_bodyparts()
@@ -724,12 +725,12 @@
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#000000")
cut_overlay(MA)
-/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated() || lying )
to_chat(src, "You can't do that right now!")
return FALSE
if(!Adjacent(M) && (M.loc != src))
- if((be_close == 0) || (dna.check_mutation(TK) && tkMaxRangeCheck(src, M)))
+ if((be_close == 0) || (!no_tk && (dna.check_mutation(TK) && tkMaxRangeCheck(src, M))))
return TRUE
to_chat(src, "You are too far away!")
return FALSE
@@ -855,13 +856,16 @@
buckle_mob(target,TRUE,TRUE)
. = ..()
+/mob/living/carbon/human/proc/piggyback_instant(mob/living/M)
+ return buckle_mob(M, TRUE, TRUE, FALSE, TRUE)
+
//Can C try to piggyback at all.
/mob/living/carbon/human/proc/can_piggyback(mob/living/carbon/C)
if(istype(C) && C.stat == CONSCIOUS)
return TRUE
return FALSE
-/mob/living/carbon/human/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE, bypass_piggybacking = FALSE)
+/mob/living/carbon/human/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE, bypass_piggybacking = FALSE, no_delay = FALSE)
if(!force)//humans are only meant to be ridden through piggybacking and special cases
return
if(bypass_piggybacking)
@@ -878,7 +882,7 @@
if(can_piggyback(M))
riding_datum.ride_check_ridden_incapacitated = TRUE
visible_message("[M] starts to climb onto [src]...")
- if(force || do_after(M, 15, target = src))
+ if(no_delay || do_after(M, 15, target = src))
if(can_piggyback(M))
if(M.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE))
M.visible_message("[M] can't hang onto [src]!")
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 2a75119841..b42346382f 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -54,7 +54,12 @@
else
visible_message("[src] deflects the projectile!", "You deflect the projectile!")
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1)
- return 0
+ if(!mind.martial_art.reroute_deflection)
+ return FALSE
+ else
+ P.firer = src
+ P.setAngle(rand(0, 360))//SHING
+ return FALSE
if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself
if(P.is_reflectable)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 62a4d42672..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()
@@ -490,11 +492,19 @@ GLOBAL_LIST_EMPTY(roundstart_races)
//Underwear, Undershirts & Socks
if(!(NO_UNDERWEAR in species_traits))
if(H.underwear)
+ if(H.hidden_underwear)
+ H.underwear = "Nude"
+ else
+ H.underwear = H.saved_underwear
var/datum/sprite_accessory/underwear/underwear = GLOB.underwear_list[H.underwear]
if(underwear)
standing += mutable_appearance(underwear.icon, underwear.icon_state, -BODY_LAYER)
if(H.undershirt)
+ if(H.hidden_undershirt)
+ H.undershirt = "Nude"
+ else
+ H.undershirt = H.saved_undershirt
var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[H.undershirt]
if(undershirt)
if(H.dna.species.sexes && H.gender == FEMALE)
@@ -503,6 +513,10 @@ GLOBAL_LIST_EMPTY(roundstart_races)
standing += mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER)
if(H.socks && H.get_num_legs(FALSE) >= 2)
+ if(H.hidden_socks)
+ H.socks = "Nude"
+ else
+ H.socks = H.saved_socks
var/datum/sprite_accessory/socks/socks = GLOB.socks_list[H.socks]
if(socks)
if(DIGITIGRADE in species_traits)
@@ -1288,7 +1302,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
. += H.physiology.speed_mod
if (H.m_intent == MOVE_INTENT_WALK && HAS_TRAIT(H, TRAIT_SPEEDY_STEP))
- . -= 1
+ . -= 1.5
if(HAS_TRAIT(H, TRAIT_IGNORESLOWDOWN))
ignoreslow = 1
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/life.dm b/code/modules/mob/living/carbon/life.dm
index 571775d541..b2eb83d668 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -654,6 +654,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
L.damage += d
/mob/living/carbon/proc/liver_failure()
+ reagents.end_metabolization(src, keep_liverless = TRUE) //Stops trait-based effects on reagents, to prevent permanent buffs
reagents.metabolize(src, can_overdose=FALSE, liverless = TRUE)
if(HAS_TRAIT(src, TRAIT_STABLEHEART))
return
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 69168caad1..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
@@ -814,7 +819,7 @@
/mob/living/proc/harvest(mob/living/user) //used for extra objects etc. in butchering
return
-/mob/living/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated())
to_chat(src, "You can't do that right now!")
return FALSE
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 46576a357f..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)
@@ -779,7 +788,7 @@
return TRUE
return ..()
-/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(control_disabled || incapacitated())
to_chat(src, "You can't do that right now!")
return FALSE
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 896d8674be..7fd861bfeb 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -183,7 +183,7 @@
// See software.dm for Topic()
-/mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(be_close && !in_range(M, src))
to_chat(src, "You are too far away!")
return FALSE
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 335645b17e..e71e269222 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -910,7 +910,7 @@
if(DISCONNECT) //Tampering with the wires
to_chat(connected_ai, "
NOTICE - Remote telemetry lost with [name]. ")
-/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(stat || lockcharge || low_power_mode)
to_chat(src, "You can't do that right now!")
return FALSE
diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm
index ff2bd7cf37..68c220ab2a 100644
--- a/code/modules/mob/living/simple_animal/bot/honkbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm
@@ -131,7 +131,6 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
. = ..()
if(emagged == 2)
if(user)
- user << "You short out [src]'s sound control system. It gives out an evil laugh!!"
oldtarget_name = user.name
audible_message("[src] gives out an evil laugh!")
playsound(src, 'sound/machines/honkbot_evil_laugh.ogg', 75, 1, -1) // evil laughter
diff --git a/code/modules/mob/living/simple_animal/friendly/panda.dm b/code/modules/mob/living/simple_animal/friendly/panda.dm
new file mode 100644
index 0000000000..a7b6143ef5
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/friendly/panda.dm
@@ -0,0 +1,20 @@
+/mob/living/simple_animal/pet/redpanda
+ name = "Red panda"
+ desc = "Wah't a dork."
+ icon = 'icons/mob/pets.dmi'
+ icon_state = "red_panda"
+ icon_living = "red_panda"
+ icon_dead = "dead_panda"
+ speak = list("Churip","Chuuriip","Cheep-cheep","Chiteurp","squueeaacipt")
+ speak_emote = list("chirps", "huff-quacks")
+ emote_hear = list("squeak-chrips.", "huff-squacks.")
+ emote_see = list("shakes its head.", "rolls about.")
+ speak_chance = 1
+ turns_per_move = 5
+ see_in_dark = 6
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3)
+ response_help = "pets"
+ response_disarm = "gently pushes aside"
+ response_harm = "kicks"
+ gold_core_spawnable = FRIENDLY_SPAWN
+ do_footstep = TRUE
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index 701e244f89..1a918766b6 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -596,6 +596,9 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
/obj/item/guardiancreator/tech/choose/traitor
possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
+/obj/item/guardiancreator/tech/choose/traitor/check_uplink_validity()
+ return !used
+
/obj/item/guardiancreator/tech/choose
random = FALSE
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 2517d2438d..1f81899d8a 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -392,7 +392,7 @@
if(target)
return new childspawn(target)
-/mob/living/simple_animal/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/simple_animal/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated())
to_chat(src, "You can't do that right now!")
return FALSE
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 7ff8fbc0b1..b098801da8 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -784,7 +784,7 @@
return 0
//Can the mob use Topic to interact with machines
-/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
return
/mob/proc/faction_check_mob(mob/target, exact_match)
@@ -871,13 +871,7 @@
return
/mob/proc/update_sight()
- for(var/O in orbiters)
- var/datum/orbit/orbit = O
- var/obj/effect/wisp/wisp = orbit.orbiter
- if (istype(wisp))
- sight |= wisp.sight_flags
- if(!isnull(wisp.lighting_alpha))
- lighting_alpha = min(lighting_alpha, wisp.lighting_alpha)
+ SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 33f1ec81c1..82e2b11f8e 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -148,7 +148,7 @@
if(INCORPOREAL_MOVE_BASIC)
var/T = get_step(L,direct)
if(T)
- L.loc = T
+ L.forceMove(T)
L.setDir(direct)
if(INCORPOREAL_MOVE_SHADOW)
if(prob(50))
@@ -190,7 +190,7 @@
new /obj/effect/temp_visual/dir_setting/ninja/shadow(mobloc, L.dir)
var/T = get_step(L,direct)
if(T)
- L.loc = T
+ L.forceMove(T)
L.setDir(direct)
if(INCORPOREAL_MOVE_JAUNT) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
var/turf/open/floor/stepTurf = get_step(L, direct)
@@ -209,7 +209,7 @@
to_chat(L, "Holy energies block your path!")
return
- L.loc = get_step(L, direct)
+ L.forceMove(stepTurf)
L.setDir(direct)
return TRUE
diff --git a/code/modules/modular_computers/computers/item/processor.dm b/code/modules/modular_computers/computers/item/processor.dm
index 20ad2214cf..99d648d02b 100644
--- a/code/modules/modular_computers/computers/item/processor.dm
+++ b/code/modules/modular_computers/computers/item/processor.dm
@@ -44,7 +44,7 @@
return machinery_computer.update_icon()
// This thing is not meant to be used on it's own, get topic data from our machinery owner.
-//obj/item/modular_computer/processor/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+//obj/item/modular_computer/processor/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
// if(!machinery_computer)
// return 0
diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm
index 0d61d1d132..b3476e7046 100644
--- a/code/modules/modular_computers/computers/machinery/modular_computer.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm
@@ -46,7 +46,7 @@
/obj/machinery/modular_computer/emag_act(mob/user)
. = ..()
if(cpu)
- return cpu.emag_act(user)
+ . |= cpu.emag_act(user)
/obj/machinery/modular_computer/update_icon()
cut_overlays()
diff --git a/code/modules/orbit/orbit.dm b/code/modules/orbit/orbit.dm
deleted file mode 100644
index 79685b9104..0000000000
--- a/code/modules/orbit/orbit.dm
+++ /dev/null
@@ -1,135 +0,0 @@
-/datum/orbit
- var/atom/movable/orbiter
- var/atom/orbiting
- var/lock = TRUE
- var/turf/lastloc
- var/lastprocess
-
-/datum/orbit/New(_orbiter, _orbiting, _lock)
- orbiter = _orbiter
- orbiting = _orbiting
- SSorbit.processing += src
- if (!orbiting.orbiters)
- orbiting.orbiters = list()
- orbiting.orbiters += src
-
- if (orbiter.orbiting)
- orbiter.stop_orbit()
- orbiter.orbiting = src
- Check()
- lock = _lock
-
-//do not qdel directly, use stop_orbit on the orbiter. (This way the orbiter can bind to the orbit stopping)
-/datum/orbit/Destroy(force = FALSE)
- SSorbit.processing -= src
- if (orbiter)
- orbiter.orbiting = null
- orbiter = null
- if (orbiting)
- if (orbiting.orbiters)
- orbiting.orbiters -= src
- if (!orbiting.orbiters.len)//we are the last orbit, delete the list
- orbiting.orbiters = null
- orbiting = null
- return ..()
-
-/datum/orbit/proc/Check(turf/targetloc, list/checked_already = list())
- //Avoid infinite loops for people who end up orbiting themself through another orbiter
- checked_already[src] = TRUE
- if (!orbiter)
- qdel(src)
- return
- if (!orbiting)
- orbiter.stop_orbit()
- return
- if (!orbiter.orbiting) //admin wants to stop the orbit.
- orbiter.orbiting = src //set it back to us first
- orbiter.stop_orbit()
- var/atom/movable/AM = orbiting
- if(istype(AM) && AM.orbiting && AM.orbiting.orbiting == orbiter)
- orbiter.stop_orbit()
- return
- lastprocess = world.time
- if (!targetloc)
- targetloc = get_turf(orbiting)
- if (!targetloc || (!lock && orbiter.loc != lastloc && orbiter.loc != targetloc))
- orbiter.stop_orbit()
- return
- var/turf/old_turf = get_turf(orbiter)
- var/turf/new_turf = get_turf(targetloc)
- if (old_turf?.z != new_turf?.z)
- orbiter.onTransitZ(old_turf?.z, new_turf?.z)
- // DO NOT PORT TO FORCEMOVE - MEMECODE WILL KILL MC
- orbiter.loc = targetloc
- orbiter.update_parallax_contents()
- orbiter.update_light()
- lastloc = orbiter.loc
- for(var/other_orbit in orbiter.orbiters)
- var/datum/orbit/OO = other_orbit
- //Skip if checked already
- if(checked_already[OO])
- continue
- OO.Check(targetloc, checked_already)
-
-/atom/movable/var/datum/orbit/orbiting = null
-/atom/var/list/orbiters = null
-
-//A: atom to orbit
-//radius: range to orbit at, radius of the circle formed by orbiting (in pixels)
-//clockwise: whether you orbit clockwise or anti clockwise
-//rotation_speed: how fast to rotate (how many ds should it take for a rotation to complete)
-//rotation_segments: the resolution of the orbit circle, less = a more block circle, this can be used to produce hexagons (6 segments) triangles (3 segments), and so on, 36 is the best default.
-//pre_rotation: Chooses to rotate src 90 degress towards the orbit dir (clockwise/anticlockwise), useful for things to go "head first" like ghosts
-//lockinorbit: Forces src to always be on A's turf, otherwise the orbit cancels when src gets too far away (eg: ghosts)
-
-/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = FALSE, rotation_speed = 20, rotation_segments = 36, pre_rotation = TRUE, lockinorbit = FALSE)
- if (!istype(A))
- return
-
- new/datum/orbit(src, A, lockinorbit)
- if (!orbiting) //something failed, and our orbit datum deleted itself
- return
- var/matrix/initial_transform = matrix(transform)
-
- //Head first!
- if (pre_rotation)
- var/matrix/M = matrix(transform)
- var/pre_rot = 90
- if(!clockwise)
- pre_rot = -90
- M.Turn(pre_rot)
- transform = M
-
- var/matrix/shift = matrix(transform)
- shift.Translate(0,radius)
- transform = shift
-
- SpinAnimation(rotation_speed, -1, clockwise, rotation_segments)
-
- //we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
- transform = initial_transform
-
-/atom/movable/proc/stop_orbit()
- SpinAnimation(0,0)
- qdel(orbiting)
-
-/atom/Destroy(force = FALSE)
- . = ..()
- if (orbiters)
- for (var/thing in orbiters)
- var/datum/orbit/O = thing
- if (O.orbiter)
- O.orbiter.stop_orbit()
-
-/atom/movable/Destroy(force = FALSE)
- . = ..()
- if (orbiting)
- stop_orbit()
-
-/atom/movable/proc/transfer_observers_to(atom/movable/target)
- if(orbiters)
- for(var/thing in orbiters)
- var/datum/orbit/O = thing
- if(O.orbiter && isobserver(O.orbiter))
- var/mob/dead/observer/D = O.orbiter
- D.ManualFollow(target)
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/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm
index 0a54bcab33..bbad3e08b0 100644
--- a/code/modules/power/tesla/energy_ball.dm
+++ b/code/modules/power/tesla/energy_ball.dm
@@ -33,8 +33,8 @@
return
/obj/singularity/energy_ball/Destroy()
- if(orbiting && istype(orbiting.orbiting, /obj/singularity/energy_ball))
- var/obj/singularity/energy_ball/EB = orbiting.orbiting
+ if(orbiting && istype(orbiting.parent, /obj/singularity/energy_ball))
+ var/obj/singularity/energy_ball/EB = orbiting.parent
EB.orbiting_balls -= src
for(var/ball in orbiting_balls)
@@ -146,12 +146,12 @@
. = ..()
/obj/singularity/energy_ball/stop_orbit()
- if (orbiting && istype(orbiting.orbiting, /obj/singularity/energy_ball))
- var/obj/singularity/energy_ball/orbitingball = orbiting.orbiting
+ if (orbiting && istype(orbiting.parent, /obj/singularity/energy_ball))
+ var/obj/singularity/energy_ball/orbitingball = orbiting.parent
orbitingball.orbiting_balls -= src
orbitingball.dissipate_strength = orbitingball.orbiting_balls.len
- ..()
- if (!loc && !QDELETED(src))
+ . = ..()
+ if (!QDELETED(src))
qdel(src)
diff --git a/code/modules/projectiles/ammunition/special/syringe.dm b/code/modules/projectiles/ammunition/special/syringe.dm
index 4a2a354ca6..d5cba6936f 100644
--- a/code/modules/projectiles/ammunition/special/syringe.dm
+++ b/code/modules/projectiles/ammunition/special/syringe.dm
@@ -59,3 +59,20 @@
S.forceMove(D)
D.injector = S
..()
+
+/obj/item/ammo_casing/syringegun/dart
+ name = "used air canister"
+ desc = "A small canister of compressed gas."
+ projectile_type = /obj/item/projectile/bullet/dart/syringe/dart
+ firing_effect_type = null
+ harmful = FALSE
+
+/obj/item/ammo_casing/syringegun/dart/ready_proj(atom/target, mob/living/user, quiet, zone_override = "")
+ ..()
+ var/obj/item/gun/syringe/SG = loc
+ if(!SG.syringes.len)
+ return
+ var/obj/item/reagent_containers/syringe/dart/S = SG.syringes[1]
+ if(S.emptrig == TRUE)
+ var/obj/item/projectile/bullet/dart/syringe/dart/D = BB
+ D.emptrig = TRUE
diff --git a/code/modules/projectiles/guns/misc/medbeam.dm b/code/modules/projectiles/guns/misc/medbeam.dm
index 17c0f63955..7bdefe5e91 100644
--- a/code/modules/projectiles/guns/misc/medbeam.dm
+++ b/code/modules/projectiles/guns/misc/medbeam.dm
@@ -116,7 +116,7 @@
new /obj/effect/temp_visual/heal(get_turf(target), "#80F5FF")
target.adjustBruteLoss(-4)
target.adjustFireLoss(-4)
- target.adjustToxLoss(-1)
+ target.adjustToxLoss(-1, forced = TRUE)
target.adjustOxyLoss(-1)
return
diff --git a/code/modules/projectiles/guns/misc/syringe_gun.dm b/code/modules/projectiles/guns/misc/syringe_gun.dm
index cc1b321e3a..26e66b1987 100644
--- a/code/modules/projectiles/guns/misc/syringe_gun.dm
+++ b/code/modules/projectiles/guns/misc/syringe_gun.dm
@@ -102,3 +102,23 @@
else
to_chat(user, "[src] cannot hold more syringes!")
return FALSE
+
+/obj/item/gun/syringe/dart
+ name = "dart gun"
+ desc = "A compressed air gun, designed to fit medicinal darts for application of medicine for those patients just out of reach."
+ icon_state = "dartgun"
+ item_state = "dartgun"
+ materials = list(MAT_METAL=2000, MAT_GLASS=500)
+ suppressed = TRUE //Softer fire sound
+ can_unsuppress = FALSE
+
+/obj/item/gun/syringe/dart/Initialize()
+ ..()
+ chambered = new /obj/item/ammo_casing/syringegun/dart(src)
+
+/obj/item/gun/syringe/dart/attackby(obj/item/A, mob/user, params, show_msg = TRUE)
+ if(istype(A, /obj/item/reagent_containers/syringe/dart))
+ ..()
+ else
+ to_chat(user, "You can't put the [A] into \the [src]!")
+ return FALSE
diff --git a/code/modules/projectiles/projectile/bullets/dart_syringe.dm b/code/modules/projectiles/projectile/bullets/dart_syringe.dm
index 94d075c789..bdbf706448 100644
--- a/code/modules/projectiles/projectile/bullets/dart_syringe.dm
+++ b/code/modules/projectiles/projectile/bullets/dart_syringe.dm
@@ -8,12 +8,14 @@
. = ..()
create_reagents(50, NO_REACT)
-/obj/item/projectile/bullet/dart/on_hit(atom/target, blocked = FALSE)
+/obj/item/projectile/bullet/dart/on_hit(atom/target, blocked = FALSE, skip = FALSE)
if(iscarbon(target))
var/mob/living/carbon/M = target
if(blocked != 100) // not completely blocked
if(M.can_inject(null, FALSE, def_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body.
..()
+ if(skip == TRUE)
+ return
reagents.reaction(M, INJECT)
reagents.trans_to(M, reagents.total_volume)
return TRUE
@@ -36,3 +38,44 @@
/obj/item/projectile/bullet/dart/syringe
name = "syringe"
icon_state = "syringeproj"
+
+//I am in a mess of my own making
+/obj/item/projectile/bullet/dart/syringe/dart
+ name = "Smartdart"
+ icon_state = "dartproj"
+ damage = 0
+ var/emptrig = FALSE
+
+/obj/item/projectile/bullet/dart/syringe/dart/on_hit(atom/target, blocked = FALSE)
+ if(iscarbon(target))
+ var/mob/living/carbon/M = target
+ if(blocked != 100)
+ if(M.can_inject(null, FALSE, def_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body.
+ ..(target, blocked, TRUE)
+ for(var/datum/reagent/R in reagents.reagent_list) //OD prevention time!
+ if(istype(R, /datum/reagent/medicine)) //Is this a medicine?
+ if(M.reagents.has_reagent(R.id))
+ if(R.overdose_threshold == 0 || emptrig == TRUE) //Is there a possible OD?
+ M.reagents.add_reagent(R.id, R.volume)
+ else
+ var/transVol = CLAMP(R.volume, 0, (R.overdose_threshold - M.reagents.get_reagent_amount(R.id)) -1)
+ M.reagents.add_reagent(R.id, transVol)
+ else
+ if(!R.overdose_threshold == 0)
+ var/transVol = CLAMP(R.volume, 0, R.overdose_threshold-1)
+ M.reagents.add_reagent(R.id, transVol)
+ else
+ M.reagents.add_reagent(R.id, R.volume)
+
+
+
+ target.visible_message("\The [src] beeps!")
+ to_chat("You feel a tiny prick as a smartdart embeds itself in you with a beep.")
+ return TRUE
+ else
+ blocked = 100
+ target.visible_message("\The [src] was deflected!", \
+ "You see a [src] bounce off you, booping sadly!")
+
+ target.visible_message("\The [src] fails to land on target!")
+ return TRUE
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index 58c29f351b..dc86ab4e6c 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -21,7 +21,9 @@
if(GLOB.chemical_reactions_list)
return
- var/paths = subtypesof(/datum/chemical_reaction)
+
+ //Randomized need to go last since they need to check against conflicts with normal recipes
+ var/paths = subtypesof(/datum/chemical_reaction) - typesof(/datum/chemical_reaction/randomized) + subtypesof(/datum/chemical_reaction/randomized)
GLOB.chemical_reactions_list = list()
for(var/path in paths)
@@ -29,6 +31,9 @@
var/datum/chemical_reaction/D = new path()
var/list/reaction_ids = list()
+ if(!D.id)
+ continue
+
if(D.required_reagents && D.required_reagents.len)
for(var/reaction in D.required_reagents)
reaction_ids += reaction
@@ -267,6 +272,9 @@
continue
if(!C)
C = R.holder.my_atom
+ if(!R.metabolizing)
+ R.metabolizing = TRUE
+ R.on_mob_metabolize(C)
if(C && R)
if(C.reagent_check(R) != 1)
if(can_overdose)
@@ -313,6 +321,21 @@
C.update_stamina()
update_total()
+//Signals that metabolization has stopped, triggering the end of trait-based effects
+/datum/reagents/proc/end_metabolization(mob/living/carbon/C, keep_liverless = TRUE)
+ var/list/cached_reagents = reagent_list
+ for(var/reagent in cached_reagents)
+ var/datum/reagent/R = reagent
+ if(QDELETED(R.holder))
+ continue
+ if(keep_liverless && R.self_consuming) //Will keep working without a liver
+ continue
+ if(!C)
+ C = R.holder.my_atom
+ if(R.metabolizing)
+ R.metabolizing = FALSE
+ R.on_mob_end_metabolize(C)
+
/datum/reagents/proc/conditional_update_move(atom/A, Running = 0)
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
@@ -466,6 +489,9 @@
if(R.id == reagent)
if(my_atom && isliving(my_atom))
var/mob/living/M = my_atom
+ if(R.metabolizing)
+ R.metabolizing = FALSE
+ R.on_mob_end_metabolize(M)
R.on_mob_delete(M)
qdel(R)
reagent_list -= R
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index 08268b2e70..e279d06133 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(
@@ -250,13 +251,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
@@ -269,7 +265,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!")
@@ -322,14 +318,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]!")
@@ -381,7 +375,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
@@ -417,6 +421,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)
@@ -480,9 +490,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",
@@ -535,18 +552,19 @@
"creme_de_cacao",
"triple_sec",
"sake"
- )//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.dm b/code/modules/reagents/chemistry/reagents.dm
index a52bb1ecfe..9bfbffd330 100644
--- a/code/modules/reagents/chemistry/reagents.dm
+++ b/code/modules/reagents/chemistry/reagents.dm
@@ -33,6 +33,10 @@
var/addiction_stage4_end = 40
var/overdosed = 0 // You fucked up and this is now triggering its overdose effects, purge that shit quick.
var/self_consuming = FALSE
+ var/metabolizing = FALSE
+
+
+
/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references
. = ..()
@@ -68,6 +72,14 @@
/datum/reagent/proc/on_mob_delete(mob/living/L)
return
+// Called when this reagent first starts being metabolized by a liver
+/datum/reagent/proc/on_mob_metabolize(mob/living/L)
+ return
+
+// Called when this reagent stops being metabolized by a liver
+/datum/reagent/proc/on_mob_end_metabolize(mob/living/L)
+ return
+
/datum/reagent/proc/on_move(mob/M)
return
diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
index 14963a6689..80e195d5ac 100644
--- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
@@ -111,7 +111,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
M.add_atom_colour(color, TEMPORARY_COLOUR_PRIORITY)
return ..()
-/datum/reagent/consumable/ethanol/beer/green/on_mob_delete(mob/living/M)
+/datum/reagent/consumable/ethanol/beer/green/on_mob_end_metabolize(mob/living/M)
M.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, color)
/datum/reagent/consumable/ethanol/kahlua
@@ -569,13 +569,13 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "Tequila and Coffee liqueur, brought together in a mouthwatering mixture. Drink up."
var/tough_text
-/datum/reagent/consumable/ethanol/brave_bull/on_mob_add(mob/living/M)
+/datum/reagent/consumable/ethanol/brave_bull/on_mob_metabolize(mob/living/M)
tough_text = pick("brawny", "tenacious", "tough", "hardy", "sturdy") //Tuff stuff
to_chat(M, "You feel [tough_text]!")
M.maxHealth += 10 //Brave Bull makes you sturdier, and thus capable of withstanding a tiny bit more punishment.
M.health += 10
-/datum/reagent/consumable/ethanol/brave_bull/on_mob_delete(mob/living/M)
+/datum/reagent/consumable/ethanol/brave_bull/on_mob_end_metabolize(mob/living/M)
to_chat(M, "You no longer feel [tough_text].")
M.maxHealth -= 10
M.health = min(M.health - 10, M.maxHealth) //This can indeed crit you if you're alive solely based on alchol ingestion
@@ -593,7 +593,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "Oh great, now you feel nostalgic about sunrises back on Terra..."
var/obj/effect/light_holder
-/datum/reagent/consumable/ethanol/tequila_sunrise/on_mob_add(mob/living/M)
+/datum/reagent/consumable/ethanol/tequila_sunrise/on_mob_metabolize(mob/living/M)
to_chat(M, "You feel gentle warmth spread through your body!")
light_holder = new(M)
light_holder.set_light(3, 0.7, "#FFCC00") //Tequila Sunrise makes you radiate dim light, like a sunrise!
@@ -605,7 +605,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
light_holder.forceMove(M)
return ..()
-/datum/reagent/consumable/ethanol/tequila_sunrise/on_mob_delete(mob/living/M)
+/datum/reagent/consumable/ethanol/tequila_sunrise/on_mob_end_metabolize(mob/living/M)
to_chat(M, "The warmth in your body fades.")
QDEL_NULL(light_holder)
@@ -671,7 +671,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "A manly concoction made from Ale and Beer. Intended for true men only."
var/dorf_mode
-/datum/reagent/consumable/ethanol/manly_dorf/on_mob_add(mob/living/M)
+/datum/reagent/consumable/ethanol/manly_dorf/on_mob_metabolize(mob/living/M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.dna.check_mutation(DWARFISM) || HAS_TRAIT(H, TRAIT_ALCOHOL_TOLERANCE))
@@ -722,7 +722,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "Kahlua, Irish Cream, and cognac. You will get bombed."
shot_glass_icon_state = "b52glass"
-/datum/reagent/consumable/ethanol/b52/on_mob_add(mob/living/M)
+/datum/reagent/consumable/ethanol/b52/on_mob_metabolize(mob/living/M)
playsound(M, 'sound/effects/explosion_distant.ogg', 100, FALSE)
/datum/reagent/consumable/ethanol/irishcoffee
@@ -1534,7 +1534,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "If you're feeling low, count on the buttery flavor of our own bastion bourbon."
shot_glass_icon_state = "shotglassgreen"
-/datum/reagent/consumable/ethanol/bastion_bourbon/on_mob_add(mob/living/L)
+/datum/reagent/consumable/ethanol/bastion_bourbon/on_mob_metabolize(mob/living/L)
var/heal_points = 10
if(L.health <= 0)
heal_points = 20 //heal more if we're in softcrit
@@ -1618,7 +1618,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "Crevice Spike"
glass_desc = "It'll either knock the drunkenness out of you or knock you out cold. Both, probably."
-/datum/reagent/consumable/ethanol/crevice_spike/on_mob_add(mob/living/L) //damage only applies when drink first enters system and won't again until drink metabolizes out
+/datum/reagent/consumable/ethanol/crevice_spike/on_mob_metabolize(mob/living/L) //damage only applies when drink first enters system and won't again until drink metabolizes out
L.adjustBruteLoss(3 * min(5,volume)) //minimum 3 brute damage on ingestion to limit non-drink means of injury - a full 5 unit gulp of the drink trucks you for the full 15
/datum/reagent/consumable/ethanol/sake
@@ -1661,7 +1661,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "A creamy, indulgent delight that is stronger than it seems."
var/obj/item/shield/mighty_shield
-/datum/reagent/consumable/ethanol/alexander/on_mob_add(mob/living/L)
+/datum/reagent/consumable/ethanol/alexander/on_mob_metabolize(mob/living/L)
if(ishuman(L))
var/mob/living/carbon/human/thehuman = L
for(var/obj/item/shield/theshield in thehuman.contents)
@@ -1675,7 +1675,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
if(mighty_shield && !(mighty_shield in L.contents)) //If you had a shield and lose it, you lose the reagent as well. Otherwise this is just a normal drink.
L.reagents.del_reagent("alexander")
-/datum/reagent/consumable/ethanol/alexander/on_mob_delete(mob/living/L)
+/datum/reagent/consumable/ethanol/alexander/on_mob_end_metabolize(mob/living/L)
if(mighty_shield)
mighty_shield.block_chance -= 10
to_chat(L,"You notice [mighty_shield] looks worn again. Weird.")
@@ -1796,7 +1796,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
M.overeatduration = 0
return ..()
-/datum/reagent/consumable/ethanol/fanciulli/on_mob_add(mob/living/M)
+/datum/reagent/consumable/ethanol/fanciulli/on_mob_metabolize(mob/living/M)
if(M.health > 0)
M.adjustStaminaLoss(20)
. = TRUE
@@ -1820,7 +1820,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
M.adjust_bodytemperature(-20 * TEMPERATURE_DAMAGE_COEFFICIENT, T0C)
return ..()
-/datum/reagent/consumable/ethanol/branca_menta/on_mob_add(mob/living/M)
+/datum/reagent/consumable/ethanol/branca_menta/on_mob_metabolize(mob/living/M)
if(M.health > 0)
M.adjustStaminaLoss(35)
. = TRUE
diff --git a/code/modules/reagents/chemistry/reagents/blob_reagents.dm b/code/modules/reagents/chemistry/reagents/blob_reagents.dm
index 8ee9449468..af85b6b35f 100644
--- a/code/modules/reagents/chemistry/reagents/blob_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/blob_reagents.dm
@@ -204,7 +204,7 @@
C.hal_screwyhud = SCREWYHUD_HEALTHY //fully healed, honest
..()
-/datum/reagent/blob/regenerative_materia/on_mob_delete(mob/living/M)
+/datum/reagent/blob/regenerative_materia/on_mob_end_metabolize(mob/living/M)
if(iscarbon(M))
var/mob/living/carbon/N = M
N.hal_screwyhud = 0
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index ac15eb6b01..d2ca7d0c87 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
@@ -390,11 +390,11 @@
glass_name = "glass of Nuka Cola"
glass_desc = "Don't cry, Don't raise your eye, It's only nuclear wasteland."
-/datum/reagent/consumable/nuka_cola/on_mob_add(mob/living/L)
+/datum/reagent/consumable/nuka_cola/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
-/datum/reagent/consumable/nuka_cola/on_mob_delete(mob/living/L)
+/datum/reagent/consumable/nuka_cola/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
..()
diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
index 04dad3a065..a4586dd997 100644
--- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
@@ -5,7 +5,7 @@
taste_description = "bitterness"
var/trippy = TRUE //Does this drug make you trip?
-/datum/reagent/drug/on_mob_delete(mob/living/M)
+/datum/reagent/drug/on_mob_end_metabolize(mob/living/M)
if(trippy)
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "[id]_high")
@@ -168,11 +168,11 @@
var/jitter = TRUE
var/confusion = TRUE
-/datum/reagent/drug/methamphetamine/on_mob_add(mob/living/L)
+/datum/reagent/drug/methamphetamine/on_mob_metabolize(mob/living/L)
..()
L.ignore_slowdown(id)
-/datum/reagent/drug/methamphetamine/on_mob_delete(mob/living/L)
+/datum/reagent/drug/methamphetamine/on_mob_end_metabolize(mob/living/L)
L.unignore_slowdown(id)
..()
@@ -262,7 +262,7 @@
taste_description = "salt" // because they're bathsalts?
var/datum/brain_trauma/special/psychotic_brawling/bath_salts/rage
-/datum/reagent/drug/bath_salts/on_mob_add(mob/living/L)
+/datum/reagent/drug/bath_salts/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_STUNIMMUNE, id)
ADD_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
@@ -271,7 +271,7 @@
rage = new()
C.gain_trauma(rage, TRAUMA_RESILIENCE_ABSOLUTE)
-/datum/reagent/drug/bath_salts/on_mob_delete(mob/living/L)
+/datum/reagent/drug/bath_salts/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_STUNIMMUNE, id)
REMOVE_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
if(rage)
@@ -381,7 +381,7 @@
addiction_stage3_end = 40
addiction_stage4_end = 240
-/datum/reagent/drug/skooma/on_mob_add(mob/living/L)
+/datum/reagent/drug/skooma/on_mob_metabolize(mob/living/L)
. = ..()
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
L.next_move_modifier *= 2
@@ -392,7 +392,7 @@
if(H.dna && H.dna.species)
H.dna.species.punchdamagehigh *= 5
-/datum/reagent/drug/skooma/on_mob_delete(mob/living/L)
+/datum/reagent/drug/skooma/on_mob_end_metabolize(mob/living/L)
. = ..()
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
L.next_move_modifier *= 0.5
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index afa469706a..38db62fd2a 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -32,6 +32,8 @@
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_verygood)
if (DRINK_FANTASTIC)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_fantastic)
+ if (FOOD_AMAZING)
+ SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_food", /datum/mood_event/amazingtaste)
return ..()
/datum/reagent/consumable/nutriment
@@ -401,7 +403,7 @@
metabolization_rate = 0.2 * REAGENTS_METABOLISM
taste_description = "mushroom"
-/datum/reagent/mushroomhallucinogen/on_mob_life(mob/living/carbon/M)
+/datum/reagent/drug/mushroomhallucinogen/on_mob_life(mob/living/carbon/M)
M.slurring = max(M.slurring,50)
switch(current_cycle)
if(1 to 5)
@@ -686,7 +688,7 @@
/datum/reagent/consumable/tinlux/reaction_mob(mob/living/M)
M.set_light(2)
-/datum/reagent/consumable/tinlux/on_mob_delete(mob/living/M)
+/datum/reagent/consumable/tinlux/on_mob_end_metabolize(mob/living/M)
M.set_light(-2)
/datum/reagent/consumable/vitfro
@@ -711,3 +713,14 @@
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#eef442" // rgb: 238, 244, 66
taste_description = "mournful honking"
+
+/datum/reagent/consumable/secretsauce
+ name = "secret sauce"
+ id = "secret_sauce"
+ description = "What could it be."
+ nutriment_factor = 2 * REAGENTS_METABOLISM
+ color = "#792300"
+ taste_description = "indescribable"
+ quality = FOOD_AMAZING
+ taste_mult = 100
+ can_synth = FALSE
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 07a2a9c02a..ed441504a5 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -366,7 +366,7 @@
to_chat(M, "You feel your wounds fade away to nothing!" )
..()
-/datum/reagent/medicine/mine_salve/on_mob_delete(mob/living/M)
+/datum/reagent/medicine/mine_salve/on_mob_end_metabolize(mob/living/M)
if(iscarbon(M))
var/mob/living/carbon/N = M
N.hal_screwyhud = SCREWYHUD_NONE
@@ -483,16 +483,24 @@
reagent_state = LIQUID
color = "#E6FFF0"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
+ var/healtoxinlover = FALSE
/datum/reagent/medicine/pen_acid/on_mob_life(mob/living/carbon/M)
M.radiation -= max(M.radiation-RAD_MOB_SAFE, 0)/50
- M.adjustToxLoss(-2*REM, 0)
+ M.adjustToxLoss(-2*REM, 0, healtoxinlover)
for(var/datum/reagent/R in M.reagents.reagent_list)
if(R != src)
M.reagents.remove_reagent(R.id,2)
..()
. = 1
+/datum/reagent/medicine/pen_acid/pen_jelly
+ name = "Pentetic Jelly"
+ id = "pen_jelly"
+ description = "Reduces massive amounts of radiation and toxin damage while purging other chemicals from the body. Slimepeople friendly!"
+ color = "#91D865"
+ healtoxinlover = TRUE
+
/datum/reagent/medicine/sal_acid
name = "Salicyclic Acid"
id = "sal_acid"
@@ -630,11 +638,11 @@
overdose_threshold = 30
addiction_threshold = 25
-/datum/reagent/medicine/morphine/on_mob_add(mob/living/L)
+/datum/reagent/medicine/morphine/on_mob_metabolize(mob/living/L)
..()
L.ignore_slowdown(id)
-/datum/reagent/medicine/morphine/on_mob_delete(mob/living/L)
+/datum/reagent/medicine/morphine/on_mob_end_metabolize(mob/living/L)
L.unignore_slowdown(id)
..()
@@ -875,11 +883,11 @@
metabolization_rate = 0.5 * REAGENTS_METABOLISM
overdose_threshold = 60
-/datum/reagent/medicine/stimulants/on_mob_add(mob/living/L)
+/datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
-/datum/reagent/medicine/stimulants/on_mob_delete(mob/living/L)
+/datum/reagent/medicine/stimulants/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
..()
@@ -1102,7 +1110,7 @@
M.adjustBruteLoss(-3 * REM, 0)
M.adjustFireLoss(-3 * REM, 0)
M.adjustOxyLoss(-15 * REM, 0)
- M.adjustToxLoss(-3 * REM, 0)
+ M.adjustToxLoss(-3 * REM, 0, TRUE) //Heals TOXINLOVERS
M.adjustBrainLoss(2 * REM, 150) //This does, after all, come from ambrosia, and the most powerful ambrosia in existence, at that!
M.adjustCloneLoss(-1 * REM, 0)
M.adjustStaminaLoss(-30 * REM, 0)
@@ -1113,7 +1121,7 @@
/datum/reagent/medicine/earthsblood/overdose_process(mob/living/M)
M.hallucination = min(max(0, M.hallucination + 5), 60)
- M.adjustToxLoss(5 * REM, 0)
+ M.adjustToxLoss(8 * REM, 0, TRUE) //Hurts TOXINLOVERS
..()
. = 1
@@ -1188,11 +1196,11 @@
color = "#C8A5DC"
metabolization_rate = 1
-/datum/reagent/medicine/changelinghaste/on_mob_add(mob/living/L)
+/datum/reagent/medicine/changelinghaste/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_GOTTAGOREALLYFAST, id)
-/datum/reagent/medicine/changelinghaste/on_mob_delete(mob/living/L)
+/datum/reagent/medicine/changelinghaste/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_GOTTAGOREALLYFAST, id)
..()
@@ -1210,11 +1218,11 @@
color = "#F5F5F5"
self_consuming = TRUE
-/datum/reagent/medicine/corazone/on_mob_add(mob/living/M)
+/datum/reagent/medicine/corazone/on_mob_metabolize(mob/living/M)
..()
ADD_TRAIT(M, TRAIT_STABLEHEART, id)
-/datum/reagent/medicine/corazone/on_mob_delete(mob/living/M)
+/datum/reagent/medicine/corazone/on_mob_end_metabolize(mob/living/M)
REMOVE_TRAIT(M, TRAIT_STABLEHEART, id)
..()
@@ -1223,11 +1231,11 @@
id = "muscle_stimulant"
description = "A potent chemical that allows someone under its influence to be at full physical ability even when under massive amounts of pain."
-/datum/reagent/medicine/muscle_stimulant/on_mob_add(mob/living/M)
+/datum/reagent/medicine/muscle_stimulant/on_mob_metabolize(mob/living/M)
. = ..()
M.ignore_slowdown(id)
-/datum/reagent/medicine/muscle_stimulant/on_mob_delete(mob/living/M)
+/datum/reagent/medicine/muscle_stimulant/on_mob_end_metabolize(mob/living/M)
. = ..()
M.unignore_slowdown(id)
@@ -1242,11 +1250,11 @@
taste_description = "salt" // it actually does taste salty
var/overdose_progress = 0 // to track overdose progress
-/datum/reagent/medicine/modafinil/on_mob_add(mob/living/M)
+/datum/reagent/medicine/modafinil/on_mob_metabolize(mob/living/M)
ADD_TRAIT(M, TRAIT_SLEEPIMMUNE, id)
..()
-/datum/reagent/medicine/modafinil/on_mob_delete(mob/living/M)
+/datum/reagent/medicine/modafinil/on_mob_end_metabolize(mob/living/M)
REMOVE_TRAIT(M, TRAIT_SLEEPIMMUNE, id)
..()
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 40242909de..890403691e 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -196,11 +196,11 @@
glass_name = "glass of holy water"
glass_desc = "A glass of holy water."
-/datum/reagent/water/holywater/on_mob_add(mob/living/L)
+/datum/reagent/water/holywater/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_HOLY, id)
-/datum/reagent/water/holywater/on_mob_delete(mob/living/L)
+/datum/reagent/water/holywater/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_HOLY, id)
..()
@@ -1241,12 +1241,12 @@
color = "E1A116"
taste_description = "sourness"
-/datum/reagent/stimulum/on_mob_add(mob/living/L)
+/datum/reagent/stimulum/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_STUNIMMUNE, id)
ADD_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
-/datum/reagent/stimulum/on_mob_delete(mob/living/L)
+/datum/reagent/stimulum/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_STUNIMMUNE, id)
REMOVE_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
..()
@@ -1266,11 +1266,11 @@
color = "90560B"
taste_description = "burning"
-/datum/reagent/nitryl/on_mob_add(mob/living/L)
+/datum/reagent/nitryl/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
-/datum/reagent/nitryl/on_mob_delete(mob/living/L)
+/datum/reagent/nitryl/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
..()
@@ -1723,7 +1723,7 @@
H.update_transform()
..()
-/datum/reagent/growthserum/on_mob_delete(mob/living/M)
+/datum/reagent/growthserum/on_mob_end_metabolize(mob/living/M)
M.resize = 1/current_size
M.update_transform()
..()
@@ -1777,11 +1777,11 @@
taste_description = "water"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
-/datum/reagent/pax/on_mob_add(mob/living/L)
+/datum/reagent/pax/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_PACIFISM, id)
-/datum/reagent/pax/on_mob_delete(mob/living/L)
+/datum/reagent/pax/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_PACIFISM, id)
..()
@@ -1793,11 +1793,11 @@
taste_description = "acrid cinnamon"
metabolization_rate = 0.2 * REAGENTS_METABOLISM
-/datum/reagent/bz_metabolites/on_mob_add(mob/living/L)
+/datum/reagent/bz_metabolites/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, CHANGELING_HIVEMIND_MUTE, id)
-/datum/reagent/bz_metabolites/on_mob_delete(mob/living/L)
+/datum/reagent/bz_metabolites/on_mob_end_metabolize(mob/living/L)
..()
REMOVE_TRAIT(L, CHANGELING_HIVEMIND_MUTE, id)
@@ -1814,14 +1814,14 @@
description = "A colorless liquid that suppresses violence on the subjects. Cheaper to synthetize, but wears out faster than normal Pax."
metabolization_rate = 1.5 * REAGENTS_METABOLISM
-/datum/reagent/peaceborg/confuse
+/datum/reagent/peaceborg_confuse
name = "Dizzying Solution"
id = "dizzysolution"
description = "Makes the target off balance and dizzy"
metabolization_rate = 1.5 * REAGENTS_METABOLISM
taste_description = "dizziness"
-/datum/reagent/peaceborg/confuse/on_mob_life(mob/living/carbon/M)
+/datum/reagent/peaceborg_confuse/on_mob_life(mob/living/carbon/M)
if(M.confused < 6)
M.confused = CLAMP(M.confused + 3, 0, 5)
if(M.dizziness < 6)
@@ -1830,14 +1830,14 @@
to_chat(M, "You feel confused and disorientated.")
..()
-/datum/reagent/peaceborg/tire
+/datum/reagent/peaceborg_tire
name = "Tiring Solution"
id = "tiresolution"
description = "An extremely weak stamina-toxin that tires out the target. Completely harmless."
metabolization_rate = 1.5 * REAGENTS_METABOLISM
taste_description = "tiredness"
-/datum/reagent/peaceborg/tire/on_mob_life(mob/living/carbon/M)
+/datum/reagent/peaceborg_tire/on_mob_life(mob/living/carbon/M)
var/healthcomp = (100 - M.health) //DOES NOT ACCOUNT FOR ADMINBUS THINGS THAT MAKE YOU HAVE MORE THAN 200/210 HEALTH, OR SOMETHING OTHER THAN A HUMAN PROCESSING THIS.
if(M.getStaminaLoss() < (45 - healthcomp)) //At 50 health you would have 200 - 150 health meaning 50 compensation. 60 - 50 = 10, so would only do 10-19 stamina.)
M.adjustStaminaLoss(10)
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 8be95efb83..6bd165f23e 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -156,11 +156,11 @@
toxpwr = 0.5
taste_description = "death"
-/datum/reagent/toxin/zombiepowder/on_mob_add(mob/living/L)
+/datum/reagent/toxin/zombiepowder/on_mob_metabolize(mob/living/L)
..()
L.fakedeath(id)
-/datum/reagent/toxin/zombiepowder/on_mob_delete(mob/living/L)
+/datum/reagent/toxin/zombiepowder/on_mob_end_metabolize(mob/living/L)
L.cure_fakedeath(id)
..()
@@ -178,11 +178,11 @@
toxpwr = 0.8
taste_description = "death"
-/datum/reagent/toxin/ghoulpowder/on_mob_add(mob/living/L)
+/datum/reagent/toxin/ghoulpowder/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_FAKEDEATH, id)
-/datum/reagent/toxin/ghoulpowder/on_mob_delete(mob/living/L)
+/datum/reagent/toxin/ghoulpowder/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_FAKEDEATH, id)
..()
@@ -626,7 +626,7 @@
toxpwr = 0
metabolization_rate = 0.5 * REAGENTS_METABOLISM
-/datum/reagent/toxin/amanitin/on_mob_delete(mob/living/M)
+/datum/reagent/toxin/amanitin/on_mob_end_metabolize(mob/living/M)
var/toxdamage = current_cycle*3*REM
M.log_message("has taken [toxdamage] toxin damage from amanitin toxin", LOG_ATTACK)
M.adjustToxLoss(toxdamage)
@@ -742,7 +742,7 @@
animate(transform = matrix(-rotation, MATRIX_ROTATE), time = 5, easing = QUAD_EASING)
return ..()
-/datum/reagent/toxin/rotatium/on_mob_delete(mob/living/M)
+/datum/reagent/toxin/rotatium/on_mob_end_metabolize(mob/living/M)
if(M && M.hud_used)
var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
for(var/whole_screen in screens)
@@ -779,7 +779,7 @@
*/
return ..()
-/datum/reagent/toxin/skewium/on_mob_delete(mob/living/M)
+/datum/reagent/toxin/skewium/on_mob_end_metabolize(mob/living/M)
if(M && M.hud_used)
var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
for(var/whole_screen in screens)
@@ -798,7 +798,7 @@
/datum/reagent/toxin/anacea/on_mob_life(mob/living/carbon/M)
var/remove_amt = 5
- if(holder.has_reagent("calomel") || holder.has_reagent("pen_acid"))
+ if(holder.has_reagent("calomel") || holder.has_reagent("pen_acid") || holder.has_reagent("pen_jelly"))
remove_amt = 0.5
for(var/datum/reagent/medicine/R in M.reagents.reagent_list)
M.reagents.remove_reagent(R.id,remove_amt)
@@ -882,8 +882,69 @@
toxpwr = 0
taste_description = "stillness"
-/datum/reagent/toxin/mimesbane/on_mob_add(mob/living/L)
+/datum/reagent/toxin/mimesbane/on_mob_metabolize(mob/living/L)
ADD_TRAIT(L, TRAIT_EMOTEMUTE, id)
-/datum/reagent/toxin/mimesbane/on_mob_delete(mob/living/L)
+/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/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm
index dc7c32d925..727048a12c 100644
--- a/code/modules/reagents/chemistry/recipes/medicine.dm
+++ b/code/modules/reagents/chemistry/recipes/medicine.dm
@@ -94,6 +94,12 @@
results = list("pen_acid" = 6)
required_reagents = list("welding_fuel" = 1, "chlorine" = 1, "ammonia" = 1, "formaldehyde" = 1, "sodium" = 1, "cyanide" = 1)
+/datum/chemical_reaction/pen_jelly
+ name = "Pentetic Jelly"
+ id = "pen_jelly"
+ results = list("pen_jelly" = 2)
+ required_reagents = list("pen_acid" = 1, "slimejelly" = 1)
+
/datum/chemical_reaction/sal_acid
name = "Salicyclic Acid"
id = "sal_acid"
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/special.dm b/code/modules/reagents/chemistry/recipes/special.dm
new file mode 100644
index 0000000000..153372101e
--- /dev/null
+++ b/code/modules/reagents/chemistry/recipes/special.dm
@@ -0,0 +1,212 @@
+GLOBAL_LIST_INIT(food_reagents, build_reagents_to_food()) //reagentid = related food types
+
+/proc/build_reagents_to_food()
+ . = list()
+ for (var/type in subtypesof(/obj/item/reagent_containers/food))
+ var/obj/item/reagent_containers/food/item = new type()
+ for(var/r in item.list_reagents)
+ if (!.[r])
+ .[r] = list()
+ .[r] += type
+ qdel(item)
+ //dang plant snowflake
+ for (var/type in subtypesof(/obj/item/seeds))
+ var/obj/item/seeds/item = new type()
+ for(var/r in item.reagents_add)
+ if (!.[r])
+ .[r] = list()
+ .[r] += type
+ qdel(item)
+
+
+#define RNGCHEM_INPUT "input"
+#define RNGCHEM_CATALYSTS "catalysts"
+#define RNGCHEM_OUTPUT "output"
+
+/datum/chemical_reaction/randomized
+ name = "semi randomized reaction"
+
+ var/persistent = FALSE
+ var/persistence_period = 7 //Will reset every x days
+ var/created //creation timestamp
+
+ var/randomize_container = FALSE
+ var/list/possible_containers = list()
+
+ var/randomize_req_temperature = TRUE
+ var/min_temp = 1
+ var/max_temp = 600
+
+ var/randomize_inputs = TRUE
+ var/min_input_reagent_amount = 1
+ var/max_input_reagent_amount = 10
+ var/min_input_reagents = 2
+ var/max_input_reagents = 5
+ var/list/possible_reagents = list()
+ var/min_catalysts = 0
+ var/max_catalysts = 2
+ var/list/possible_catalysts = list()
+
+ var/randomize_results = FALSE
+ var/min_output_reagent_amount = 1
+ var/max_output_reagent_amount = 5
+ var/min_result_reagents = 1
+ var/max_result_reagents = 1
+ var/list/possible_results = list()
+
+/datum/chemical_reaction/randomized/proc/GenerateRecipe()
+ created = world.time
+ if(randomize_container)
+ required_container = pick(possible_containers)
+ if(randomize_req_temperature)
+ required_temp = rand(min_temp,max_temp)
+ is_cold_recipe = pick(TRUE,FALSE)
+
+ if(randomize_results)
+ results = list()
+ var/list/remaining_possible_results = GetPossibleReagents(RNGCHEM_OUTPUT)
+ var/out_reagent_count = min(rand(min_result_reagents,max_result_reagents),remaining_possible_results.len)
+ for(var/i in 1 to out_reagent_count)
+ var/r_id = pick_n_take(remaining_possible_results)
+ results[r_id] = rand(min_output_reagent_amount,max_output_reagent_amount)
+
+ if(randomize_inputs)
+ var/list/remaining_possible_reagents = GetPossibleReagents(RNGCHEM_INPUT)
+ var/list/remaining_possible_catalysts = GetPossibleReagents(RNGCHEM_CATALYSTS)
+
+ //We're going to assume we're not doing any weird partial reactions for now.
+ for(var/reagent_type in results)
+ remaining_possible_catalysts -= reagent_type
+ remaining_possible_reagents -= reagent_type
+
+ var/in_reagent_count = min(rand(min_input_reagents,max_input_reagents),remaining_possible_reagents.len)
+ if(in_reagent_count <= 0)
+ return FALSE
+
+ required_reagents = list()
+ for(var/i in 1 to in_reagent_count)
+ var/r_id = pick_n_take(remaining_possible_reagents)
+ required_reagents[r_id] = rand(min_input_reagent_amount,max_input_reagent_amount)
+ remaining_possible_catalysts -= r_id //Can't have same reagents both as catalyst and reagent. Or can we ?
+
+ required_catalysts = list()
+ var/in_catalyst_count = min(rand(min_catalysts,max_catalysts),remaining_possible_catalysts.len)
+ for(var/i in 1 to in_catalyst_count)
+ var/r_id = pick_n_take(remaining_possible_catalysts)
+ required_catalysts[r_id] = rand(min_input_reagent_amount,max_input_reagent_amount)
+
+ return TRUE
+
+/datum/chemical_reaction/randomized/proc/GetPossibleReagents(kind)
+ switch(kind)
+ if(RNGCHEM_INPUT)
+ return possible_reagents.Copy()
+ if(RNGCHEM_CATALYSTS)
+ return possible_catalysts.Copy()
+ if(RNGCHEM_OUTPUT)
+ return possible_results.Copy()
+
+/datum/chemical_reaction/randomized/proc/HasConflicts()
+ for(var/x in required_reagents)
+ for(var/datum/chemical_reaction/R in GLOB.chemical_reactions_list[x])
+ if(chem_recipes_do_conflict(R,src))
+ return TRUE
+ return FALSE
+
+/datum/chemical_reaction/randomized/proc/unwrap_reagent_list(list/textreagents)
+ . = list()
+ for(var/R in textreagents)
+ var/pathR = text2path(R)
+ if(!pathR)
+ return null
+ .[pathR] = textreagents[R]
+
+/datum/chemical_reaction/randomized/proc/LoadOldRecipe(recipe_data)
+ created = text2num(recipe_data["timestamp"])
+
+ var/req_reag = unwrap_reagent_list(recipe_data["required_reagents"])
+ if(!req_reag)
+ return FALSE
+ required_reagents = req_reag
+
+ var/req_catalysts = unwrap_reagent_list(recipe_data["required_catalysts"])
+ if(!req_catalysts)
+ return FALSE
+ required_catalysts = req_catalysts
+
+ required_temp = recipe_data["required_temp"]
+ is_cold_recipe = recipe_data["is_cold_recipe"]
+
+ var/temp_results = unwrap_reagent_list(recipe_data["results"])
+ if(!temp_results)
+ return FALSE
+ results = temp_results
+ var/containerpath = text2path(recipe_data["required_container"])
+ if(!containerpath)
+ return FALSE
+ required_container = containerpath
+ return TRUE
+
+/datum/chemical_reaction/randomized/secret_sauce
+ name = "secret sauce creation"
+ id = "secretsauce"
+ persistent = TRUE
+ persistence_period = 7 //Reset every week
+ randomize_container = TRUE
+ possible_containers = list(/obj/item/reagent_containers/glass/bucket) //easy way to ensure no common conflicts
+ randomize_req_temperature = TRUE
+ results = list("secret_sauce" =1)
+
+/datum/chemical_reaction/randomized/secret_sauce/GetPossibleReagents(kind)
+ switch(kind)
+ if(RNGCHEM_INPUT,RNGCHEM_CATALYSTS)
+ var/food_reagent_ids = list()
+ for(var/key in GLOB.food_reagents)
+ food_reagent_ids += key
+ return food_reagent_ids
+ return ..()
+
+
+/obj/item/paper/secretrecipe
+ name = "old recipe"
+ var/recipe_id = "secretsauce"
+
+/obj/item/paper/secretrecipe/examine(mob/user) //Extra secret
+ if(isobserver(user))
+ return
+ . = ..()
+
+/obj/item/paper/secretrecipe/Initialize()
+ . = ..()
+ if(SSpersistence.initialized)
+ UpdateInfo()
+ else
+ SSticker.OnRoundstart(CALLBACK(src,.proc/UpdateInfo))
+
+/obj/item/paper/secretrecipe/proc/UpdateInfo()
+ var/datum/chemical_reaction/recipe = get_chemical_reaction(recipe_id)
+ if(!recipe)
+ info = "This recipe is illegible."
+ var/list/dat = list("
")
+ for(var/rid in recipe.required_reagents)
+ var/datum/reagent/R = GLOB.chemical_reagents_list[rid]
+ dat += "
[recipe.required_reagents[rid]]u of [R.name]
"
+ dat += "
"
+ if(recipe.required_catalysts.len)
+ dat += "With following present:
"
+ for(var/rid in recipe.required_catalysts)
+ var/datum/reagent/R = GLOB.chemical_reagents_list[rid]
+ dat += "
[recipe.required_catalysts[rid]]u of [R.name]
"
+ dat += "
"
+ dat += "Mix slowly"
+ if(recipe.required_container)
+ var/obj/item/I = recipe.required_container
+ dat += " in [initial(I.name)]"
+ if(recipe.required_temp != 0)
+ if(recipe.is_cold_recipe)
+ dat += " below [recipe.required_temp] degrees"
+ else
+ dat += " above [recipe.required_temp] degrees"
+ dat += "."
+ info = dat.Join("")
+ update_icon()
\ No newline at end of file
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/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 4947ddde6f..cc83eb28f6 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -259,3 +259,92 @@
/obj/item/reagent_containers/syringe/get_belt_overlay()
return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "pouch")
+
+/obj/item/reagent_containers/syringe/dart
+ name = "medicinal smartdart"
+ desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented."
+ volume = 20
+ amount_per_transfer_from_this = 20
+ icon_state = "empty"
+ item_state = "syringe_empty"
+ var/emptrig = FALSE
+
+/obj/item/reagent_containers/syringe/dart/afterattack(atom/target, mob/user , proximity)
+
+ if(busy)
+ return
+ if(!proximity)
+ return
+ if(!target.reagents)
+ return
+
+ var/mob/living/L
+ if(isliving(target))
+ L = target
+ if(!L.can_inject(user, 1))
+ return
+
+ switch(mode)
+ if(SYRINGE_DRAW)
+
+ if(reagents.total_volume >= reagents.maximum_volume)
+ to_chat(user, "The dart is full!")
+ return
+
+ if(L) //living mob
+ to_chat(user, "You can't draw blood using a dart!")
+ return
+
+ else //if not mob
+ if(!target.reagents.total_volume)
+ to_chat(user, "[target] is empty!")
+ return
+
+ if(!target.is_drawable())
+ to_chat(user, "You cannot directly remove reagents from [target]!")
+ return
+
+ var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
+
+ to_chat(user, "You soak the [src] with [trans] units of the solution. It now contains [reagents.total_volume] units.")
+ if (reagents.total_volume >= reagents.maximum_volume)
+ mode=!mode
+ update_icon()
+
+ if(SYRINGE_INJECT)
+ src.visible_message("The smartdart gives a frustrated boop! It's fully saturated; You need to shoot someone with it!")
+
+/obj/item/reagent_containers/syringe/dart/attack_self(mob/user)
+ return
+
+/obj/item/reagent_containers/syringe/dart/update_icon()
+ cut_overlays()
+ var/rounded_vol
+
+ rounded_vol = "empty"
+ if(reagents && reagents.total_volume)
+ if(volume/reagents.total_volume == 1)
+ rounded_vol="full"
+
+ icon_state = "[rounded_vol]"
+ item_state = "syringe_[rounded_vol]"
+ if(ismob(loc))
+ var/mob/M = loc
+ var/injoverlay
+ switch(mode)
+ if (SYRINGE_DRAW)
+ injoverlay = "draw"
+ if (SYRINGE_INJECT)
+ injoverlay = "ready"
+ add_overlay(injoverlay)
+ M.update_inv_hands()
+
+/obj/item/reagent_containers/syringe/dart/emp_act(severity)
+ emptrig = TRUE
+ ..()
+
+/obj/item/reagent_containers/syringe/dart/bluespace
+ name = "bluespace smartdart"
+ desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented. Has an extended volume capacity thanks to bluespace foam."
+ amount_per_transfer_from_this = 50
+ volume = 50
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/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm
index 8a8377601a..3a7ef68903 100644
--- a/code/modules/research/designs/medical_designs.dm
+++ b/code/modules/research/designs/medical_designs.dm
@@ -92,6 +92,36 @@
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+/datum/design/medicinalsmartdart
+ name = "Medicinal Smartdart"
+ desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented."
+ id = "medicinalsmartdart"
+ build_type = PROTOLATHE
+ materials = list(MAT_GLASS = 100, MAT_PLASTIC = 100, MAT_METAL = 100)
+ build_path = /obj/item/reagent_containers/syringe/dart
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+
+/datum/design/bluespacesmartdart
+ name = "bluespace smartdart"
+ desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented. Has an extended volume capacity thanks to bluespace foam."
+ id = "bluespacesmartdart"
+ build_type = PROTOLATHE
+ materials = list(MAT_GLASS = 250, MAT_PLASTIC = 250, MAT_METAL = 250, MAT_BLUESPACE = 250)
+ build_path = /obj/item/reagent_containers/syringe/dart/bluespace
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+
+/datum/design/smartdartgun
+ name = "dart gun"
+ desc = "A compressed air gun, designed to fit medicinal darts for application of medicine for those patients just out of reach."
+ id = "smartdartgun"
+ build_type = PROTOLATHE
+ materials = list(MAT_GLASS = 500, MAT_PLASTIC = 1000, MAT_METAL = 500)
+ build_path = /obj/item/gun/syringe/dart
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+
/datum/design/bluespacebodybag
name = "Bluespace Body Bag"
desc = "A bluespace body bag, powered by experimental bluespace technology. It can hold loads of bodies and the largest of creatures."
diff --git a/code/modules/research/nanites/nanite_programs.dm b/code/modules/research/nanites/nanite_programs.dm
index f691c828c9..a06311f26f 100644
--- a/code/modules/research/nanites/nanite_programs.dm
+++ b/code/modules/research/nanites/nanite_programs.dm
@@ -57,6 +57,7 @@
deactivate()
if(passive_enabled)
disable_passive_effect()
+ on_mob_remove()
if(nanites)
nanites.programs -= src
return ..()
@@ -107,6 +108,9 @@
if(activated) //apply activation effects if it starts active
activate()
+datum/nanite_program/proc/on_mob_remove()
+ return
+
/datum/nanite_program/proc/toggle()
if(!activated)
activate()
@@ -115,6 +119,7 @@
/datum/nanite_program/proc/activate()
activated = TRUE
+ timer_counter = activation_delay
/datum/nanite_program/proc/deactivate()
if(passive_enabled)
@@ -135,8 +140,10 @@
if(timer && timer_counter > timer)
if(timer_type == NANITE_TIMER_DEACTIVATE)
deactivate()
+ return
else if(timer_type == NANITE_TIMER_SELFDELETE)
qdel(src)
+ return
else if(can_trigger && timer_type == NANITE_TIMER_TRIGGER)
trigger()
timer_counter = activation_delay
@@ -251,4 +258,3 @@
return "Trigger"
if(NANITE_TIMER_RESET)
return "Reset Activation Timer"
-
diff --git a/code/modules/research/nanites/nanite_programs/utility.dm b/code/modules/research/nanites/nanite_programs/utility.dm
index 4405401cec..77fb4e1005 100644
--- a/code/modules/research/nanites/nanite_programs/utility.dm
+++ b/code/modules/research/nanites/nanite_programs/utility.dm
@@ -237,7 +237,11 @@
if(prob(10))
var/list/mob/living/target_hosts = list()
for(var/mob/living/L in oview(5, host_mob))
+ if(!(MOB_ORGANIC in L.mob_biotypes) && !(MOB_UNDEAD in L.mob_biotypes))
+ continue
target_hosts += L
+ if(!target_hosts.len)
+ return
var/mob/living/infectee = pick(target_hosts)
if(prob(100 - (infectee.get_permeability_protection() * 100)))
//this will potentially take over existing nanites!
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index c1124efe2d..4331d8858b 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -69,7 +69,7 @@
display_name = "Advanced Biotechnology"
description = "Advanced Biotechnology"
prereq_ids = list("biotech")
- design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "defibrillator", "meta_beaker", "healthanalyzer_advanced","harvester","holobarrier_med")
+ design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "defibrillator", "meta_beaker", "healthanalyzer_advanced","harvester","holobarrier_med","smartdartgun","medicinalsmartdart")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -246,7 +246,7 @@
display_name = "Applied Bluespace Research"
description = "Using bluespace to make things faster and better."
prereq_ids = list("bluespace_basic", "engineering")
- design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "roastingstick", "ore_silo")
+ design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "roastingstick", "ore_silo", "bluespacesmartdart")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500)
export_price = 5000
diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm
index 28ea849782..92a637ce43 100644
--- a/code/modules/ruins/lavaland_ruin_code.dm
+++ b/code/modules/ruins/lavaland_ruin_code.dm
@@ -22,7 +22,7 @@
icon_state = "datadisk1"
max_blueprints = 1
-/obj/item/disk/design_disk/golem_shell/Initialize()
+/obj/item/disk/design_disk/plant_disk/Initialize()
. = ..()
var/datum/design/diskplantgene/P = new
blueprints[1] = P
@@ -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/shuttle/ferry.dm b/code/modules/shuttle/ferry.dm
index eaa1f36b75..4404332619 100644
--- a/code/modules/shuttle/ferry.dm
+++ b/code/modules/shuttle/ferry.dm
@@ -12,7 +12,7 @@
/obj/machinery/computer/shuttle/ferry/emag_act(mob/user)
if(!allow_emag)
to_chat(user, "[src]'s security firewall is far too powerful for you to bypass.")
- return FALSE
+ return SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
return ..()
/obj/machinery/computer/shuttle/ferry/attack_ai()
diff --git a/code/modules/spells/spell_types/construct_spells.dm b/code/modules/spells/spell_types/construct_spells.dm
index 39066ae4a9..bb3cc1f7e3 100644
--- a/code/modules/spells/spell_types/construct_spells.dm
+++ b/code/modules/spells/spell_types/construct_spells.dm
@@ -146,11 +146,14 @@
clothes_req = 0
invocation = "none"
invocation_type = "none"
+ proj_type = /obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile/lesser
proj_lifespan = 10
max_targets = 6
action_icon_state = "magicm"
action_background_icon_state = "bg_demon"
+/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile/lesser
+ amt_knockdown = 84
/obj/effect/proc_holder/spell/targeted/smoke/disable
name = "Paralysing Smoke"
@@ -304,7 +307,8 @@
name = "Gauntlet Echo"
alpha = 180
amt_dam_brute = 30
- amt_knockdown = 50
+ amt_knockdown = 84
+ amt_dam_stam = 30
sound = 'sound/weapons/punch3.ogg'
/obj/effect/proc_holder/spell/targeted/inflict_handler/juggernaut/cast(list/targets,mob/user = usr)
diff --git a/code/modules/spells/spell_types/inflict_handler.dm b/code/modules/spells/spell_types/inflict_handler.dm
index da0af7a601..25bdc7c9d2 100644
--- a/code/modules/spells/spell_types/inflict_handler.dm
+++ b/code/modules/spells/spell_types/inflict_handler.dm
@@ -3,10 +3,12 @@
desc = "This spell blinds and/or destroys/damages/heals and/or knockdowns/stuns the target."
var/amt_knockdown = 0
+ var/amt_hardstun
var/amt_unconscious = 0
var/amt_stun = 0
//set to negatives for healing
+ var/amt_dam_stam
var/amt_dam_fire = 0
var/amt_dam_brute = 0
var/amt_dam_oxy = 0
@@ -41,7 +43,10 @@
target.adjustToxLoss(amt_dam_tox)
target.adjustOxyLoss(amt_dam_oxy)
//disabling
- target.Knockdown(amt_knockdown)
+ if(!amt_knockdown && amt_dam_stam)
+ target.adjustStaminaLoss(amt_dam_stam)
+ else
+ target.Knockdown(amt_knockdown, override_hardstun = amt_hardstun, amt_dam_stam)
target.Unconscious(amt_unconscious)
target.Stun(amt_stun)
diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm
index aec0e7806b..c4d2c34a71 100644
--- a/code/modules/spells/spell_types/wizard.dm
+++ b/code/modules/spells/spell_types/wizard.dm
@@ -28,7 +28,8 @@
sound = 'sound/magic/magic_missile.ogg'
/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile
- amt_knockdown = 60
+ amt_knockdown = 120
+ amt_hardstun = 5
sound = 'sound/magic/mm_hit.ogg'
/obj/effect/proc_holder/spell/targeted/genetic/mutate
@@ -262,7 +263,7 @@
action_icon_state = "repulse"
-/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets,mob/user = usr, var/stun_amt = 40)
+/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets,mob/user = usr, stun_amt = 50)
var/list/thrownatoms = list()
var/atom/throwtarget
var/distfromcaster
@@ -286,14 +287,14 @@
if(distfromcaster == 0)
if(isliving(AM))
var/mob/living/M = AM
- M.Knockdown(100)
+ M.Knockdown(100, override_hardstun = 20)
M.adjustBruteLoss(5)
to_chat(M, "You're slammed into the floor by [user]!")
else
new sparkle_path(get_turf(AM), get_dir(user, AM)) //created sparkles will disappear on their own
if(isliving(AM))
var/mob/living/M = AM
- M.Knockdown(stun_amt)
+ M.Knockdown(stun_amt, override_hardstun = stun_amt * 0.2)
to_chat(M, "You're thrown back by [user]!")
AM.throw_at(throwtarget, ((CLAMP((maxthrow - (CLAMP(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time.
diff --git a/code/modules/station_goals/shield.dm b/code/modules/station_goals/shield.dm
index 94e711bf6c..cc53958c56 100644
--- a/code/modules/station_goals/shield.dm
+++ b/code/modules/station_goals/shield.dm
@@ -204,3 +204,4 @@
to_chat(user, "You access the satellite's debug mode, increasing the chance of meteor strikes.")
if(active)
change_meteor_chance(4)
+ return TRUE
diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm
index 9204de3d08..a97a133685 100644
--- a/code/modules/surgery/bodyparts/bodyparts.dm
+++ b/code/modules/surgery/bodyparts/bodyparts.dm
@@ -21,7 +21,7 @@
var/held_index = 0 //are we a hand? if so, which one!
var/is_pseudopart = FALSE //For limbs that don't really exist, eg chainsaws
- var/disabled = FALSE //If TRUE, limb is as good as missing
+ var/disabled = BODYPART_NOT_DISABLED //If disabled, limb is as good as missing
var/body_damage_coeff = 1 //Multiplier of the limb's damage that gets applied to the mob
var/stam_damage_coeff = 0.5
var/brutestate = 0
@@ -189,7 +189,7 @@
if(stamina > DAMAGE_PRECISION)
owner.update_stamina()
consider_processing()
- check_disabled()
+ update_disabled()
return update_bodypart_damage_state()
//Heals brute and burn damage for the organ. Returns 1 if the damage-icon states changed at all.
@@ -209,7 +209,7 @@
if(owner && updating_health)
owner.updatehealth()
consider_processing()
- check_disabled()
+ update_disabled()
return update_bodypart_damage_state()
//Returns total damage.
@@ -220,7 +220,24 @@
return total
//Checks disabled status thresholds
-/obj/item/bodypart/proc/check_disabled()
+
+//Checks disabled status thresholds
+/obj/item/bodypart/proc/update_disabled()
+ set_disabled(is_disabled())
+
+/obj/item/bodypart/proc/is_disabled()
+ if(HAS_TRAIT(owner, TRAIT_PARALYSIS))
+ return BODYPART_DISABLED_PARALYSIS
+ if(can_dismember() && !HAS_TRAIT(owner, TRAIT_NODISMEMBER))
+ . = disabled //inertia, to avoid limbs healing 0.1 damage and being re-enabled
+ if((get_damage(TRUE) >= max_damage))
+ return BODYPART_DISABLED_DAMAGE
+ if(disabled && (get_damage(TRUE) <= (max_damage * 0.5)))
+ return BODYPART_NOT_DISABLED
+ else
+ return BODYPART_NOT_DISABLED
+
+/obj/item/bodypart/proc/check_disabled() //This might be depreciated and should be safe to remove.
if(!can_dismember() || HAS_TRAIT(owner, TRAIT_NODISMEMBER))
return
if(!disabled && (get_damage(TRUE) >= max_damage))
@@ -228,7 +245,8 @@
else if(disabled && (get_damage(TRUE) <= (max_damage * 0.5)))
set_disabled(FALSE)
-/obj/item/bodypart/proc/set_disabled(new_disabled = TRUE)
+
+/obj/item/bodypart/proc/set_disabled(new_disabled)
if(disabled == new_disabled)
return
disabled = new_disabled
@@ -546,6 +564,11 @@
max_stamina_damage = 200
var/obj/item/cavity_item
+/obj/item/bodypart/chest/can_dismember(obj/item/I)
+ if(!((owner.stat == DEAD) || owner.InFullCritical()))
+ return FALSE
+ return ..()
+
/obj/item/bodypart/chest/Destroy()
if(cavity_item)
qdel(cavity_item)
@@ -601,13 +624,27 @@
px_y = 0
stam_heal_tick = 2
-/obj/item/bodypart/l_arm/set_disabled(new_disabled = TRUE)
- ..()
- if(disabled)
- to_chat(owner, "Your [name] is too damaged to function!")
- owner.emote("scream")
+/obj/item/bodypart/l_arm/is_disabled()
+ if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM))
+ return BODYPART_DISABLED_PARALYSIS
+ return ..()
+
+/obj/item/bodypart/l_arm/set_disabled(new_disabled)
+ . = ..()
+ if(disabled == new_disabled)
+ return
+ if(disabled == BODYPART_DISABLED_DAMAGE)
+ if(owner.stat > UNCONSCIOUS)
+ owner.emote("scream")
+ if(. && (owner.stat > DEAD))
+ to_chat(owner, "Your [name] is too damaged to function!")
if(held_index)
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
+ else if(disabled == BODYPART_DISABLED_PARALYSIS)
+ if(. && (owner.stat > DEAD))
+ to_chat(owner, "You can't feel your [name]!")
+ if(held_index)
+ owner.dropItemToGround(owner.get_item_for_held_index(held_index))
if(owner.hud_used)
var/obj/screen/inventory/hand/L = owner.hud_used.hand_slots["[held_index]"]
if(L)
@@ -652,18 +689,33 @@
stam_heal_tick = 2
max_stamina_damage = 50
-/obj/item/bodypart/r_arm/set_disabled(new_disabled = TRUE)
- ..()
- if(disabled)
- to_chat(owner, "Your [name] is too damaged to function!")
- owner.emote("scream")
+/obj/item/bodypart/r_arm/is_disabled()
+ if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM))
+ return BODYPART_DISABLED_PARALYSIS
+ return ..()
+
+/obj/item/bodypart/r_arm/set_disabled(new_disabled)
+ . = ..()
+ if(disabled == new_disabled)
+ return
+ if(disabled == BODYPART_DISABLED_DAMAGE)
+ if(owner.stat > UNCONSCIOUS)
+ owner.emote("scream")
+ if(. && (owner.stat > DEAD))
+ to_chat(owner, "Your [name] is too damaged to function!")
if(held_index)
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
+ else if(disabled == BODYPART_DISABLED_PARALYSIS)
+ if(. && (owner.stat > DEAD))
+ to_chat(owner, "You can't feel your [name]!")
+ if(held_index)
+ owner.dropItemToGround(owner.get_item_for_held_index(held_index))
if(owner.hud_used)
var/obj/screen/inventory/hand/R = owner.hud_used.hand_slots["[held_index]"]
if(R)
R.update_icon()
+
/obj/item/bodypart/r_arm/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_r_arm"
@@ -700,11 +752,24 @@
stam_heal_tick = 2
max_stamina_damage = 50
-/obj/item/bodypart/l_leg/set_disabled(new_disabled = TRUE)
- ..()
- if(disabled)
- to_chat(owner, "Your [name] is too damaged to function!")
- owner.emote("scream")
+/obj/item/bodypart/l_leg/is_disabled()
+ if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG))
+ return BODYPART_DISABLED_PARALYSIS
+ return ..()
+
+/obj/item/bodypart/l_leg/set_disabled(new_disabled)
+ . = ..()
+ if(disabled == new_disabled)
+ return
+ if(disabled == BODYPART_DISABLED_DAMAGE)
+ if(owner.stat > UNCONSCIOUS)
+ owner.emote("scream")
+ if(. && (owner.stat > DEAD))
+ to_chat(owner, "Your [name] is too damaged to function!")
+ else if(disabled == BODYPART_DISABLED_PARALYSIS)
+ if(. && (owner.stat > DEAD))
+ to_chat(owner, "You can't feel your [name]!")
+
/obj/item/bodypart/l_leg/digitigrade
name = "left digitigrade leg"
@@ -747,11 +812,23 @@
max_stamina_damage = 50
stam_heal_tick = 2
-/obj/item/bodypart/r_leg/set_disabled(new_disabled = TRUE)
- ..()
- if(disabled)
- to_chat(owner, "Your [name] is too damaged to function!")
- owner.emote("scream")
+/obj/item/bodypart/r_leg/is_disabled()
+ if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG))
+ return BODYPART_DISABLED_PARALYSIS
+ return ..()
+
+/obj/item/bodypart/r_leg/set_disabled(new_disabled)
+ . = ..()
+ if(disabled == new_disabled)
+ return
+ if(disabled == BODYPART_DISABLED_DAMAGE)
+ if(owner.stat > UNCONSCIOUS)
+ owner.emote("scream")
+ if(. && (owner.stat > DEAD))
+ to_chat(owner, "Your [name] is too damaged to function!")
+ else if(disabled == BODYPART_DISABLED_PARALYSIS)
+ if(. && (owner.stat > DEAD))
+ to_chat(owner, "You can't feel your [name]!")
/obj/item/bodypart/r_leg/digitigrade
name = "right digitigrade leg"
diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm
index e7ab37b021..c8b8d17d71 100644
--- a/code/modules/surgery/organs/augments_arms.dm
+++ b/code/modules/surgery/organs/augments_arms.dm
@@ -129,11 +129,14 @@
holder = null
if(contents.len == 1)
Extend(contents[1])
- else // TODO: make it similar to borg's storage-like module selection
- var/obj/item/choise = input("Activate which item?", "Arm Implant", null, null) as null|anything in items_list
- if(owner && owner == usr && owner.stat != DEAD && (src in owner.internal_organs) && !holder && istype(choise) && (choise in contents))
- // This monster sanity check is a nice example of how bad input() is.
- Extend(choise)
+ else
+ var/list/choice_list = list()
+ for(var/obj/item/I in items_list)
+ choice_list[I] = getFlatIcon(I)
+ var/obj/item/choice = show_radial_menu(owner, owner, choice_list)
+ if(owner && owner == usr && owner.stat != DEAD && (src in owner.internal_organs) && !holder && (choice in contents))
+ // This monster sanity check is a nice example of how bad input is.
+ Extend(choice)
else
Retract()
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/unit_tests/reagent_recipe_collisions.dm b/code/modules/unit_tests/reagent_recipe_collisions.dm
index 31027c2cd3..20e875422f 100644
--- a/code/modules/unit_tests/reagent_recipe_collisions.dm
+++ b/code/modules/unit_tests/reagent_recipe_collisions.dm
@@ -11,57 +11,5 @@
for(var/i2 in (i+1) to reactions.len)
var/datum/chemical_reaction/r1 = reactions[i]
var/datum/chemical_reaction/r2 = reactions[i2]
- if(recipes_do_conflict(r1, r2))
+ if(chem_recipes_do_conflict(r1, r2))
Fail("Chemical recipe conflict between [r1.type] and [r2.type]")
-
-/datum/unit_test/reagent_recipe_collisions/proc/recipes_do_conflict(datum/chemical_reaction/r1, datum/chemical_reaction/r2)
- //do the non-list tests first, because they are cheaper
- if(r1.required_container != r2.required_container)
- return FALSE
- if(r1.is_cold_recipe == r2.is_cold_recipe)
- if(r1.required_temp != r2.required_temp)
- //one reaction requires a more extreme temperature than the other, so there is no conflict
- return FALSE
- else
- var/datum/chemical_reaction/cold_one = r1.is_cold_recipe ? r1 : r2
- var/datum/chemical_reaction/warm_one = r1.is_cold_recipe ? r2 : r1
- if(cold_one.required_temp < warm_one.required_temp)
- //the range of temperatures does not overlap, so there is no conflict
- return FALSE
-
- //find the reactions with the shorter and longer required_reagents list
- var/datum/chemical_reaction/long_req
- var/datum/chemical_reaction/short_req
- if(r1.required_reagents.len > r2.required_reagents.len)
- long_req = r1
- short_req = r2
- else if(r1.required_reagents.len < r2.required_reagents.len)
- long_req = r2
- short_req = r1
- else
- //if they are the same length, sort instead by the length of the catalyst list
- //this is important if the required_reagents lists are the same
- if(r1.required_catalysts.len > r2.required_catalysts.len)
- long_req = r1
- short_req = r2
- else
- long_req = r2
- short_req = r1
-
-
- //check if the shorter reaction list is a subset of the longer one
- var/list/overlap = r1.required_reagents & r2.required_reagents
- if(overlap.len != short_req.required_reagents.len)
- //there is at least one reagent in the short list that is not in the long list, so there is no conflict
- return FALSE
-
- //check to see if the shorter reaction's catalyst list is also a subset of the longer reaction's catalyst list
- //if the longer reaction's catalyst list is a subset of the shorter ones, that is fine
- //if the reaction lists are the same, the short reaction will have the shorter required_catalysts list, so it will register as a conflict
- var/list/short_minus_long_catalysts = short_req.required_catalysts - long_req.required_catalysts
- if(short_minus_long_catalysts.len)
- //there is at least one unique catalyst for the short reaction, so there is no conflict
- return FALSE
-
- //if we got this far, the longer reaction will be impossible to create if the shorter one is earlier in GLOB.chemical_reactions_list, and will require the reagents to be added in a particular order otherwise
- return TRUE
\ No newline at end of file
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index 871de715df..af1c954c5b 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -109,72 +109,194 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/discounts
category = "Discounted Gear"
-// Nuclear Operative (Special Offers)
-/datum/uplink_item/nukeoffer
- category = "Special Offers"
+//All bundles and telecrystals
+/datum/uplink_item/bundles_TC
+ category = "Bundles and Telecrystals"
surplus = 0
- include_modes = list(/datum/game_mode/nuclear)
cant_discount = TRUE
-/datum/uplink_item/nukeoffer/c20r
- name = "C-20r bundle"
- desc = "Old faithful: The classic C-20r, bundled with two magazines, and a (surplus) suppressor at discount price."
- item = /obj/item/storage/backpack/duffelbag/syndie/c20rbundle
- cost = 14 // normally 16
-
-/datum/uplink_item/nukeoffer/bulldog
- name = "Bulldog bundle"
- desc = "Lean and mean: Optimised for people that want to get up close and personal. Contains the popular \
- Bulldog shotgun, two 12g drums, and a pair of Thermal imaging goggles."
- item = /obj/item/storage/backpack/duffelbag/syndie/bulldogbundle
- cost = 13 // normally 16
-
-/datum/uplink_item/nukeoffer/medical
- name = "Medical bundle"
- desc = "The support specialist: Aid your fellow operatives with this medical bundle. Contains a Donksoft machine gun, \
- a box of ammo, and a pair of magboots to rescue your friends in no-gravity environments."
- item = /obj/item/storage/backpack/duffelbag/syndie/med/medicalbundle
- cost = 15 // normally 20
-
-/datum/uplink_item/nukeoffer/sniper
- name = "Sniper bundle"
- desc = "Elegant and refined: Contains a collapsed sniper rifle in an expensive carrying case, a hollow-point \
- a soporific knockout magazine, a free surplus supressor, and a worn out suit and tie."
- item = /obj/item/storage/briefcase/sniperbundle
- cost = 20 // normally 26
-
-/datum/uplink_item/nukeoffer/chemical
+/datum/uplink_item/bundles_TC/chemical
name = "Bioterror bundle"
desc = "For the madman: Contains Bioterror spray, Bioterror grenade, chemicals, syringe gun, box of syringes,\
Donksoft assault rifle, and some darts. Remember: Seal suit and equip internals before use."
item = /obj/item/storage/backpack/duffelbag/syndie/med/bioterrorbundle
cost = 30 // normally 42
+ include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/nukeoffer/firestarter
+/datum/uplink_item/bundles_TC/bulldog
+ name = "Bulldog bundle"
+ desc = "Lean and mean: Optimised for people that want to get up close and personal. Contains the popular \
+ Bulldog shotgun, two 12g drums, and a pair of Thermal imaging goggles."
+ item = /obj/item/storage/backpack/duffelbag/syndie/bulldogbundle
+ cost = 13 // normally 16
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/c20r
+ name = "C-20r bundle"
+ desc = "Old faithful: The classic C-20r, bundled with two magazines, and a (surplus) suppressor at discount price."
+ item = /obj/item/storage/backpack/duffelbag/syndie/c20rbundle
+ cost = 14 // normally 16
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/cybernetics_bundle
+ name = "Cybernetic Implants Bundle"
+ desc = "A random selection of cybernetic implants. Guaranteed 5 high quality implants. Comes with an autosurgeon."
+ item = /obj/item/storage/box/cyber_implants
+ cost = 40
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/medical
+ name = "Medical bundle"
+ desc = "The support specialist: Aid your fellow operatives with this medical bundle. Contains a Donksoft machine gun, \
+ a box of ammo, and a pair of magboots to rescue your friends in no-gravity environments."
+ item = /obj/item/storage/backpack/duffelbag/syndie/med/medicalbundle
+ cost = 15 // normally 20
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/modular
+ name = "Modular Pistol Kit"
+ desc = "A heavy briefcase containing one modular pistol (chambered in 10mm), one supressor, and spare ammunition, including a box of soporific ammo. \
+ Includes a suit jacket that is padded with a robust liner."
+ item = /obj/item/storage/briefcase/modularbundle
+ cost = 12
+
+/datum/uplink_item/bundles_TC/shredder
+ name = "Shredder bundle"
+ desc = "A truly horrific weapon designed simply to maim its victim, the CX Shredder is banned by several intergalactic treaties. \
+ You'll get two of them with this. And spare ammo to boot. And we'll throw in an extra elite hardsuit and chest rig to hold them all!"
+ item = /obj/item/storage/backpack/duffelbag/syndie/shredderbundle
+ cost = 30 // normally 41
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/sniper
+ name = "Sniper bundle"
+ desc = "Elegant and refined: Contains a collapsed sniper rifle in an expensive carrying case, a hollow-point \
+ a soporific knockout magazine, a free surplus supressor, and a worn out suit and tie."
+ item = /obj/item/storage/briefcase/sniperbundle
+ cost = 20 // normally 26
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/firestarter
name = "Spetsnaz Pyro bundle"
desc = "For systematic suppression of carbon lifeforms in close range: Contains a specialist Pyrotechnic equipment, foreign pistol, two magazines, a pipebomb, and a stimulant syringe."
item = /obj/item/storage/backpack/duffelbag/syndie/firestarter
cost = 30
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/bundle
+ name = "Syndicate Bundle"
+ desc = "Syndicate Bundles are specialized groups of items that arrive in a plain box. \
+ These items are collectively worth more than 20 telecrystals, but you do not know which specialization \
+ you will receive."
+ item = /obj/item/storage/box/syndicate
+ cost = 20
+ exclude_modes = list(/datum/game_mode/nuclear)
+ cant_discount = TRUE
+
+/datum/uplink_item/bundles_TC/surplus
+ name = "Syndicate Surplus Crate"
+ desc = "A dusty crate from the back of the Syndicate warehouse. Rumored to contain a valuable assortment of items, \
+ but you never know. Contents are sorted to always be worth 50 TC."
+ item = /obj/structure/closet/crate
+ cost = 20
+ player_minimum = 25
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+ cant_discount = TRUE
+ var/starting_crate_value = 50
+
+/datum/uplink_item/bundles_TC/surplus/super
+ name = "Super Surplus Crate"
+ desc = "A dusty SUPER-SIZED from the back of the Syndicate warehouse. Rumored to contain a valuable assortment of items, \
+ but you never know. Contents are sorted to always be worth 125 TC."
+ cost = 40
+ player_minimum = 40
+ starting_crate_value = 125
+
+/datum/uplink_item/bundles_TC/surplus/purchase(mob/user, datum/component/uplink/U)
+ var/list/uplink_items = get_uplink_items(SSticker && SSticker.mode? SSticker.mode : null, FALSE)
+
+ var/crate_value = starting_crate_value
+ var/obj/structure/closet/crate/C = spawn_item(/obj/structure/closet/crate, user)
+ if(U.purchase_log)
+ U.purchase_log.LogPurchase(C, src, cost)
+ while(crate_value)
+ var/category = pick(uplink_items)
+ var/item = pick(uplink_items[category])
+ var/datum/uplink_item/I = uplink_items[category][item]
+
+ if(!I.surplus || prob(100 - I.surplus))
+ continue
+ if(crate_value < I.cost)
+ continue
+ crate_value -= I.cost
+ var/obj/goods = new I.item(C)
+ if(U.purchase_log)
+ U.purchase_log.LogPurchase(goods, I, 0)
+ return C
+
+/datum/uplink_item/bundles_TC/random
+ name = "Random Item"
+ desc = "Picking this will purchase a random item. Useful if you have some TC to spare or if you haven't decided on a strategy yet."
+ item = /obj/effect/gibspawner/generic // non-tangible item because techwebs use this path to determine illegal tech
+ cost = 0
+ cant_discount = TRUE
+
+/datum/uplink_item/bundles_TC/random/purchase(mob/user, datum/component/uplink/U)
+ var/list/uplink_items = U.uplink_items
+ var/list/possible_items = list()
+ for(var/category in uplink_items)
+ for(var/item in uplink_items[category])
+ var/datum/uplink_item/I = uplink_items[category][item]
+ if(src == I || !I.item)
+ continue
+ if(U.telecrystals < I.cost)
+ continue
+ if(I.limited_stock == 0)
+ continue
+ possible_items += I
+
+ if(possible_items.len)
+ var/datum/uplink_item/I = pick(possible_items)
+ SSblackbox.record_feedback("tally", "traitor_random_uplink_items_gotten", 1, initial(I.name))
+ U.MakePurchase(user, I)
+
+/datum/uplink_item/bundles_TC/telecrystal
+ name = "1 Raw Telecrystal"
+ desc = "A telecrystal in its rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
+ item = /obj/item/stack/telecrystal
+ cost = 1
+ surplus = 0
+ cant_discount = TRUE
+ // Don't add telecrystals to the purchase_log since
+ // it's just used to buy more items (including itself!)
+ purchase_log_vis = FALSE
+
+/datum/uplink_item/bundles_TC/telecrystal/five
+ name = "5 Raw Telecrystals"
+ desc = "Five telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
+ item = /obj/item/stack/telecrystal/five
+ cost = 5
+
+/datum/uplink_item/bundles_TC/telecrystal/twenty
+ name = "20 Raw Telecrystals"
+ desc = "Twenty telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
+ item = /obj/item/stack/telecrystal/twenty
+ cost = 20
// Dangerous Items
/datum/uplink_item/dangerous
category = "Conspicuous and Dangerous Weapons"
-/datum/uplink_item/dangerous/pistol
- name = "Stechkin Pistol"
- desc = "A small, easily concealable handgun that uses 10mm auto rounds in 8-round magazines and is compatible \
- with suppressors."
- item = /obj/item/gun/ballistic/automatic/pistol
- cost = 7
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/dangerous/revolver
- name = "Syndicate Revolver"
- desc = "A brutally simple syndicate revolver that fires .357 Magnum rounds and has 7 chambers."
- item = /obj/item/gun/ballistic/revolver
- cost = 13
- surplus = 50
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/dangerous/antitank
+ name = "Anti Tank Pistol"
+ desc = "Essentially amounting to a sniper rifle with no stock and barrel (or indeed, any rifling at all), \
+ this extremely dubious pistol is guaranteed to dislocate your wrists and hit the broad side of a barn! \
+ Uses sniper ammo. \
+ Bullets tend to veer off-course. We are not responsible for any unintentional damage or injury resulting from inaacuracy."
+ item = /obj/item/gun/ballistic/automatic/pistol/antitank/syndicate
+ cost = 14
+ surplus = 25
+ include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/dangerous/pie_cannon
name = "Banana Cream Pie Cannon"
@@ -184,6 +306,42 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
surplus = 0
include_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/dangerous/bananashield
+ name = "Bananium Energy Shield"
+ desc = "A clown's most powerful defensive weapon, this personal shield provides near immunity to ranged energy attacks \
+ by bouncing them back at the ones who fired them. It can also be thrown to bounce off of people, slipping them, \
+ and returning to you even if you miss. WARNING: DO NOT ATTEMPT TO STAND ON SHIELD WHILE DEPLOYED, EVEN IF WEARING ANTI-SLIP SHOES."
+ item = /obj/item/shield/energy/bananium
+ cost = 16
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/dangerous/clownsword
+ name = "Bananium Energy Sword"
+ desc = "An energy sword that deals no damage, but will slip anyone it contacts, be it by melee attack, thrown \
+ impact, or just stepping on it. Beware friendly fire, as even anti-slip shoes will not protect against it."
+ item = /obj/item/melee/transforming/energy/sword/bananium
+ cost = 3
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/dangerous/bioterror
+ name = "Biohazardous Chemical Sprayer"
+ desc = "A chemical sprayer that allows a wide dispersal of selected chemicals. Especially tailored by the Tiger \
+ Cooperative, the deadly blend it comes stocked with will disorient, damage, and disable your foes... \
+ Use with extreme caution, to prevent exposure to yourself and your fellow operatives."
+ item = /obj/item/reagent_containers/spray/chemsprayer/bioterror
+ cost = 20
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/dangerous/throwingweapons
+ name = "Box of Throwing Weapons"
+ desc = "A box of shurikens and reinforced bolas from ancient Earth martial arts. They are highly effective \
+ throwing weapons. The bolas can knock a target down and the shurikens will embed into limbs."
+ item = /obj/item/storage/box/syndie_kit/throwing_weapons
+ cost = 3
+
/datum/uplink_item/dangerous/shotgun
name = "Bulldog Shotgun"
desc = "A fully-loaded semi-automatic drum-fed shotgun. Compatible with all 12g rounds. Designed for close \
@@ -202,86 +360,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
surplus = 40
include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/dangerous/carbine
- name = "M-90gl Carbine"
- desc = "A fully-loaded, specialized three-round burst carbine that fires 5.56mm ammunition from a 30 round magazine \
- with a togglable 40mm under-barrel grenade launcher."
- item = /obj/item/gun/ballistic/automatic/m90
- cost = 18
- surplus = 50
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/dangerous/machinegun
- name = "L6 Squad Automatic Weapon"
- desc = "A fully-loaded Aussec Armoury belt-fed machine gun. \
- This deadly weapon has a massive 50-round magazine of devastating 1.95x129mm ammunition."
- item = /obj/item/gun/ballistic/automatic/l6_saw
- cost = 18
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/dangerous/grenadier
- name = "Grenadier's belt"
- desc = "A belt of a large variety of lethally dangerous and destructive grenades."
- item = /obj/item/storage/belt/grenade/full
- include_modes = list(/datum/game_mode/nuclear)
- cost = 22
- surplus = 0
-
-/datum/uplink_item/dangerous/sniper
- name = "Sniper Rifle"
- desc = "Ranged fury, Syndicate style. Guaranteed to cause shock and awe or your TC back!"
- item = /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate
- cost = 16
- surplus = 25
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/dangerous/bolt_action
- name = "Surplus Rifle"
- desc = "A horribly outdated bolt action weapon. You've got to be desperate to use this."
- item = /obj/item/gun/ballistic/shotgun/boltaction
- cost = 2
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/dangerous/crossbow
- name = "Miniature Energy Crossbow"
- desc = "A short bow mounted across a tiller in miniature. Small enough to \
- fit into a pocket or slip into a bag unnoticed. It will synthesize \
- and fire bolts tipped with a paralyzing toxin that will briefly stun \
- targets and cause them to slur as if inebriated. It can produce an \
- infinite number of bolts, but takes time to automatically recharge \
- after each shot."
- item = /obj/item/gun/energy/kinetic_accelerator/crossbow
- cost = 12
- surplus = 50
- exclude_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/dangerous/flamethrower
- name = "Flamethrower"
- desc = "A flamethrower, fueled by a portion of highly flammable biotoxins stolen previously from Nanotrasen \
- stations. Make a statement by roasting the filth in their own greed. Use with caution."
- item = /obj/item/flamethrower/full/tank
- cost = 4
- surplus = 40
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/dangerous/sword
- name = "Energy Sword"
- desc = "The energy sword is an edged weapon with a blade of pure energy. The sword is small enough to be \
- pocketed when inactive. Activating it produces a loud, distinctive noise."
- item = /obj/item/melee/transforming/energy/sword/saber
- cost = 8
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/dangerous/clownsword
- name = "Bananium Energy Sword"
- desc = "An energy sword that deals no damage, but will slip anyone it contacts, be it by melee attack, thrown \
- impact, or just stepping on it. Beware friendly fire, as even anti-slip shoes will not protect against it."
- item = /obj/item/melee/transforming/energy/sword/bananium
- cost = 3
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
-
/datum/uplink_item/dangerous/doublesword
name = "Double-Bladed Energy Sword"
desc = "The double-bladed energy sword does slightly more damage than a standard energy sword and will deflect \
@@ -294,6 +372,90 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/dangerous/doublesword/get_discount()
return pick(4;0.8,2;0.65,1;0.5)
+/datum/uplink_item/dangerous/cxneb
+ name = "Dragon's Tooth Non-Eutactic Blade"
+ desc = "An illegal modification of a weapon that is functionally identical to the energy sword, \
+ the Non-Eutactic Blade (NEB) forges a hardlight blade on-demand, \
+ generating an extremely sharp, unbreakable edge that is guaranteed to satisfy your every need. \
+ This particular model has a polychromic hardlight generator, allowing you to murder in style! \
+ The illegal modifications bring this weapon up to par with the classic energy sword, and also gives it the energy sword's distinctive sounds."
+ item = /obj/item/melee/transforming/energy/sword/cx/traitor
+ cost = 8
+
+/datum/uplink_item/dangerous/sword
+ name = "Energy Sword"
+ desc = "The energy sword is an edged weapon with a blade of pure energy. The sword is small enough to be \
+ pocketed when inactive. Activating it produces a loud, distinctive noise."
+ item = /obj/item/melee/transforming/energy/sword/saber
+ cost = 8
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/dangerous/shield
+ name = "Energy Shield"
+ desc = "An incredibly useful personal shield projector, capable of reflecting energy projectiles and defending \
+ against other attacks. Pair with an Energy Sword for a killer combination."
+ item = /obj/item/shield/energy
+ cost = 16
+ surplus = 20
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/dangerous/flamethrower
+ name = "Flamethrower"
+ desc = "A flamethrower, fueled by a portion of highly flammable biotoxins stolen previously from Nanotrasen \
+ stations. Make a statement by roasting the filth in their own greed. Use with caution."
+ item = /obj/item/flamethrower/full/tank
+ cost = 4
+ surplus = 40
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/dangerous/flechettegun
+ name = "Flechette Launcher"
+ desc = "A compact bullpup that fires micro-flechettes.\
+ Flechettes have very poor performance idividually, but can be very deadly in numbers. \
+ Pre-loaded with armor piercing flechettes that are capable of puncturing most kinds of armor."
+ item = /obj/item/gun/ballistic/automatic/flechette
+ cost = 12
+ surplus = 30
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/badass/rapid
+ name = "Gloves of the North Star"
+ desc = "These gloves let the user punch people very fast. Does not improve weapon attack speed or the meaty fists of a hulk."
+ item = /obj/item/clothing/gloves/rapid
+ cost = 8
+
+/datum/uplink_item/dangerous/guardian
+ name = "Holoparasites"
+ desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an \
+ organic host as a home base and source of fuel."
+ item = /obj/item/storage/box/syndie_kit/guardian
+ cost = 15
+ refundable = TRUE
+ cant_discount = TRUE
+ surplus = 0
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+ player_minimum = 25
+ restricted = TRUE
+ refund_path = /obj/item/guardiancreator/tech/choose/traitor
+
+/datum/uplink_item/dangerous/machinegun
+ name = "L6 Squad Automatic Weapon"
+ desc = "A fully-loaded Aussec Armoury belt-fed machine gun. \
+ This deadly weapon has a massive 50-round magazine of devastating 1.95x129mm ammunition."
+ item = /obj/item/gun/ballistic/automatic/l6_saw
+ cost = 18
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/dangerous/carbine
+ name = "M-90gl Carbine"
+ desc = "A fully-loaded, specialized three-round burst carbine that fires 5.56mm ammunition from a 30 round magazine \
+ with a togglable 40mm under-barrel grenade launcher."
+ item = /obj/item/gun/ballistic/automatic/m90
+ cost = 18
+ surplus = 50
+ include_modes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/dangerous/powerfist
name = "Power Fist"
desc = "The power-fist is a metal gauntlet with a built-in piston-ram powered by an external gas supply.\
@@ -303,46 +465,36 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/melee/powerfist
cost = 8
-/datum/uplink_item/badass/combatglovesplus
- name = "Combat Gloves Plus"
- desc = "A pair of gloves that are fireproof and shock resistant, however unlike the regular Combat Gloves this one uses nanotechnology \
- to learn the abilities of krav maga to the wearer."
- item = /obj/item/clothing/gloves/krav_maga/combatglovesplus
- cost = 5
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/dangerous/sniper
+ name = "Sniper Rifle"
+ desc = "Ranged fury, Syndicate style. Guaranteed to cause shock and awe or your TC back!"
+ item = /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate
+ cost = 16
+ surplus = 25
+ include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/dangerous/emp
- name = "EMP Grenades and Implanter Kit"
- desc = "A box that contains two EMP grenades and an EMP implant. Useful to disrupt communication, \
- security's energy weapons, and silicon lifeforms when you're in a tight spot."
- item = /obj/item/storage/box/syndie_kit/emp
- cost = 2
-
-/datum/uplink_item/dangerous/syndicate_minibomb
- name = "Syndicate Minibomb"
- desc = "The minibomb is a grenade with a five-second fuse. Upon detonation, it will create a small hull breach \
- in addition to dealing high amounts of damage to nearby personnel."
- item = /obj/item/grenade/syndieminibomb
- cost = 6
+/datum/uplink_item/dangerous/pistol
+ name = "Stechkin Pistol"
+ desc = "A small, easily concealable handgun that uses 10mm auto rounds in 8-round magazines and is compatible \
+ with suppressors."
+ item = /obj/item/gun/ballistic/automatic/pistol
+ cost = 7
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/dangerous/bombanana
- name = "Bombanana"
- desc = "A banana with an explosive taste! discard the peel quickly, as it will explode with the force of a syndicate minibomb \
- a few seconds after the banana is eaten."
- item = /obj/item/reagent_containers/food/snacks/grown/banana/bombanana
- cost = 4 //it is a bit cheaper than a minibomb because you have to take off your helmet to eat it, which is how you arm it
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/dangerous/bolt_action
+ name = "Surplus Rifle"
+ desc = "A horribly outdated bolt action weapon. You've got to be desperate to use this."
+ item = /obj/item/gun/ballistic/shotgun/boltaction
+ cost = 2
+ include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/dangerous/tearstache
- name = "Teachstache Grenade"
- desc = "A teargas grenade that launches sticky moustaches onto the face of anyone not wearing a clown or mime mask. The moustaches will \
- remain attached to the face of all targets for one minute, preventing the use of breath masks and other such devices."
- item = /obj/item/grenade/chem_grenade/teargas/moustache
- cost = 3
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/dangerous/revolver
+ name = "Syndicate Revolver"
+ desc = "A brutally simple syndicate revolver that fires .357 Magnum rounds and has 7 chambers."
+ item = /obj/item/gun/ballistic/revolver/syndie
+ cost = 13
+ surplus = 50
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
/datum/uplink_item/dangerous/foamsmg
name = "Toy Submachine Gun"
@@ -361,65 +513,132 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
surplus = 0
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/dangerous/viscerators
- name = "Viscerator Delivery Grenade"
- desc = "A unique grenade that deploys a swarm of viscerators upon activation, which will chase down and shred \
- any non-operatives in the area."
- item = /obj/item/grenade/spawnergrenade/manhacks
- cost = 5
- surplus = 35
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/dangerous/foampistol
+ name = "Toy Gun with Riot Darts"
+ desc = "An innocent-looking toy pistol designed to fire foam darts. Comes loaded with riot-grade \
+ darts effective at incapacitating a target."
+ item = /obj/item/gun/ballistic/automatic/toy/pistol/riot
+ cost = 3
+ surplus = 10
-/datum/uplink_item/dangerous/bioterrorfoam
- name = "Chemical Foam Grenade"
- desc = "A powerful chemical foam grenade which creates a deadly torrent of foam that will mute, blind, confuse, \
- mutate, and irritate carbon lifeforms. Specially brewed by Tiger Cooperative chemical weapons specialists \
- using additional spore toxin. Ensure suit is sealed before use."
- item = /obj/item/grenade/chem_grenade/bioterrorfoam
- cost = 5
- surplus = 35
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+// Stealthy Weapons
+/datum/uplink_item/stealthy_weapons
+ category = "Stealthy and Inconspicuous Weapons"
-/datum/uplink_item/dangerous/bioterror
- name = "Biohazardous Chemical Sprayer"
- desc = "A chemical sprayer that allows a wide dispersal of selected chemicals. Especially tailored by the Tiger \
- Cooperative, the deadly blend it comes stocked with will disorient, damage, and disable your foes... \
- Use with extreme caution, to prevent exposure to yourself and your fellow operatives."
- item = /obj/item/reagent_containers/spray/chemsprayer/bioterror
- cost = 20
+/datum/uplink_item/stealthy_weapons/combatglovesplus
+ name = "Combat Gloves Plus"
+ desc = "A pair of gloves that are fireproof and shock resistant, however unlike the regular Combat Gloves this one uses nanotechnology \
+ to learn the abilities of krav maga to the wearer."
+ item = /obj/item/clothing/gloves/krav_maga/combatglovesplus
+ cost = 5
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
surplus = 0
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/stealthy_weapons/virus_grenade
- name = "Fungal Tuberculosis Grenade"
- desc = "A primed bio-grenade packed into a compact box. Comes with five Bio Virus Antidote Kit (BVAK) \
- autoinjectors for rapid application on up to two targets each, a syringe, and a bottle containing \
- the BVAK solution."
- item = /obj/item/storage/box/syndie_kit/tuberculosisgrenade
- cost = 8
- surplus = 35
+/datum/uplink_item/stealthy_weapons/cqc
+ name = "CQC Manual"
+ desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing."
+ item = /obj/item/book/granter/martial/cqc
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
- restricted = TRUE
+ cost = 13
+ surplus = 0
-/datum/uplink_item/dangerous/guardian
- name = "Holoparasites"
- desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an \
- organic host as a home base and source of fuel."
- item = /obj/item/storage/box/syndie_kit/guardian
- cost = 18
+/datum/uplink_item/stealthy_weapons/dart_pistol
+ name = "Dart Pistol"
+ desc = "A miniaturized version of a normal syringe gun. It is very quiet when fired and can fit into any \
+ space a small item can."
+ item = /obj/item/gun/syringe/syndicate
+ cost = 4
+ surplus = 50
+
+/datum/uplink_item/stealthy_weapons/dehy_carp
+ name = "Dehydrated Space Carp"
+ desc = "Looks like a plush toy carp, but just add water and it becomes a real-life space carp! Activate in \
+ your hand before use so it knows not to kill you."
+ item = /obj/item/toy/plush/carpplushie/dehy_carp
+ cost = 1
+
+/datum/uplink_item/stealthy_weapons/edagger
+ name = "Energy Dagger"
+ desc = "A dagger made of energy that looks and functions as a pen when off."
+ item = /obj/item/pen/edagger
+ cost = 2
+
+/datum/uplink_item/stealthy_weapons/martialarts
+ name = "Martial Arts Scroll"
+ desc = "This scroll contains the secrets of an ancient martial arts technique. You will master unarmed combat, \
+ deflecting all ranged weapon fire, but you also refuse to use dishonorable ranged weaponry."
+ item = /obj/item/book/granter/martial/carp
+ cost = 17
surplus = 0
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
- player_minimum = 25
- restricted = TRUE
-/datum/uplink_item/dangerous/buzzkill
- name = "Buzzkill Grenade Box"
- desc = "A box with three grenades that release a swarm of angry bees upon activation. These bees indiscriminately attack friend or foe \
- with random toxins. Courtesy of the BLF and Tiger Cooperative."
- item = /obj/item/storage/box/syndie_kit/bee_grenades
- cost = 15
- surplus = 35
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/stealthy_weapons/crossbow
+ name = "Miniature Energy Crossbow"
+ desc = "A short bow mounted across a tiller in miniature. Small enough to \
+ fit into a pocket or slip into a bag unnoticed. It will synthesize \
+ and fire bolts tipped with a paralyzing toxin that will briefly stun \
+ targets and cause them to slur as if inebriated. It can produce an \
+ infinite number of bolts, but takes time to automatically recharge \
+ after each shot."
+ item = /obj/item/gun/energy/kinetic_accelerator/crossbow
+ cost = 12
+ surplus = 50
+ exclude_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/stealthy_weapons/traitor_chem_bottle
+ name = "Poison Kit"
+ desc = "An assortment of deadly chemicals packed into a compact box. Comes with a syringe for more precise application."
+ item = /obj/item/storage/box/syndie_kit/chemical
+ cost = 6
+ surplus = 50
+
+/datum/uplink_item/stealthy_weapons/romerol_kit
+ name = "Romerol"
+ desc = "A highly experimental bioterror agent which creates dormant nodules to be etched into the grey matter of the brain. On death, these nodules take control of the dead body, causing limited revivification, along with slurred speech, aggression, and the ability to infect others with this agent."
+ item = /obj/item/storage/box/syndie_kit/romerol
+ cost = 25
+ cant_discount = TRUE
+ exclude_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/stealthy_weapons/sleepy_pen
+ name = "Sleepy Pen"
+ desc = "A syringe disguised as a functional pen, filled with a potent mix of drugs, including a \
+ strong anesthetic and a chemical that prevents the target from speaking. \
+ The pen holds one dose of the mixture, and can be refilled. Note that before the target \
+ falls asleep, they will be able to move and act."
+ item = /obj/item/pen/sleepy
+ cost = 4
+ exclude_modes = list(/datum/game_mode/nuclear)
+
+datum/uplink_item/stealthy_weapons/taeclowndo_shoes
+ name = "Tae-clown-do Shoes"
+ desc = "A pair of shoes for the most elite agents of the honkmotherland. They grant the mastery of taeclowndo with some honk-fu moves as long as they're worn."
+ cost = 12
+ item = /obj/item/clothing/shoes/clown_shoes/taeclowndo
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/stealthy_weapons/suppressor
+ name = "Universal Suppressor"
+ desc = "Fitted for use on any small caliber weapon with a threaded barrel, this suppressor will silence the \
+ shots of the weapon for increased stealth and superior ambushing capability."
+ item = /obj/item/suppressor
+ cost = 1
+ surplus = 10
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/stealthy_weapons/soap
+ name = "Syndicate Soap"
+ desc = "A sinister-looking surfactant used to clean blood stains to hide murders and prevent DNA analysis. \
+ You can also drop it underfoot to slip people."
+ item = /obj/item/soap/syndie
+ cost = 1
+ surplus = 50
+
+/datum/uplink_item/stealthy_weapons/soap_clusterbang
+ name = "Slipocalypse Clusterbang"
+ desc = "A traditional clusterbang grenade with a payload consisting entirely of Syndicate soap. Useful in any scenario!"
+ item = /obj/item/grenade/clusterbuster/soap
+ cost = 6
// Ammunition
/datum/uplink_item/ammo
@@ -441,13 +660,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 2
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/ammo/pistolfire
- name = "10mm Incendiary Magazine"
- desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. Loaded with incendiary rounds which ignite the target."
- item = /obj/item/ammo_box/magazine/m10mm/fire
- cost = 2
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-
/datum/uplink_item/ammo/pistolhp
name = "10mm Hollow Point Magazine"
desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. These rounds are more damaging but ineffective against armour."
@@ -455,51 +667,35 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 3
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/ammo/pistolaps
- name = "9mm Handgun Magazine"
- desc = "An additional 15-round 9mm magazine, compatible with the Stetchkin APS pistol, found in the Spetsnaz Pyro bundle."
- item = /obj/item/ammo_box/magazine/pistolm9mm
+/datum/uplink_item/ammo/pistolfire
+ name = "10mm Incendiary Magazine"
+ desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. Loaded with incendiary rounds which ignite the target."
+ item = /obj/item/ammo_box/magazine/m10mm/fire
cost = 2
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/ammo/bolt_action
- name = "Surplus Rifle Clip"
- desc = "A stripper clip used to quickly load bolt action rifles. Contains 5 rounds."
- item = /obj/item/ammo_box/a762
- cost = 1
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/ammo/revolver
- name = ".357 Speed Loader"
- desc = "A speed loader that contains seven additional .357 Magnum rounds; usable with the Syndicate revolver. \
- For when you really need a lot of things dead."
- item = /obj/item/ammo_box/a357
- cost = 4
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/ammo/pistolzzz
+ name = "10mm Soporific Magazine"
+ desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. Loaded with soporific rounds that put the target to sleep. \
+ NOTE: Soporific is not instant acting due to the constraints of the round's scale. Will usually require three shots to take effect."
+ item = /obj/item/ammo_box/magazine/m10mm/soporific
+ cost = 2
+
/datum/uplink_item/ammo/shotgun
cost = 2
include_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/ammo/shotgun/bag
+ name = "12g Ammo Duffel Bag"
+ desc = "A duffel bag filled with enough 12g ammo to supply an entire team, at a discounted price."
+ item = /obj/item/storage/backpack/duffelbag/syndie/ammo/shotgun
+ cost = 12
+
/datum/uplink_item/ammo/shotgun/buck
name = "12g Buckshot Drum"
desc = "An additional 8-round buckshot magazine for use with the Bulldog shotgun. Front towards enemy."
item = /obj/item/ammo_box/magazine/m12g
-/datum/uplink_item/ammo/shotgun/slug
- name = "12g Slug Drum"
- desc = "An additional 8-round slug magazine for use with the Bulldog shotgun. \
- Now 8 times less likely to shoot your pals."
- cost = 3
- item = /obj/item/ammo_box/magazine/m12g/slug
-
-/datum/uplink_item/ammo/shotgun/stun
- name = "12g Stun Slug Drum"
- desc = "An alternative 8-round stun slug magazine for use with the Bulldog shotgun. \
- Saying that they're completely non-lethal would be lying."
- item = /obj/item/ammo_box/magazine/m12g/stun
- include_modes = list(/datum/game_mode/nuclear)
-
/datum/uplink_item/ammo/shotgun/dragon
name = "12g Dragon's Breath Drum"
desc = "An alternative 8-round dragon's breath magazine for use in the Bulldog shotgun. \
@@ -520,18 +716,34 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/ammo_box/magazine/m12g/scatter
cost = 4 // most armor has less laser protection then bullet
-/datum/uplink_item/ammo/shotgun/bag
- name = "12g Ammo Duffel Bag"
- desc = "A duffel bag filled with enough 12g ammo to supply an entire team, at a discounted price."
- item = /obj/item/storage/backpack/duffelbag/syndie/ammo/shotgun
- cost = 12
-
-/datum/uplink_item/ammo/smg
- name = ".45 SMG Magazine"
- desc = "An additional 24-round .45 magazine suitable for use with the C-20r submachine gun. \
- These bullets pack a lot of punch that can knock most targets down, but do limited overall damage."
- item = /obj/item/ammo_box/magazine/smgm45
+/datum/uplink_item/ammo/shotgun/slug
+ name = "12g Slug Drum"
+ desc = "An additional 8-round slug magazine for use with the Bulldog shotgun. \
+ Now 8 times less likely to shoot your pals."
cost = 3
+ item = /obj/item/ammo_box/magazine/m12g/slug
+
+/datum/uplink_item/ammo/shotgun/stun
+ name = "12g Stun Slug Drum"
+ desc = "An alternative 8-round stun slug magazine for use with the Bulldog shotgun. \
+ Saying that they're completely non-lethal would be lying."
+ item = /obj/item/ammo_box/magazine/m12g/stun
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/ammo/revolver
+ name = ".357 Speed Loader"
+ desc = "A speed loader that contains seven additional .357 Magnum rounds; usable with the Syndicate revolver. \
+ For when you really need a lot of things dead."
+ item = /obj/item/ammo_box/a357
+ cost = 4
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/ammo/a40mm
+ name = "40mm Grenade"
+ desc = "A 40mm HE grenade for use with the M-90gl's under-barrel grenade launcher. \
+ Your teammates will ask you to not shoot these down small hallways."
+ item = /obj/item/ammo_casing/a40mm
+ cost = 2
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/smg/bag
@@ -541,6 +753,36 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 20
include_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/ammo/smg
+ name = ".45 SMG Magazine"
+ desc = "An additional 24-round .45 magazine suitable for use with the C-20r submachine gun. \
+ These bullets pack a lot of punch that can knock most targets down, but do limited overall damage."
+ item = /obj/item/ammo_box/magazine/smgm45
+ cost = 3
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/ammo/sniper
+ cost = 4
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/ammo/sniper/basic
+ name = ".50 Magazine"
+ desc = "An additional standard 6-round magazine for use with .50 sniper rifles."
+ item = /obj/item/ammo_box/magazine/sniper_rounds
+
+/datum/uplink_item/ammo/sniper/penetrator
+ name = ".50 Penetrator Magazine"
+ desc = "A 5-round magazine of penetrator ammo designed for use with .50 sniper rifles. \
+ Can pierce walls and multiple enemies."
+ item = /obj/item/ammo_box/magazine/sniper_rounds/penetrator
+ cost = 5
+
+/datum/uplink_item/ammo/sniper/soporific
+ name = ".50 Soporific Magazine"
+ desc = "A 3-round magazine of soporific ammo designed for use with .50 sniper rifles. Put your enemies to sleep today!"
+ item = /obj/item/ammo_box/magazine/sniper_rounds/soporific
+ cost = 6
+
/datum/uplink_item/ammo/carbine
name = "5.56mm Toploader Magazine"
desc = "An additional 30-round 5.56mm magazine; suitable for use with the M-90gl carbine. \
@@ -549,14 +791,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 4
include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/ammo/a40mm
- name = "40mm Grenade"
- desc = "A 40mm HE grenade for use with the M-90gl's under-barrel grenade launcher. \
- Your teammates will ask you to not shoot these down small hallways."
- item = /obj/item/ammo_casing/a40mm
- cost = 2
- include_modes = list(/datum/game_mode/nuclear)
-
/datum/uplink_item/ammo/machinegun
cost = 6
surplus = 0
@@ -568,12 +802,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
By the time you need to use this, you'll already be on a pile of corpses."
item = /obj/item/ammo_box/magazine/mm195x129
-/datum/uplink_item/ammo/machinegun/hollow
- name = "1.95x129mm (Hollow-Point) Box Magazine"
- desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; equipped with hollow-point tips to help \
- with the unarmored masses of crew."
- item = /obj/item/ammo_box/magazine/mm195x129/hollow
-
/datum/uplink_item/ammo/machinegun/ap
name = "1.95x129mm (Armor Penetrating) Box Magazine"
desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; equipped with special properties \
@@ -581,33 +809,41 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/ammo_box/magazine/mm195x129/ap
cost = 9
+/datum/uplink_item/ammo/machinegun/hollow
+ name = "1.95x129mm (Hollow-Point) Box Magazine"
+ desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; equipped with hollow-point tips to help \
+ with the unarmored masses of crew."
+ item = /obj/item/ammo_box/magazine/mm195x129/hollow
+
/datum/uplink_item/ammo/machinegun/incen
name = "1.95x129mm (Incendiary) Box Magazine"
desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; tipped with a special flammable \
mixture that'll ignite anyone struck by the bullet. Some men just want to watch the world burn."
item = /obj/item/ammo_box/magazine/mm195x129/incen
-/datum/uplink_item/ammo/sniper
- cost = 4
+/datum/uplink_item/ammo/pistolaps
+ name = "9mm Handgun Magazine"
+ desc = "An additional 15-round 9mm magazine, compatible with the Stetchkin APS pistol, found in the Spetsnaz Pyro bundle."
+ item = /obj/item/ammo_box/magazine/pistolm9mm
+ cost = 2
include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/ammo/sniper/basic
- name = ".50 Magazine"
- desc = "An additional standard 6-round magazine for use with .50 sniper rifles."
- item = /obj/item/ammo_box/magazine/sniper_rounds
+/datum/uplink_item/ammo/flechetteap
+ name = "Armor Piercing Flechette Magazine"
+ desc = "An additional 40-round flechette magazine; compatible with the Flechette Launcer. \
+ Loaded with armor piercing flechettes that very nearly ignore armor, but are not very effective agaisnt flesh."
+ item = /obj/item/ammo_box/magazine/flechette
+ cost = 2
+ include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/ammo/sniper/soporific
- name = ".50 Soporific Magazine"
- desc = "A 3-round magazine of soporific ammo designed for use with .50 sniper rifles. Put your enemies to sleep today!"
- item = /obj/item/ammo_box/magazine/sniper_rounds/soporific
- cost = 6
-
-/datum/uplink_item/ammo/sniper/penetrator
- name = ".50 Penetrator Magazine"
- desc = "A 5-round magazine of penetrator ammo designed for use with .50 sniper rifles. \
- Can pierce walls and multiple enemies."
- item = /obj/item/ammo_box/magazine/sniper_rounds/penetrator
- cost = 5
+/datum/uplink_item/ammo/flechettes
+ name = "Serrated Flechette Magazine"
+ desc = "An additional 40-round flechette magazine; compatible with the Flechette Launcer. \
+ Loaded with serrated flechettes that shreds flesh, but is stopped dead in its tracks by armor. \
+ These flechettes are highly likely to sever arteries, and even limbs."
+ item = /obj/item/ammo_box/magazine/flechette/s
+ cost = 2
+ include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/toydarts
name = "Box of Riot Darts"
@@ -624,12 +860,184 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 6
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/ammo/bolt_action
+ name = "Surplus Rifle Clip"
+ desc = "A stripper clip used to quickly load bolt action rifles. Contains 5 rounds."
+ item = /obj/item/ammo_box/a762
+ cost = 1
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/explosives
+ category = "Grenades and Explosives"
+
+/datum/uplink_item/explosives/bioterrorfoam
+ name = "Chemical Foam Grenade"
+ desc = "A powerful chemical foam grenade which creates a deadly torrent of foam that will mute, blind, confuse, \
+ mutate, and irritate carbon lifeforms. Specially brewed by Tiger Cooperative chemical weapons specialists \
+ using additional spore toxin. Ensure suit is sealed before use."
+ item = /obj/item/grenade/chem_grenade/bioterrorfoam
+ cost = 5
+ surplus = 35
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/bombanana
+ name = "Bombanana"
+ desc = "A banana with an explosive taste! discard the peel quickly, as it will explode with the force of a syndicate minibomb \
+ a few seconds after the banana is eaten."
+ item = /obj/item/reagent_containers/food/snacks/grown/banana/bombanana
+ cost = 4 //it is a bit cheaper than a minibomb because you have to take off your helmet to eat it, which is how you arm it
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/buzzkill
+ name = "Buzzkill Grenade Box"
+ desc = "A box with three grenades that release a swarm of angry bees upon activation. These bees indiscriminately attack friend or foe \
+ with random toxins. Courtesy of the BLF and Tiger Cooperative."
+ item = /obj/item/storage/box/syndie_kit/bee_grenades
+ cost = 15
+ surplus = 35
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/c4
+ name = "Composition C-4"
+ desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls, sabotage equipment, or connect \
+ an assembly to it in order to alter the way it detonates. It has a modifiable timer with a \
+ minimum setting of 10 seconds."
+ item = /obj/item/grenade/plastic/c4
+ cost = 1
+
+/datum/uplink_item/explosives/c4bag
+ name = "Bag of C-4 explosives"
+ desc = "Because sometimes quantity is quality. Contains 10 C-4 plastic explosives."
+ item = /obj/item/storage/backpack/duffelbag/syndie/c4
+ cost = 9 //10% discount!
+ cant_discount = TRUE
+
+/datum/uplink_item/explosives/x4bag
+ name = "Bag of X-4 explosives"
+ desc = "Contains 3 X-4 plastic explosives. Similar, but more powerful than C-4. X-4 can be placed on a solid surface, such as a wall or window, and it will \
+ blast through the wall, injuring anything on the opposite side, while being safer to the user. For when you want a wider, deeper, hole."
+ item = /obj/item/storage/backpack/duffelbag/syndie/x4
+ cost = 4 //
+ cant_discount = TRUE
+
+/datum/uplink_item/explosives/clown_bomb_clownops
+ name = "Clown Bomb"
+ desc = "The Clown bomb is a hilarious device capable of massive pranks. It has an adjustable timer, \
+ with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \
+ movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \
+ transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \
+ be defused, and some crew may attempt to do so."
+ item = /obj/item/sbeacondrop/clownbomb
+ cost = 15
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/detomatix
+ name = "Detomatix PDA Cartridge"
+ desc = "When inserted into a personal digital assistant, this cartridge gives you four opportunities to \
+ detonate PDAs of crewmembers who have their message feature enabled. \
+ The concussive effect from the explosion will knock the recipient out for a short period, and deafen \
+ them for longer. Beware, it has a chance to detonate your PDA."
+ item = /obj/item/cartridge/virus/syndicate
+ cost = 5
+ restricted = TRUE
+
+/datum/uplink_item/explosives/emp
+ name = "EMP Grenades and Implanter Kit"
+ desc = "A box that contains two EMP grenades and an EMP implant. Useful to disrupt communication, \
+ security's energy weapons, and silicon lifeforms when you're in a tight spot."
+ item = /obj/item/storage/box/syndie_kit/emp
+ cost = 2
+
+/datum/uplink_item/explosives/virus_grenade
+ name = "Fungal Tuberculosis Grenade"
+ desc = "A primed bio-grenade packed into a compact box. Comes with five Bio Virus Antidote Kit (BVAK) \
+ autoinjectors for rapid application on up to two targets each, a syringe, and a bottle containing \
+ the BVAK solution."
+ item = /obj/item/storage/box/syndie_kit/tuberculosisgrenade
+ cost = 8
+ surplus = 35
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+ restricted = TRUE
+
+/datum/uplink_item/explosives/grenadier
+ name = "Grenadier's belt"
+ desc = "A belt of a large variety of lethally dangerous and destructive grenades."
+ item = /obj/item/storage/belt/grenade/full
+ include_modes = list(/datum/game_mode/nuclear)
+ cost = 22
+ surplus = 0
+
+/datum/uplink_item/explosives/pizza_bomb
+ name = "Pizza Bomb"
+ desc = "A pizza box with a bomb cunningly attached to the lid. The timer needs to be set by opening the box; afterwards, \
+ opening the box again will trigger the detonation after the timer has elapsed. Comes with free pizza, for you or your target!"
+ item = /obj/item/pizzabox/bomb
+ cost = 6
+ surplus = 8
+
+/datum/uplink_item/explosives/syndicate_bomb
+ name = "Syndicate Bomb"
+ desc = "The Syndicate bomb is a fearsome device capable of massive destruction. It has an adjustable timer, \
+ with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \
+ movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \
+ transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \
+ be defused, and some crew may attempt to do so."
+ item = /obj/item/sbeacondrop/bomb
+ cost = 11
+
+/datum/uplink_item/explosives/syndicate_detonator
+ name = "Syndicate Detonator"
+ desc = "The Syndicate detonator is a companion device to the Syndicate bomb. Simply press the included button \
+ and an encrypted radio frequency will instruct all live Syndicate bombs to detonate. \
+ Useful for when speed matters or you wish to synchronize multiple bomb blasts. Be sure to stand clear of \
+ the blast radius before using the detonator."
+ item = /obj/item/syndicatedetonator
+ cost = 3
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/syndicate_minibomb
+ name = "Syndicate Minibomb"
+ desc = "The minibomb is a grenade with a five-second fuse. Upon detonation, it will create a small hull breach \
+ in addition to dealing high amounts of damage to nearby personnel."
+ item = /obj/item/grenade/syndieminibomb
+ cost = 6
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/tearstache
+ name = "Teachstache Grenade"
+ desc = "A teargas grenade that launches sticky moustaches onto the face of anyone not wearing a clown or mime mask. The moustaches will \
+ remain attached to the face of all targets for one minute, preventing the use of breath masks and other such devices."
+ item = /obj/item/grenade/chem_grenade/teargas/moustache
+ cost = 3
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/viscerators
+ name = "Viscerator Delivery Grenade"
+ desc = "A unique grenade that deploys a swarm of viscerators upon activation, which will chase down and shred \
+ any non-operatives in the area."
+ item = /obj/item/grenade/spawnergrenade/manhacks
+ cost = 5
+ surplus = 35
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+
//Support and Mechs
/datum/uplink_item/support
category = "Support and Mechanized Exosuits"
surplus = 0
include_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/support/clown_reinforcement
+ name = "Clown Reinforcements"
+ desc = "Call in an additional clown to share the fun, equipped with full starting gear, but no telecrystals."
+ item = /obj/item/antag_spawner/nuke_ops/clown
+ cost = 20
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+ restricted = TRUE
+
/datum/uplink_item/support/reinforcement
name = "Reinforcements"
desc = "Call in an additional team member. They won't come with any gear, so you'll have to save some telecrystals \
@@ -664,13 +1072,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/mecha/combat/gygax/dark/loaded
cost = 80
-/datum/uplink_item/support/mauler
- name = "Mauler Exosuit"
- desc = "A massive and incredibly deadly military-grade exosuit. Features long-range targeting, thrust vectoring, \
- and deployable smoke."
- item = /obj/mecha/combat/marauder/mauler/loaded
- cost = 140
-
/datum/uplink_item/support/honker
name = "Dark H.O.N.K."
desc = "A clown combat mech equipped with bombanana peel and tearstache grenade launchers, as well as the ubiquitous HoNkER BlAsT 5000."
@@ -678,141 +1079,36 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 80
include_modes = list(/datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/support/clown_reinforcement
- name = "Clown Reinforcements"
- desc = "Call in an additional clown to share the fun, equipped with full starting gear, but no telecrystals."
- item = /obj/item/antag_spawner/nuke_ops/clown
- cost = 20
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
- restricted = TRUE
-
-// Stealthy Weapons
-/datum/uplink_item/stealthy_weapons
- category = "Stealthy and Inconspicuous Weapons"
-
-/datum/uplink_item/stealthy_weapons/martialarts
- name = "Martial Arts Scroll"
- desc = "This scroll contains the secrets of an ancient martial arts technique. You will master unarmed combat, \
- deflecting all ranged weapon fire, but you also refuse to use dishonorable ranged weaponry."
- item = /obj/item/book/granter/martial/carp
- cost = 17
- surplus = 0
- exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/stealthy_weapons/cqc
- name = "CQC Manual"
- desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing."
- item = /obj/item/book/granter/martial/cqc
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
- cost = 13
- surplus = 0
-
-/datum/uplink_item/stealthy_weapons/throwingweapons
- name = "Box of Throwing Weapons"
- desc = "A box of shurikens and reinforced bolas from ancient Earth martial arts. They are highly effective \
- throwing weapons. The bolas can knock a target down and the shurikens will embed into limbs."
- item = /obj/item/storage/box/syndie_kit/throwing_weapons
- cost = 3
-
-/datum/uplink_item/stealthy_weapons/edagger
- name = "Energy Dagger"
- desc = "A dagger made of energy that looks and functions as a pen when off."
- item = /obj/item/pen/edagger
- cost = 2
-
-/datum/uplink_item/stealthy_weapons/foampistol
- name = "Toy Gun with Riot Darts"
- desc = "An innocent-looking toy pistol designed to fire foam darts. Comes loaded with riot-grade \
- darts effective at incapacitating a target."
- item = /obj/item/gun/ballistic/automatic/toy/pistol/riot
- cost = 3
- surplus = 10
-
-/datum/uplink_item/stealthy_weapons/sleepy_pen
- name = "Sleepy Pen"
- desc = "A syringe disguised as a functional pen, filled with a potent mix of drugs, including a \
- strong anesthetic and a chemical that prevents the target from speaking. \
- The pen holds one dose of the mixture, and can be refilled. Note that before the target \
- falls asleep, they will be able to move and act."
- item = /obj/item/pen/sleepy
- cost = 4
- exclude_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/stealthy_weapons/soap
- name = "Syndicate Soap"
- desc = "A sinister-looking surfactant used to clean blood stains to hide murders and prevent DNA analysis. \
- You can also drop it underfoot to slip people."
- item = /obj/item/soap/syndie
- cost = 1
- surplus = 50
-
-/datum/uplink_item/stealthy_weapons/traitor_chem_bottle
- name = "Poison Kit"
- desc = "An assortment of deadly chemicals packed into a compact box. Comes with a syringe for more precise application."
- item = /obj/item/storage/box/syndie_kit/chemical
- cost = 6
- surplus = 50
-
-/datum/uplink_item/stealthy_weapons/romerol_kit
- name = "Romerol"
- desc = "A highly experimental bioterror agent which creates dormant nodules to be etched into the grey matter of the brain. On death, these nodules take control of the dead body, causing limited revivification, along with slurred speech, aggression, and the ability to infect others with this agent."
- item = /obj/item/storage/box/syndie_kit/romerol
- cost = 25
- cant_discount = TRUE
- exclude_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/stealthy_weapons/dart_pistol
- name = "Dart Pistol"
- desc = "A miniaturized version of a normal syringe gun. It is very quiet when fired and can fit into any \
- space a small item can."
- item = /obj/item/gun/syringe/syndicate
- cost = 4
- surplus = 50
-
-/datum/uplink_item/stealthy_weapons/detomatix
- name = "Detomatix PDA Cartridge"
- desc = "When inserted into a personal digital assistant, this cartridge gives you four opportunities to \
- detonate PDAs of crewmembers who have their message feature enabled. \
- The concussive effect from the explosion will knock the recipient out for a short period, and deafen \
- them for longer. Beware, it has a chance to detonate your PDA."
- item = /obj/item/cartridge/virus/syndicate
- cost = 5
- restricted = TRUE
-
-/datum/uplink_item/stealthy_weapons/suppressor
- name = "Universal Suppressor"
- desc = "Fitted for use on any small caliber weapon with a threaded barrel, this suppressor will silence the \
- shots of the weapon for increased stealth and superior ambushing capability."
- item = /obj/item/suppressor
- cost = 1
- surplus = 10
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/stealthy_weapons/pizza_bomb
- name = "Pizza Bomb"
- desc = "A pizza box with a bomb cunningly attached to the lid. The timer needs to be set by opening the box; afterwards, \
- opening the box again will trigger the detonation after the timer has elapsed. Comes with free pizza, for you or your target!"
- item = /obj/item/pizzabox/bomb
- cost = 6
- surplus = 8
-
-/datum/uplink_item/stealthy_weapons/dehy_carp
- name = "Dehydrated Space Carp"
- desc = "Looks like a plush toy carp, but just add water and it becomes a real-life space carp! Activate in \
- your hand before use so it knows not to kill you."
- item = /obj/item/toy/plush/carpplushie/dehy_carp
- cost = 1
-
-/datum/uplink_item/stealthy_weapons/soap_clusterbang
- name = "Slipocalypse Clusterbang"
- desc = "A traditional clusterbang grenade with a payload consisting entirely of Syndicate soap. Useful in any scenario!"
- item = /obj/item/grenade/clusterbuster/soap
- cost = 6
+/datum/uplink_item/support/mauler
+ name = "Mauler Exosuit"
+ desc = "A massive and incredibly deadly military-grade exosuit. Features long-range targeting, thrust vectoring, \
+ and deployable smoke."
+ item = /obj/mecha/combat/marauder/mauler/loaded
+ cost = 140
// Stealth Items
/datum/uplink_item/stealthy_tools
category = "Stealth and Camouflage Items"
+/datum/uplink_item/stealthy_tools/agent_card
+ name = "Agent Identification Card"
+ desc = "Agent cards prevent artificial intelligences from tracking the wearer, and can copy access \
+ from other identification cards. The access is cumulative, so scanning one card does not erase the \
+ access gained from another. In addition, they can be forged to display a new assignment and name. \
+ This can be done an unlimited amount of times. Some Syndicate areas and devices can only be accessed \
+ with these cards."
+ item = /obj/item/card/id/syndicate
+ cost = 2
+
+/datum/uplink_item/stealthy_tools/ai_detector
+ name = "Artificial Intelligence Detector"
+ desc = "A functional multitool that turns red when it detects an artificial intelligence watching it, and can be \
+ activated to display their exact viewing location and nearby security camera blind spots. Knowing when \
+ an artificial intelligence is watching you is useful for knowing when to maintain cover, and finding nearby \
+ blind spots can help you identify escape routes."
+ item = /obj/item/multitool/ai_detect
+ cost = 1
+
/datum/uplink_item/stealthy_tools/chameleon
name = "Chameleon Kit"
desc = "A set of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more!"
@@ -820,6 +1116,46 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 2
exclude_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/stealthy_tools/chameleon_proj
+ name = "Chameleon Projector"
+ desc = "Projects an image across a user, disguising them as an object scanned with it, as long as they don't \
+ move the projector from their hand. Disguised users move slowly, and projectiles pass over them."
+ item = /obj/item/chameleon
+ cost = 7
+
+/datum/uplink_item/stealthy_tools/codespeak_manual
+ name = "Codespeak Manual"
+ desc = "Syndicate agents can be trained to use a series of codewords to convey complex information, which sounds like random concepts and drinks to anyone listening. This manual teaches you this Codespeak. You can also hit someone else with the manual in order to teach them. This is the deluxe edition, which has unlimited used."
+ item = /obj/item/codespeak_manual/unlimited
+ cost = 3
+
+/datum/uplink_item/stealthy_tools/combatbananashoes
+ name = "Combat Banana Shoes"
+ desc = "While making the wearer immune to most slipping attacks like regular combat clown shoes, these shoes \
+ can generate a large number of synthetic banana peels as the wearer walks, slipping up would-be pursuers. They also \
+ squeak significantly louder."
+ item = /obj/item/clothing/shoes/clown_shoes/banana_shoes/combat
+ cost = 6
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/stealthy_tools/emplight
+ name = "EMP Flashlight"
+ desc = "A small, self-charging, short-ranged EMP device disguised as a flashlight. \
+ Useful for disrupting headsets, cameras, and borgs during stealth operations."
+ item = /obj/item/flashlight/emp
+ cost = 2
+ surplus = 30
+
+/datum/uplink_item/stealthy_tools/mulligan
+ name = "Mulligan"
+ desc = "Screwed up and have security on your tail? This handy syringe will give you a completely new identity \
+ and appearance."
+ item = /obj/item/reagent_containers/syringe/mulligan
+ cost = 3
+ surplus = 30
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
/datum/uplink_item/stealthy_tools/syndigaloshes
name = "No-Slip Chameleon Shoes"
desc = "These shoes will allow the wearer to run on wet floors and slippery objects without falling down. \
@@ -835,57 +1171,22 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
exclude_modes = list()
include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/stealthy_tools/combatbananashoes
- name = "Combat Banana Shoes"
- desc = "While making the wearer immune to most slipping attacks like regular combat clown shoes, these shoes \
- can generate a large number of synthetic banana peels as the wearer walks, slipping up would-be pursuers. They also \
- squeak significantly louder."
- item = /obj/item/clothing/shoes/clown_shoes/banana_shoes/combat
- cost = 6
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/stealthy_tools/jammer
+ name = "Radio Jammer"
+ desc = "This device will disrupt any nearby outgoing radio communication when activated."
+ item = /obj/item/jammer
+ cost = 5
-datum/uplink_item/stealthy_tools/taeclowndo_shoes
- name = "Tae-clown-do Shoes"
- desc = "A pair of shoes for the most elite agents of the honkmotherland. They grant the mastery of taeclowndo with some honk-fu moves as long as they're worn."
- cost = 12
- item = /obj/item/clothing/shoes/clown_shoes/taeclowndo
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/stealthy_tools/frame
- name = "F.R.A.M.E. PDA Cartridge"
- desc = "When inserted into a personal digital assistant, this cartridge gives you five PDA viruses which \
- when used cause the targeted PDA to become a new uplink with zero TCs, and immediately become unlocked. \
- You will receive the unlock code upon activating the virus, and the new uplink may be charged with \
- telecrystals normally."
- item = /obj/item/cartridge/virus/frame
- cost = 2
- restricted = TRUE
-
-/datum/uplink_item/stealthy_tools/agent_card
- name = "Agent Identification Card"
- desc = "Agent cards prevent artificial intelligences from tracking the wearer, and can copy access \
- from other identification cards. The access is cumulative, so scanning one card does not erase the \
- access gained from another. In addition, they can be forged to display a new assignment and name. \
- This can be done an unlimited amount of times. Some Syndicate areas and devices can only be accessed \
- with these cards."
- item = /obj/item/card/id/syndicate
- cost = 2
-
-/datum/uplink_item/stealthy_tools/chameleon_proj
- name = "Chameleon Projector"
- desc = "Projects an image across a user, disguising them as an object scanned with it, as long as they don't \
- move the projector from their hand. Disguised users move slowly, and projectiles pass over them."
- item = /obj/item/chameleon
- cost = 7
-
-/datum/uplink_item/stealthy_tools/camera_bug
- name = "Camera Bug"
- desc = "Enables you to view all cameras on the network and track a target. Bugging cameras allows you \
- to disable them remotely."
- item = /obj/item/camera_bug
- cost = 1
- surplus = 90
+/*/datum/uplink_item/stealthy_tools/syndi_borer
+ name = "Syndicate Brain Slug"
+ desc = "A small cortical borer, modified to be completely loyal to the owner. \
+ Genetically infertile, these brain slugs can assist medically in a support role, or take direct action \
+ to assist their host."
+ item = /obj/item/antag_spawner/syndi_borer
+ refundable = TRUE
+ cost = 10
+ surplus = 20 //Let's not have this be too common
+ exclude_modes = list(/datum/game_mode/nuclear) */
/datum/uplink_item/stealthy_tools/smugglersatchel
name = "Smuggler's Satchel"
@@ -896,46 +1197,6 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
cost = 2
surplus = 30
-/datum/uplink_item/stealthy_tools/stimpack
- name = "Stimpack"
- desc = "Stimpacks, the tool of many great heroes, make you nearly immune to stuns and knockdowns for about \
- 5 minutes after injection."
- item = /obj/item/reagent_containers/syringe/stimulants
- cost = 5
- surplus = 90
-
-/datum/uplink_item/stealthy_tools/mulligan
- name = "Mulligan"
- desc = "Screwed up and have security on your tail? This handy syringe will give you a completely new identity \
- and appearance."
- item = /obj/item/reagent_containers/syringe/mulligan
- cost = 3
- surplus = 30
- exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/stealthy_tools/emplight
- name = "EMP Flashlight"
- desc = "A small, self-charging, short-ranged EMP device disguised as a flashlight. \
- Useful for disrupting headsets, cameras, and borgs during stealth operations."
- item = /obj/item/flashlight/emp
- cost = 2
- surplus = 30
-
-/datum/uplink_item/stealthy_tools/cutouts
- name = "Adaptive Cardboard Cutouts"
- desc = "These cardboard cutouts are coated with a thin material that prevents discoloration and makes the images on them appear more lifelike. This pack contains three as well as a \
- crayon for changing their appearances."
- item = /obj/item/storage/box/syndie_kit/cutouts
- cost = 1
- surplus = 20
-
-/datum/uplink_item/stealthy_tools/fakenucleardisk
- name = "Decoy Nuclear Authentication Disk"
- desc = "It's just a normal disk. Visually it's identical to the real deal, but it won't hold up under closer scrutiny by the Captain. Don't try to give this to us to complete your objective, we know better!"
- item = /obj/item/disk/nuclear/fake
- cost = 1
- surplus = 1
-
//Space Suits and Hardsuits
/datum/uplink_item/suits
category = "Space Suits and Hardsuits"
@@ -982,6 +1243,74 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
/datum/uplink_item/device_tools
category = "Devices and Tools"
+/datum/uplink_item/device_tools/cutouts
+ name = "Adaptive Cardboard Cutouts"
+ desc = "These cardboard cutouts are coated with a thin material that prevents discoloration and makes the images on them appear more lifelike. This pack contains three as well as a \
+ crayon for changing their appearances."
+ item = /obj/item/storage/box/syndie_kit/cutouts
+ cost = 1
+ surplus = 20
+
+/datum/uplink_item/device_tools/assault_pod
+ name = "Assault Pod Targeting Device"
+ desc = "Use to select the landing zone of your assault pod."
+ item = /obj/item/assault_pod
+ cost = 30
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+ restricted = TRUE
+
+/datum/uplink_item/device_tools/binary
+ name = "Binary Translator Key"
+ desc = "A key that, when inserted into a radio headset, allows you to listen to and talk with silicon-based lifeforms, \
+ such as AI units and cyborgs, over their private binary channel. Caution should \
+ be taken while doing this, as unless they are allied with you, they are programmed to report such intrusions."
+ item = /obj/item/encryptionkey/binary
+ cost = 2
+ surplus = 75
+ restricted = TRUE
+
+/datum/uplink_item/device_tools/magboots
+ name = "Blood-Red Magboots"
+ desc = "A pair of magnetic boots with a Syndicate paintjob that assist with freer movement in space or on-station \
+ during gravitational generator failures. These reverse-engineered knockoffs of Nanotrasen's \
+ 'Advanced Magboots' slow you down in simulated-gravity environments much like the standard issue variety."
+ item = /obj/item/clothing/shoes/magboots/syndie
+ cost = 2
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/device_tools/compressionkit
+ name = "Bluespace Compression Kit"
+ desc = "A modified version of a BSRPED that can be used to reduce the size of most items while retaining their original functions! \
+ Does not work on storage items. \
+ Recharge using bluespace crystals. \
+ Comes with 5 charges."
+ item = /obj/item/compressionkit
+ cost = 5
+
+/datum/uplink_item/device_tools/briefcase_launchpad
+ name = "Briefcase Launchpad"
+ desc = "A briefcase containing a launchpad, a device able to teleport items and people to and from targets up to twenty tiles away from the briefcase. \
+ Also includes a remote control, disguised as an ordinary folder. Touch the briefcase with the remote to link it."
+ surplus = 0
+ item = /obj/item/storage/briefcase/launchpad
+ cost = 6
+
+/datum/uplink_item/device_tools/camera_bug
+ name = "Camera Bug"
+ desc = "Enables you to view all cameras on the network and track a target. Bugging cameras allows you \
+ to disable them remotely."
+ item = /obj/item/camera_bug
+ cost = 1
+ surplus = 90
+
+/datum/uplink_item/device_tools/military_belt
+ name = "Chest Rig"
+ desc = "A robust seven-slot set of webbing that is capable of holding all manner of tactical equipment."
+ item = /obj/item/storage/belt/military
+ cost = 1
+ exclude_modes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/device_tools/emag
name = "Cryptographic Sequencer"
desc = "The cryptographic sequencer, electromagnetic card, or emag, is a small card that unlocks hidden functions \
@@ -989,6 +1318,29 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
item = /obj/item/card/emag
cost = 6
+/datum/uplink_item/device_tools/emagrecharge
+ name = "Electromagnet Charging Device"
+ desc = "A small device intended for recharging Cryptographic Sequencers. Using it will add five extra charges to the Cryptographic Sequencer."
+ item = /obj/item/emagrecharge
+ cost = 2
+
+/datum/uplink_item/device_tools/fakenucleardisk
+ name = "Decoy Nuclear Authentication Disk"
+ desc = "It's just a normal disk. Visually it's identical to the real deal, but it won't hold up under closer scrutiny by the Captain. Don't try to give this to us to complete your objective, we know better!"
+ item = /obj/item/disk/nuclear/fake
+ cost = 1
+ surplus = 1
+
+/datum/uplink_item/device_tools/frame
+ name = "F.R.A.M.E. PDA Cartridge"
+ desc = "When inserted into a personal digital assistant, this cartridge gives you five PDA viruses which \
+ when used cause the targeted PDA to become a new uplink with zero TCs, and immediately become unlocked. \
+ You will receive the unlock code upon activating the virus, and the new uplink may be charged with \
+ telecrystals normally."
+ item = /obj/item/cartridge/virus/frame
+ cost = 2
+ restricted = TRUE
+
/datum/uplink_item/device_tools/toolbox
name = "Full Syndicate Toolbox"
desc = "The syndicate toolbox is a suspicious black and red. It comes loaded with a full tool set including a \
@@ -996,12 +1348,28 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
item = /obj/item/storage/toolbox/syndicate
cost = 1
-/datum/uplink_item/device_tools/surgerybag
- name = "Syndicate Surgery Duffel Bag"
- desc = "The Syndicate surgery duffel bag is a toolkit containing all surgery tools, surgical drapes, \
- a Syndicate brand MMI, a straitjacket, and a muzzle."
- item = /obj/item/storage/backpack/duffelbag/syndie/surgery
- cost = 3
+/datum/uplink_item/device_tools/syndie_glue
+ name = "Glue"
+ desc = "A cheap bottle of one use syndicate brand super glue. \
+ Use on any item to make it undroppable. \
+ Be careful not to glue an item you're already holding!"
+ item = /obj/item/syndie_glue
+ cost = 2
+
+/datum/uplink_item/device_tools/hacked_module
+ name = "Hacked AI Law Upload Module"
+ desc = "When used with an upload console, this module allows you to upload priority laws to an artificial intelligence. \
+ Be careful with wording, as artificial intelligences may look for loopholes to exploit."
+ item = /obj/item/aiModule/syndicate
+ cost = 9
+
+/datum/uplink_item/device_tools/medgun
+ name = "Medbeam Gun"
+ desc = "A wonder of Syndicate engineering, the Medbeam gun, or Medi-Gun enables a medic to keep his fellow \
+ operatives in the fight, even while under fire."
+ item = /obj/item/gun/medbeam
+ cost = 15
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
/datum/uplink_item/device_tools/nutcracker
name = "Nutcracker"
@@ -1009,19 +1377,39 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
item = /obj/item/nutcracker
cost = 1
-/datum/uplink_item/device_tools/surgerybag_adv
- name = "Advanced Syndicate Surgery Duffel Bag"
- desc = "The Syndicate surgery duffel bag is a toolkit containing all newest surgery tools, surgical drapes, \
- a Syndicate brand MMI, a straitjacket, a muzzle, and a full Syndicate Combat Medic Kit."
- item = /obj/item/storage/backpack/duffelbag/syndie/surgery_adv
- cost = 10
+/datum/uplink_item/device_tools/singularity_beacon
+ name = "Power Beacon"
+ desc = "When screwed to wiring attached to an electric grid and activated, this large device pulls any \
+ active gravitational singularities or tesla balls towards it. This will not work when the engine is still \
+ in containment. Because of its size, it cannot be carried. Ordering this \
+ sends you a small beacon that will teleport the larger beacon to your location upon activation."
+ item = /obj/item/sbeacondrop
+ cost = 14
-/datum/uplink_item/device_tools/military_belt
- name = "Chest Rig"
- desc = "A robust seven-slot set of webbing that is capable of holding all manner of tactical equipment."
- item = /obj/item/storage/belt/military
- cost = 1
- exclude_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/device_tools/powersink
+ name = "Power Sink"
+ desc = "When screwed to wiring attached to a power grid and activated, this large device places excessive \
+ load on the grid, causing a station-wide blackout. The sink is large and cannot be stored in most \
+ traditional bags and boxes."
+ item = /obj/item/powersink
+ cost = 6
+
+/datum/uplink_item/device_tools/rad_laser
+ name = "Radioactive Microlaser"
+ desc = "A radioactive microlaser disguised as a standard Nanotrasen health analyzer. When used, it emits a \
+ powerful burst of radiation, which, after a short delay, can incapacitate all but the most protected \
+ of humanoids. It has two settings: intensity, which controls the power of the radiation, \
+ and wavelength, which controls how long the radiation delay is."
+ item = /obj/item/healthanalyzer/rad_laser
+ cost = 3
+
+/datum/uplink_item/device_tools/stimpack
+ name = "Stimpack"
+ desc = "Stimpacks, the tool of many great heroes, make you nearly immune to stuns and knockdowns for about \
+ 5 minutes after injection."
+ item = /obj/item/reagent_containers/syringe/stimulants
+ cost = 5
+ surplus = 90
/datum/uplink_item/device_tools/medkit
name = "Syndicate Combat Medic Kit"
@@ -1032,6 +1420,29 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
cost = 4
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/device_tools/surgerybag
+ name = "Syndicate Surgery Duffel Bag"
+ desc = "The Syndicate surgery duffel bag is a toolkit containing all surgery tools, surgical drapes, \
+ a Syndicate brand MMI, a straitjacket, and a muzzle."
+ item = /obj/item/storage/backpack/duffelbag/syndie/surgery
+ cost = 3
+
+/datum/uplink_item/device_tools/surgerybag_adv
+ name = "Advanced Syndicate Surgery Duffel Bag"
+ desc = "The Syndicate surgery duffel bag is a toolkit containing all newest surgery tools, surgical drapes, \
+ a Syndicate brand MMI, a straitjacket, a muzzle, and a full Syndicate Combat Medic Kit."
+ item = /obj/item/storage/backpack/duffelbag/syndie/surgery_adv
+ cost = 10
+
+/datum/uplink_item/device_tools/encryptionkey
+ name = "Syndicate Encryption Key"
+ desc = "A key that, when inserted into a radio headset, allows you to listen to all station department channels \
+ as well as talk on an encrypted Syndicate channel with other agents that have the same key."
+ item = /obj/item/encryptionkey/syndicate
+ cost = 2
+ surplus = 75
+ restricted = TRUE
+
/datum/uplink_item/device_tools/syndietome
name = "Syndicate Tome"
desc = "Using rare artifacts acquired at great cost, the syndicate has reverse engineered \
@@ -1050,175 +1461,6 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
item = /obj/item/clothing/glasses/thermal/syndi
cost = 4
-/datum/uplink_item/device_tools/binary
- name = "Binary Translator Key"
- desc = "A key that, when inserted into a radio headset, allows you to listen to and talk with silicon-based lifeforms, \
- such as AI units and cyborgs, over their private binary channel. Caution should \
- be taken while doing this, as unless they are allied with you, they are programmed to report such intrusions."
- item = /obj/item/encryptionkey/binary
- cost = 2
- surplus = 75
- restricted = TRUE
-
-/datum/uplink_item/device_tools/encryptionkey
- name = "Syndicate Encryption Key"
- desc = "A key that, when inserted into a radio headset, allows you to listen to all station department channels \
- as well as talk on an encrypted Syndicate channel with other agents that have the same key."
- item = /obj/item/encryptionkey/syndicate
- cost = 2
- surplus = 75
- restricted = TRUE
-
-/datum/uplink_item/device_tools/ai_detector
- name = "Artificial Intelligence Detector"
- desc = "A functional multitool that turns red when it detects an artificial intelligence watching it, and can be \
- activated to display their exact viewing location and nearby security camera blind spots. Knowing when \
- an artificial intelligence is watching you is useful for knowing when to maintain cover, and finding nearby \
- blind spots can help you identify escape routes."
- item = /obj/item/multitool/ai_detect
- cost = 1
-
-/datum/uplink_item/device_tools/hacked_module
- name = "Hacked AI Law Upload Module"
- desc = "When used with an upload console, this module allows you to upload priority laws to an artificial intelligence. \
- Be careful with wording, as artificial intelligences may look for loopholes to exploit."
- item = /obj/item/aiModule/syndicate
- cost = 9
-
-/datum/uplink_item/device_tools/briefcase_launchpad
- name = "Briefcase Launchpad"
- desc = "A briefcase containing a launchpad, a device able to teleport items and people to and from targets up to twenty tiles away from the briefcase. \
- Also includes a remote control, disguised as an ordinary folder. Touch the briefcase with the remote to link it."
- surplus = 0
- item = /obj/item/storage/briefcase/launchpad
- cost = 6
-
-/datum/uplink_item/device_tools/magboots
- name = "Blood-Red Magboots"
- desc = "A pair of magnetic boots with a Syndicate paintjob that assist with freer movement in space or on-station \
- during gravitational generator failures. These reverse-engineered knockoffs of Nanotrasen's \
- 'Advanced Magboots' slow you down in simulated-gravity environments much like the standard issue variety."
- item = /obj/item/clothing/shoes/magboots/syndie
- cost = 2
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/device_tools/c4
- name = "Composition C-4"
- desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls, sabotage equipment, or connect \
- an assembly to it in order to alter the way it detonates. It has a modifiable timer with a \
- minimum setting of 10 seconds."
- item = /obj/item/grenade/plastic/c4
- cost = 1
-
-/datum/uplink_item/device_tools/c4bag
- name = "Bag of C-4 explosives"
- desc = "Because sometimes quantity is quality. Contains 10 C-4 plastic explosives."
- item = /obj/item/storage/backpack/duffelbag/syndie/c4
- cost = 9 //10% discount!
- cant_discount = TRUE
-
-/datum/uplink_item/device_tools/x4bag
- name = "Bag of X-4 explosives"
- desc = "Contains 3 X-4 plastic explosives. Similar, but more powerful than C-4. X-4 can be placed on a solid surface, such as a wall or window, and it will \
- blast through the wall, injuring anything on the opposite side, while being safer to the user. For when you want a wider, deeper, hole."
- item = /obj/item/storage/backpack/duffelbag/syndie/x4
- cost = 4 //
- cant_discount = TRUE
-
-/datum/uplink_item/device_tools/powersink
- name = "Power Sink"
- desc = "When screwed to wiring attached to a power grid and activated, this large device places excessive \
- load on the grid, causing a station-wide blackout. The sink is large and cannot be stored in most \
- traditional bags and boxes."
- item = /obj/item/powersink
- cost = 6
-
-/datum/uplink_item/device_tools/singularity_beacon
- name = "Power Beacon"
- desc = "When screwed to wiring attached to an electric grid and activated, this large device pulls any \
- active gravitational singularities or tesla balls towards it. This will not work when the engine is still \
- in containment. Because of its size, it cannot be carried. Ordering this \
- sends you a small beacon that will teleport the larger beacon to your location upon activation."
- item = /obj/item/sbeacondrop
- cost = 14
-
-/datum/uplink_item/device_tools/syndicate_bomb
- name = "Syndicate Bomb"
- desc = "The Syndicate bomb is a fearsome device capable of massive destruction. It has an adjustable timer, \
- with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \
- movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \
- transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \
- be defused, and some crew may attempt to do so."
- item = /obj/item/sbeacondrop/bomb
- cost = 11
-
-/datum/uplink_item/device_tools/clown_bomb_clownops
- name = "Clown Bomb"
- desc = "The Clown bomb is a hilarious device capable of massive pranks. It has an adjustable timer, \
- with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \
- movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \
- transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \
- be defused, and some crew may attempt to do so."
- item = /obj/item/sbeacondrop/clownbomb
- cost = 15
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/device_tools/syndicate_detonator
- name = "Syndicate Detonator"
- desc = "The Syndicate detonator is a companion device to the Syndicate bomb. Simply press the included button \
- and an encrypted radio frequency will instruct all live Syndicate bombs to detonate. \
- Useful for when speed matters or you wish to synchronize multiple bomb blasts. Be sure to stand clear of \
- the blast radius before using the detonator."
- item = /obj/item/syndicatedetonator
- cost = 3
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/device_tools/rad_laser
- name = "Radioactive Microlaser"
- desc = "A radioactive microlaser disguised as a standard Nanotrasen health analyzer. When used, it emits a \
- powerful burst of radiation, which, after a short delay, can incapacitate all but the most protected \
- of humanoids. It has two settings: intensity, which controls the power of the radiation, \
- and wavelength, which controls how long the radiation delay is."
- item = /obj/item/healthanalyzer/rad_laser
- cost = 3
-
-/datum/uplink_item/device_tools/assault_pod
- name = "Assault Pod Targeting Device"
- desc = "Use to select the landing zone of your assault pod."
- item = /obj/item/assault_pod
- cost = 30
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
- restricted = TRUE
-
-/datum/uplink_item/device_tools/shield
- name = "Energy Shield"
- desc = "An incredibly useful personal shield projector, capable of reflecting energy projectiles and defending \
- against other attacks. Pair with an Energy Sword for a killer combination."
- item = /obj/item/shield/energy
- cost = 16
- surplus = 20
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/device_tools/bananashield
- name = "Bananium Energy Shield"
- desc = "A clown's most powerful defensive weapon, this personal shield provides near immunity to ranged energy attacks \
- by bouncing them back at the ones who fired them. It can also be thrown to bounce off of people, slipping them, \
- and returning to you even if you miss. WARNING: DO NOT ATTEMPT TO STAND ON SHIELD WHILE DEPLOYED, EVEN IF WEARING ANTI-SLIP SHOES."
- item = /obj/item/shield/energy/bananium
- cost = 16
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/device_tools/medgun
- name = "Medbeam Gun"
- desc = "A wonder of Syndicate engineering, the Medbeam gun, or Medi-Gun enables a medic to keep his fellow \
- operatives in the fight, even while under fire."
- item = /obj/item/gun/medbeam
- cost = 15
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-
/datum/uplink_item/device_tools/potion
name = "Syndicate Sentience Potion"
item = /obj/item/slimepotion/slime/sentience/nuclear
@@ -1227,79 +1469,12 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
restricted = TRUE
-/datum/uplink_item/device_tools/telecrystal
- name = "Raw Telecrystal"
- desc = "A telecrystal in its rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
- item = /obj/item/stack/telecrystal
- cost = 1
- surplus = 0
- cant_discount = TRUE
- // Don't add telecrystals to the purchase_log since
- // it's just used to buy more items (including itself!)
- purchase_log_vis = FALSE
-
-/datum/uplink_item/device_tools/telecrystal/five
- name = "5 Raw Telecrystals"
- desc = "Five telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
- item = /obj/item/stack/telecrystal/five
- cost = 5
-
-/datum/uplink_item/device_tools/telecrystal/twenty
- name = "20 Raw Telecrystals"
- desc = "Twenty telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
- item = /obj/item/stack/telecrystal/twenty
- cost = 20
-
-/datum/uplink_item/device_tools/jammer
- name = "Radio Jammer"
- desc = "This device will disrupt any nearby outgoing radio communication when activated."
- item = /obj/item/jammer
- cost = 5
-
-/datum/uplink_item/device_tools/codespeak_manual
- name = "Codespeak Manual"
- desc = "Syndicate agents can be trained to use a series of codewords to convey complex information, which sounds like random concepts and drinks to anyone listening. This manual teaches you this Codespeak. You can also hit someone else with the manual in order to teach them. This is the deluxe edition, which has unlimited used."
- item = /obj/item/codespeak_manual/unlimited
- cost = 3
-
-/datum/uplink_item/device_tools/compressionkit
- name = "Bluespace Compression Kit"
- desc = "A modified version of a BSRPED that can be used to reduce the size of most items while retaining their original functions! \
- Does not work on storage items. \
- Recharge using bluespace crystals. \
- Comes with 5 charges."
- item = /obj/item/compressionkit
- cost = 5
-
-/datum/uplink_item/device_tools/syndie_glue
- name = "Glue"
- desc = "A cheap bottle of one use syndicate brand super glue. \
- Use on any item to make it undroppable. \
- Be careful not to glue an item you're already holding!"
- item = /obj/item/syndie_glue
- cost = 2
// Implants
/datum/uplink_item/implants
category = "Implants"
surplus = 50
-/datum/uplink_item/implants/freedom
- name = "Freedom Implant"
- desc = "An implant injected into the body and later activated at the user's will. It will attempt to free the \
- user from common restraints such as handcuffs."
- item = /obj/item/storage/box/syndie_kit/imp_freedom
- cost = 5
-
-/datum/uplink_item/implants/uplink
- name = "Uplink Implant"
- desc = "An implant injected into the body, and later activated at the user's will. Has no telecrystals, must be charged by the use of physical telecrystals. Undetectable (except via surgery), and excellent for escaping confinement."
- item = /obj/item/storage/box/syndie_kit/imp_uplink
- cost = 4
- // An empty uplink is kinda useless.
- surplus = 0
- restricted = TRUE
-
/datum/uplink_item/implants/adrenal
name = "Adrenal Implant"
desc = "An implant injected into the body, and later activated at the user's will. It will inject a chemical \
@@ -1308,12 +1483,19 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
cost = 8
player_minimum = 25
-/datum/uplink_item/implants/storage
- name = "Storage Implant"
- desc = "An implant injected into the body, and later activated at the user's will. It will open a small bluespace \
- pocket capable of storing two items."
- item = /obj/item/storage/box/syndie_kit/imp_storage
- cost = 8
+/datum/uplink_item/implants/antistun
+ name = "CNS Rebooter Implant"
+ desc = "This implant will help you get back up on your feet faster after being stunned. Comes with an autosurgeon."
+ item = /obj/item/autosurgeon/anti_stun
+ cost = 12
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/implants/freedom
+ name = "Freedom Implant"
+ desc = "An implant injected into the body and later activated at the user's will. It will attempt to free the \
+ user from common restraints such as handcuffs."
+ item = /obj/item/storage/box/syndie_kit/imp_freedom
+ cost = 5
/datum/uplink_item/implants/microbomb
name = "Microbomb Implant"
@@ -1340,48 +1522,49 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
cost = 4
restricted = TRUE
+/datum/uplink_item/implants/reviver
+ name = "Reviver Implant"
+ desc = "This implant will attempt to revive you if you lose consciousness. Comes with an autosurgeon."
+ item = /obj/item/autosurgeon/reviver
+ cost = 8
+ include_modes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/implants/stealthimplant
name = "Stealth Implant"
desc = "This one-of-a-kind implant will make you almost invisible if you play your cards right."
item = /obj/item/implanter/stealth
cost = 8
-// Cybernetics
-/datum/uplink_item/cyber_implants
- category = "Cybernetic Implants"
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/implants/storage
+ name = "Storage Implant"
+ desc = "An implant injected into the body, and later activated at the user's will. It will open a small bluespace \
+ pocket capable of storing two items."
+ item = /obj/item/storage/box/syndie_kit/imp_storage
+ cost = 8
-/datum/uplink_item/cyber_implants/thermals
+/datum/uplink_item/implants/thermals
name = "Thermal Eyes"
desc = "These cybernetic eyes will give you thermal vision. Comes with a free autosurgeon."
item = /obj/item/autosurgeon/thermal_eyes
cost = 8
+ include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/cyber_implants/xray
+/datum/uplink_item/implants/uplink
+ name = "Uplink Implant"
+ desc = "An implant injected into the body, and later activated at the user's will. Has no telecrystals, must be charged by the use of physical telecrystals. Undetectable (except via surgery), and excellent for escaping confinement."
+ item = /obj/item/storage/box/syndie_kit/imp_uplink
+ cost = 4
+ // An empty uplink is kinda useless.
+ surplus = 0
+ restricted = TRUE
+
+/datum/uplink_item/implants/xray
name = "X-ray Vision Implant"
desc = "These cybernetic eyes will give you X-ray vision. Comes with an autosurgeon."
item = /obj/item/autosurgeon/xray_eyes
cost = 10
-
-/datum/uplink_item/cyber_implants/antistun
- name = "CNS Rebooter Implant"
- desc = "This implant will help you get back up on your feet faster after being stunned. Comes with an autosurgeon."
- item = /obj/item/autosurgeon/anti_stun
- cost = 12
-
-/datum/uplink_item/cyber_implants/reviver
- name = "Reviver Implant"
- desc = "This implant will attempt to revive you if you lose consciousness. Comes with an autosurgeon."
- item = /obj/item/autosurgeon/reviver
- cost = 8
-
-/datum/uplink_item/cyber_implants/bundle
- name = "Cybernetic Implants Bundle"
- desc = "A random selection of cybernetic implants. Guaranteed 5 high quality implants. Comes with an autosurgeon."
- item = /obj/item/storage/box/cyber_implants
- cost = 40
- cant_discount = TRUE
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear)
// Role-specific items
/datum/uplink_item/role_restricted
@@ -1389,23 +1572,62 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
surplus = 0
-/datum/uplink_item/role_restricted/reverse_revolver
- name = "Reverse Revolver"
- desc = "A revolver that always fires at its user. \"Accidentally\" drop your weapon, then watch as the greedy corporate pigs blow their own brains all over the wall. \
- The revolver itself is actually real. Only clumsy people, and clowns, can fire it normally. Comes in a box of hugs. Honk."
- cost = 14
- item = /obj/item/storage/box/hug/reverse_revolver
+/datum/uplink_item/role_restricted/ancient_jumpsuit
+ name = "Ancient Jumpsuit"
+ desc = "A tattered old jumpsuit that will provide absolutely no benefit to you. It fills the wearer with a strange compulsion to blurt out 'glorf'."
+ item = /obj/item/clothing/under/color/grey/glorf
+ cost = 20
+ restricted_roles = list("Assistant")
+
+/datum/uplink_item/role_restricted/pie_cannon
+ name = "Banana Cream Pie Cannon"
+ desc = "A special pie cannon for a special clown, this gadget can hold up to 20 pies and automatically fabricates one every two seconds!"
+ cost = 10
+ item = /obj/item/pneumatic_cannon/pie/selfcharge
restricted_roles = list("Clown")
-/datum/uplink_item/role_restricted/reverse_bear_trap
- name = "Reverse Bear Trap"
- desc = "An ingenious execution device worn on (or forced onto) the head. Arming it starts a 1-minute kitchen timer mounted on the bear trap. When it goes off, the trap's jaws will \
- violently open, instantly killing anyone wearing it by tearing their jaws in half. To arm, attack someone with it while they're not wearing headgear, and you will force it onto their \
- head after three seconds uninterrupted."
- cost = 5
- item = /obj/item/reverse_bear_trap
+/datum/uplink_item/role_restricted/blastcannon
+ name = "Blast Cannon"
+ desc = "A highly specialized weapon, the Blast Cannon is actually relatively simple. It contains an attachment for a tank transfer valve mounted to an angled pipe specially constructed \
+ withstand extreme pressure and temperatures, and has a mechanical trigger for triggering the transfer valve. Essentially, it turns the explosive force of a bomb into a narrow-angle \
+ blast wave \"projectile\". Aspiring scientists may find this highly useful, as forcing the pressure shockwave into a narrow angle seems to be able to bypass whatever quirk of physics \
+ disallows explosive ranges above a certain distance, allowing for the device to use the theoretical yield of a transfer valve bomb, instead of the factual yield."
+ item = /obj/item/gun/blastcannon
+ cost = 14 //High cost because of the potential for extreme damage in the hands of a skilled gas masked scientist.
+ restricted_roles = list("Research Director", "Scientist")
+
+/datum/uplink_item/role_restricted/brainwash_disk
+ name = "Brainwashing Surgery Program"
+ desc = "A disk containing the procedure to perform a brainwashing surgery, allowing you to implant an objective onto a target. \
+ Insert into an Operating Console to enable the procedure."
+ item = /obj/item/disk/surgery/brainwashing
+ restricted_roles = list("Medical Doctor")
+ cost = 3
+
+/datum/uplink_item/role_restricted/clown_bomb
+ name = "Clown Bomb"
+ desc = "The Clown bomb is a hilarious device capable of massive pranks. It has an adjustable timer, \
+ with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \
+ movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \
+ transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \
+ be defused, and some crew may attempt to do so."
+ item = /obj/item/sbeacondrop/clownbomb
+ cost = 15
restricted_roles = list("Clown")
+/*
+/datum/uplink_item/role_restricted/clowncar
+ name = "Clown Car"
+ desc = "The Clown Car is the ultimate transportation method for any worthy clown! \
+ Simply insert your bikehorn and get in, and get ready to have the funniest ride of your life! \
+ You can ram any spacemen you come across and stuff them into your car, kidnapping them and locking them inside until \
+ someone saves them or they manage to crawl out. Be sure not to ram into any walls or vending machines, as the springloaded seats \
+ are very sensetive. Now with our included lube defense mechanism which will protect you against any angry shitcurity!"
+ item = /obj/vehicle/sealed/car/clowncar
+ cost = 15
+ restricted_roles = list("Clown")
+*/
+
/datum/uplink_item/role_restricted/clumsyDNA
name = "Clumsy Clown DNA"
desc = "A DNA injector that has been loaded with the clown gene that makes people clumsy.. \
@@ -1414,19 +1636,31 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
item = /obj/item/dnainjector/clumsymut
restricted_roles = list("Clown")
-/datum/uplink_item/role_restricted/taeclowndo_shoes
- name = "Tae-clown-do Shoes"
- desc = "A pair of shoes for the most elite agents of the honkmotherland. They grant the mastery of taeclowndo with some honk-fu moves as long as they're worn."
- cost = 14
- item = /obj/item/clothing/shoes/clown_shoes/taeclowndo
- restricted_roles = list("Clown")
+/datum/uplink_item/role_restricted/haunted_magic_eightball
+ name = "Haunted Magic Eightball"
+ desc = "Most magic eightballs are toys with dice inside. Although identical in appearance to the harmless toys, this occult device reaches into the spirit world to find its answers. Be warned, that spirits are often capricious or just little assholes. To use, simply speak your question aloud, then begin shaking."
+ item = /obj/item/toy/eightball/haunted
+ cost = 2
+ restricted_roles = list("Curator")
+ limited_stock = 1 //please don't spam deadchat
-/datum/uplink_item/role_restricted/mimery
- name = "Guide to Advanced Mimery Series"
- desc = "The classical two part series on how to further hone your mime skills. Upon studying the series, the user should be able to make 3x1 invisible walls, and shoot bullets out of their fingers. Obviously only works for Mimes."
- cost = 12
- item = /obj/item/storage/box/syndie_kit/mimery
- restricted_roles = list("Mime")
+/datum/uplink_item/role_restricted/his_grace
+ name = "His Grace"
+ desc = "An incredibly dangerous weapon recovered from a station overcome by the grey tide. Once activated, He will thirst for blood and must be used to kill to sate that thirst. \
+ His Grace grants gradual regeneration and complete stun immunity to His wielder, but be wary: if He gets too hungry, He will become impossible to drop and eventually kill you if not fed. \
+ However, if left alone for long enough, He will fall back to slumber. \
+ To activate His Grace, simply unlatch Him."
+ item = /obj/item/his_grace
+ cost = 20
+ restricted_roles = list("Chaplain")
+ surplus = 5 //Very low chance to get it in a surplus crate even without being the chaplain
+
+/datum/uplink_item/role_restricted/explosive_hot_potato
+ name = "Exploding Hot Potato"
+ desc = "A potato rigged with explosives. On activation, a special mechanism is activated that prevents it from being dropped. The only way to get rid of it if you are holding it is to attack someone else with it, causing it to latch to that person instead."
+ item = /obj/item/hot_potato/syndicate
+ cost = 4
+ restricted_roles = list("Cook", "Botanist", "Clown", "Mime")
/datum/uplink_item/role_restricted/ez_clean_bundle
name = "EZ Clean Grenade Bundle"
@@ -1436,6 +1670,36 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
surplus = 20
restricted_roles = list("Janitor")
+/datum/uplink_item/role_restricted/goldenbox
+ name = "Gold Toolbox"
+ desc = "A gold planted plastitanium toolbox loaded with tools. Comes with a set of AI detection multi-tool and a pare of combat gloves."
+ item = /obj/item/storage/toolbox/gold_real
+ cost = 3 // Has syndie tools + gloves + a robust weapon
+ restricted_roles = list("Assistant", "Curator") //Curator due to this being made of gold - It fits the theme
+
+/datum/uplink_item/role_restricted/mimery
+ name = "Guide to Advanced Mimery Series"
+ desc = "The classical two part series on how to further hone your mime skills. Upon studying the series, the user should be able to make 3x1 invisible walls, and shoot bullets out of their fingers. Obviously only works for Mimes."
+ cost = 12
+ item = /obj/item/storage/box/syndie_kit/mimery
+ restricted_roles = list("Mime")
+
+/datum/uplink_item/role_restricted/ultrahonkpins
+ name = "Hilarious firing pin"
+ desc = "A single firing pin made for Clown agents, this firing pin makes any gun honk when fired if not a true clown! \
+ This firing pin also helps you fire the gun correctly. May the HonkMother HONK you agent."
+ item = /obj/item/firing_pin/clown/ultra
+ cost = 2
+ restricted_roles = list("Clown")
+
+/datum/uplink_item/role_restricted/pressure_mod
+ name = "Kinetic Accelerator Pressure Mod"
+ desc = "A modification kit which allows Kinetic Accelerators to do greatly increased damage while indoors. Occupies 35% mod capacity."
+ item = /obj/item/borg/upgrade/modkit/indoors
+ cost = 5 //you need two for full damage, so total of 10 for maximum damage
+ limited_stock = 2 //you can't use more than two!
+ restricted_roles = list("Shaft Miner")
+
/datum/uplink_item/role_restricted/kitchen_gun
name = "Kitchen Gun (TM)"
desc = "A revolutionary .45 caliber cleaning solution! Say goodbye to daily stains and dirty surfaces with Kitchen Gun (TM)! Just five shots from Kitchen Gun (TM), and it'll sparkle like new! Includes two extra ammunition clips!"
@@ -1451,60 +1715,12 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
restricted_roles = list("Cook", "Janitor")
item = /obj/item/ammo_box/magazine/m45/kitchengun
-/datum/uplink_item/role_restricted/explosive_hot_potato
- name = "Exploding Hot Potato"
- desc = "A potato rigged with explosives. On activation, a special mechanism is activated that prevents it from being dropped. The only way to get rid of it if you are holding it is to attack someone else with it, causing it to latch to that person instead."
- item = /obj/item/hot_potato/syndicate
- cost = 4
- restricted_roles = list("Cook", "Botanist", "Clown", "Mime")
-
-/datum/uplink_item/role_restricted/his_grace
- name = "His Grace"
- desc = "An incredibly dangerous weapon recovered from a station overcome by the grey tide. Once activated, He will thirst for blood and must be used to kill to sate that thirst. \
- His Grace grants gradual regeneration and complete stun immunity to His wielder, but be wary: if He gets too hungry, He will become impossible to drop and eventually kill you if not fed. \
- However, if left alone for long enough, He will fall back to slumber. \
- To activate His Grace, simply unlatch Him."
- item = /obj/item/his_grace
- cost = 20
- restricted_roles = list("Chaplain")
- surplus = 5 //Very low chance to get it in a surplus crate even without being the chaplain
-
-/datum/uplink_item/role_restricted/pie_cannon
- name = "Banana Cream Pie Cannon"
- desc = "A special pie cannon for a special clown, this gadget can hold up to 20 pies and automatically fabricates one every two seconds!"
- cost = 10
- item = /obj/item/pneumatic_cannon/pie/selfcharge
- restricted_roles = list("Clown")
-
-/datum/uplink_item/role_restricted/ancient_jumpsuit
- name = "Ancient Jumpsuit"
- desc = "A tattered old jumpsuit that will provide absolutely no benefit to you. It fills the wearer with a strange compulsion to blurt out 'glorf'."
- item = /obj/item/clothing/under/color/grey/glorf
- cost = 20
- restricted_roles = list("Assistant")
-
-/datum/uplink_item/role_restricted/goldenbox
- name = "Gold Toolbox"
- desc = "A gold planted plastitanium toolbox loaded with tools. Comes with a set of AI detection multi-tool and a pare of combat gloves."
- item = /obj/item/storage/toolbox/gold_real
- cost = 3 // Has synda tools + gloves + a robust weapon
- restricted_roles = list("Assistant", "Curator") //Curator do to being made of gold - It fits the theme
-
-/datum/uplink_item/role_restricted/brainwash_disk
- name = "Brainwashing Surgery Program"
- desc = "A disk containing the procedure to perform a brainwashing surgery, allowing you to implant an objective onto a target. \
- Insert into an Operating Console to enable the procedure."
- item = /obj/item/disk/surgery/brainwashing
- restricted_roles = list("Medical Doctor")
- cost = 3
-
-/datum/uplink_item/role_restricted/haunted_magic_eightball
- name = "Haunted Magic Eightball"
- desc = "Most magic eightballs are toys with dice inside. Although identical in appearance to the harmless toys, this occult device reaches into the spirit world to find its answers. Be warned, that spirits are often capricious or just little assholes. To use, simply speak your question aloud, then begin shaking."
- item = /obj/item/toy/eightball/haunted
- cost = 2
- restricted_roles = list("Curator")
- limited_stock = 1 //please don't spam deadchat
+/datum/uplink_item/role_restricted/magillitis_serum
+ name = "Magillitis Serum Autoinjector"
+ desc = "A single-use autoinjector which contains an experimental serum that causes rapid muscular growth in Hominidae. Side-affects may include hypertrichosis, violent outbursts, and an unending affinity for bananas."
+ item = /obj/item/reagent_containers/hypospray/magillitis
+ cost = 15
+ restricted_roles = list("Geneticist", "Chief Medical Officer")
/datum/uplink_item/role_restricted/modified_syringe_gun
name = "Modified Syringe Gun"
@@ -1520,106 +1736,41 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
cost = 12
restricted_roles = list("Chemist", "Chief Medical Officer")
-/datum/uplink_item/role_restricted/magillitis_serum
- name = "Magillitis Serum Autoinjector"
- desc = "A single-use autoinjector which contains an experimental serum that causes rapid muscular growth in Hominidae. Side-affects may include hypertrichosis, violent outbursts, and an unending affinity for bananas."
- item = /obj/item/reagent_containers/hypospray/magillitis
- cost = 15
- restricted_roles = list("Geneticist", "Chief Medical Officer")
-
-/datum/uplink_item/role_restricted/pressure_mod
- name = "Kinetic Accelerator Pressure Mod"
- desc = "A modification kit which allows Kinetic Accelerators to do greatly increased damage while indoors. Occupies 35% mod capacity."
- item = /obj/item/borg/upgrade/modkit/indoors
- cost = 5 //you need two for full damage, so total of 10 for maximum damage
- limited_stock = 2 //you can't use more than two!
- restricted_roles = list("Shaft Miner")
-
-/datum/uplink_item/role_restricted/blastcannon
- name = "Blast Cannon"
- desc = "A highly specialized weapon, the Blast Cannon is actually relatively simple. It contains an attachment for a tank transfer valve mounted to an angled pipe specially constructed \
- withstand extreme pressure and temperatures, and has a mechanical trigger for triggering the transfer valve. Essentially, it turns the explosive force of a bomb into a narrow-angle \
- blast wave \"projectile\". Aspiring scientists may find this highly useful, as forcing the pressure shockwave into a narrow angle seems to be able to bypass whatever quirk of physics \
- disallows explosive ranges above a certain distance, allowing for the device to use the theoretical yield of a transfer valve bomb, instead of the factual yield."
- item = /obj/item/gun/blastcannon
- cost = 14 //High cost because of the potential for extreme damage in the hands of a skilled gas masked scientist.
- restricted_roles = list("Research Director", "Scientist")
-
-/datum/uplink_item/device_tools/clown_bomb
- name = "Clown Bomb"
- desc = "The Clown bomb is a hilarious device capable of massive pranks. It has an adjustable timer, \
- with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \
- movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \
- transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \
- be defused, and some crew may attempt to do so."
- item = /obj/item/sbeacondrop/clownbomb
- cost = 15
+/datum/uplink_item/role_restricted/reverse_bear_trap
+ name = "Reverse Bear Trap"
+ desc = "An ingenious execution device worn on (or forced onto) the head. Arming it starts a 1-minute kitchen timer mounted on the bear trap. When it goes off, the trap's jaws will \
+ violently open, instantly killing anyone wearing it by tearing their jaws in half. To arm, attack someone with it while they're not wearing headgear, and you will force it onto their \
+ head after three seconds uninterrupted."
+ cost = 5
+ item = /obj/item/reverse_bear_trap
restricted_roles = list("Clown")
-/datum/uplink_item/device_tools/ultrahonkpins //Idealy so they can place it into their own guns without needing cargo
- name = "Hilarious firing pin"
- desc = "A single firing pin made for Clown agents, this firing pin makes any gun honk when fired if not a true clown! \
- This firing pin also helps you fire the gun correctly. May the HonkMother HONK you agent."
- item = /obj/item/firing_pin/clown/ultra
- cost = 2
+/datum/uplink_item/role_restricted/reverse_revolver
+ name = "Reverse Revolver"
+ desc = "A revolver that always fires at its user. \"Accidentally\" drop your weapon, then watch as the greedy corporate pigs blow their own brains all over the wall. \
+ The revolver itself is actually real. Only clumsy people, and clowns, can fire it normally. Comes in a box of hugs. Honk."
+ cost = 14
+ item = /obj/item/storage/box/hug/reverse_revolver
restricted_roles = list("Clown")
-/*
-/datum/uplink_item/role_restricted/clowncar
- name = "Clown Car"
- desc = "The Clown Car is the ultimate transportation method for any worthy clown! \
- Simply insert your bikehorn and get in, and get ready to have the funniest ride of your life! \
- You can ram any spacemen you come across and stuff them into your car, kidnapping them and locking them inside until \
- someone saves them or they manage to crawl out. Be sure not to ram into any walls or vending machines, as the springloaded seats \
- are very sensetive. Now with our included lube defense mechanism which will protect you against any angry shitcurity!"
- item = /obj/vehicle/sealed/car/clowncar
- cost = 15
+/datum/uplink_item/role_restricted/taeclowndo_shoes
+ name = "Tae-clown-do Shoes"
+ desc = "A pair of shoes for the most elite agents of the honkmotherland. They grant the mastery of taeclowndo with some honk-fu moves as long as they're worn."
+ cost = 14
+ item = /obj/item/clothing/shoes/clown_shoes/taeclowndo
restricted_roles = list("Clown")
-*/
+
// Pointless
/datum/uplink_item/badass
category = "(Pointless) Badassery"
surplus = 0
-/datum/uplink_item/badass/syndiecards
- name = "Syndicate Playing Cards"
- desc = "A special deck of space-grade playing cards with a mono-molecular edge and metal reinforcement, \
- making them slightly more robust than a normal deck of cards. \
- You can also play card games with them or leave them on your victims."
- item = /obj/item/toy/cards/deck/syndicate
- cost = 1
- surplus = 40
-
-/datum/uplink_item/badass/syndiecash
- name = "Syndicate Briefcase Full of Cash"
- desc = "A secure briefcase containing 5000 space credits. Useful for bribing personnel, or purchasing goods \
- and services at lucrative prices. The briefcase also feels a little heavier to hold; it has been \
- manufactured to pack a little bit more of a punch if your client needs some convincing."
- item = /obj/item/storage/secure/briefcase/syndie
- cost = 1
-
-/datum/uplink_item/badass/syndiecigs
- name = "Syndicate Smokes"
- desc = "Strong flavor, dense smoke, infused with omnizine."
- item = /obj/item/storage/fancy/cigarettes/cigpack_syndicate
- cost = 2
-
-/datum/uplink_item/badass/balloon
- name = "Syndicate Balloon"
- desc = "For showing that you are THE BOSS: A useless red balloon with the Syndicate logo on it. \
- Can blow the deepest of covers."
- item = /obj/item/toy/syndicateballoon
- cost = 20
- cant_discount = TRUE
-
-/datum/uplink_item/badass/durasteel_toolbox
- name = "Durasteel Toolbox"
- desc = "A very high impact toolbox. Excels at destroying stationary structures."
- item = /obj/item/storage/toolbox/durasteel
- cost = 2 //18 damage on mobs, 50 on objects, 4.5 stam/hit
+/datum/uplink_item/badass/costumes/obvious_chameleon
+ name = "Broken Chameleon Kit"
+ desc = "A set of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more! Please note that this kit did NOT pass quality control."
+ item = /obj/item/storage/box/syndie_kit/chameleon/broken
/datum/uplink_item/badass/costumes
- surplus = 0
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
cost = 4
cant_discount = TRUE
@@ -1634,90 +1785,45 @@ datum/uplink_item/stealthy_tools/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/costumes/obvious_chameleon
- name = "Broken Chameleon Kit"
- desc = "A set of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more! Please note that this kit did NOT pass quality control."
- item = /obj/item/storage/box/syndie_kit/chameleon/broken
+/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/plastitanium
+ cost = 2 //18 damage on mobs, 50 on objects, 4.5 stam/hit
-/datum/uplink_item/badass/rapid
- name = "Gloves of the North Star"
- desc = "These gloves let the user punch people very fast. Does not improve weapon attack speed or the meaty fists of a hulk."
- item = /obj/item/clothing/gloves/rapid
- cost = 8
-
-/datum/uplink_item/badass/bundle
- name = "Syndicate Bundle"
- desc = "Syndicate Bundles are specialized groups of items that arrive in a plain box. \
- These items are collectively worth more than 20 telecrystals, but you do not know which specialization \
- you will receive."
- item = /obj/item/storage/box/syndicate
+/datum/uplink_item/badass/balloon
+ name = "Syndicate Balloon"
+ desc = "For showing that you are THE BOSS: A useless red balloon with the Syndicate logo on it. \
+ Can blow the deepest of covers."
+ item = /obj/item/toy/syndicateballoon
cost = 20
- exclude_modes = list(/datum/game_mode/nuclear)
cant_discount = TRUE
-/datum/uplink_item/badass/surplus
- name = "Syndicate Surplus Crate"
- desc = "A dusty crate from the back of the Syndicate warehouse. Rumored to contain a valuable assortment of items, \
- but you never know. Contents are sorted to always be worth 50 TC."
- item = /obj/structure/closet/crate
- cost = 20
- player_minimum = 25
- exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
- cant_discount = TRUE
- var/starting_crate_value = 50
+/datum/uplink_item/badass/syndiecash
+ name = "Syndicate Briefcase Full of Cash"
+ desc = "A secure briefcase containing 5000 space credits. Useful for bribing personnel, or purchasing goods \
+ and services at lucrative prices. The briefcase also feels a little heavier to hold; it has been \
+ manufactured to pack a little bit more of a punch if your client needs some convincing."
+ item = /obj/item/storage/secure/briefcase/syndie
+ cost = 1
-/datum/uplink_item/badass/surplus/super
- name = "Super Surplus Crate"
- desc = "A dusty SUPER-SIZED from the back of the Syndicate warehouse. Rumored to contain a valuable assortment of items, \
- but you never know. Contents are sorted to always be worth 125 TC."
- cost = 40
- player_minimum = 40
- starting_crate_value = 125
+/datum/uplink_item/badass/phantomthief
+ name = "Syndicate Mask"
+ desc = "A cheap plastic mask fitted with an adrenaline autoinjector, which can be used by simply tensing your muscles"
+ item = /obj/item/clothing/glasses/phantomthief/syndicate
+ cost = 2
-/datum/uplink_item/badass/surplus/purchase(mob/user, datum/component/uplink/U)
- var/list/uplink_items = get_uplink_items(SSticker && SSticker.mode? SSticker.mode : null, FALSE)
+/datum/uplink_item/badass/syndiecards
+ name = "Syndicate Playing Cards"
+ desc = "A special deck of space-grade playing cards with a mono-molecular edge and metal reinforcement, \
+ making them slightly more robust than a normal deck of cards. \
+ You can also play card games with them or leave them on your victims."
+ item = /obj/item/toy/cards/deck/syndicate
+ cost = 1
+ surplus = 40
- var/crate_value = starting_crate_value
- var/obj/structure/closet/crate/C = spawn_item(/obj/structure/closet/crate, user)
- if(U.purchase_log)
- U.purchase_log.LogPurchase(C, src, cost)
- while(crate_value)
- var/category = pick(uplink_items)
- var/item = pick(uplink_items[category])
- var/datum/uplink_item/I = uplink_items[category][item]
-
- if(!I.surplus || prob(100 - I.surplus))
- continue
- if(crate_value < I.cost)
- continue
- crate_value -= I.cost
- var/obj/goods = new I.item(C)
- if(U.purchase_log)
- U.purchase_log.LogPurchase(goods, I, 0)
- return C
-
-/datum/uplink_item/badass/random
- name = "Random Item"
- desc = "Picking this will purchase a random item. Useful if you have some TC to spare or if you haven't decided on a strategy yet."
- item = /obj/effect/gibspawner/generic // non-tangible item because techwebs use this path to determine illegal tech
- cost = 0
- cant_discount = TRUE
-
-/datum/uplink_item/badass/random/purchase(mob/user, datum/component/uplink/U)
- var/list/uplink_items = U.uplink_items
- var/list/possible_items = list()
- for(var/category in uplink_items)
- for(var/item in uplink_items[category])
- var/datum/uplink_item/I = uplink_items[category][item]
- if(src == I || !I.item)
- continue
- if(U.telecrystals < I.cost)
- continue
- if(I.limited_stock == 0)
- continue
- possible_items += I
-
- if(possible_items.len)
- var/datum/uplink_item/I = pick(possible_items)
- SSblackbox.record_feedback("tally", "traitor_random_uplink_items_gotten", 1, initial(I.name))
- U.MakePurchase(user, I)
+/datum/uplink_item/badass/syndiecigs
+ name = "Syndicate Smokes"
+ desc = "Strong flavor, dense smoke, infused with omnizine."
+ item = /obj/item/storage/fancy/cigarettes/cigpack_syndicate
+ cost = 2
diff --git a/code/modules/vehicles/_vehicle.dm b/code/modules/vehicles/_vehicle.dm
index be59a6df65..54bc03bcf3 100644
--- a/code/modules/vehicles/_vehicle.dm
+++ b/code/modules/vehicles/_vehicle.dm
@@ -31,6 +31,19 @@
occupant_actions = list()
generate_actions()
+/obj/vehicle/examine(mob/user)
+ ..()
+ if(resistance_flags & ON_FIRE)
+ to_chat(user, "It's on fire!")
+ var/healthpercent = obj_integrity/max_integrity * 100
+ switch(healthpercent)
+ if(50 to 99)
+ to_chat(user, "It looks slightly damaged.")
+ if(25 to 50)
+ to_chat(user, "It appears heavily damaged.")
+ if(0 to 25)
+ to_chat(user, "It's falling apart!")
+
/obj/vehicle/proc/is_key(obj/item/I)
return I? (key_type_exact? (I.type == key_type) : istype(I, key_type)) : FALSE
diff --git a/code/modules/vehicles/ridden.dm b/code/modules/vehicles/ridden.dm
index 25a337bc22..8fe7322579 100644
--- a/code/modules/vehicles/ridden.dm
+++ b/code/modules/vehicles/ridden.dm
@@ -4,8 +4,8 @@
max_buckled_mobs = 1
buckle_lying = FALSE
default_driver_move = FALSE
- var/legs_required = 2
- var/arms_requires = 0 //why not?
+ var/legs_required = 1
+ var/arms_required = 0 //why not?
/obj/vehicle/ridden/Initialize()
. = ..()
@@ -31,6 +31,9 @@
/obj/vehicle/ridden/post_buckle_mob(mob/living/M)
add_occupant(M)
+ if(M.get_num_legs() < legs_required)
+ to_chat(M, "You don't have enough legs to operate the pedals!")
+ unbuckle_mob(M)
return ..()
/obj/vehicle/ridden/attackby(obj/item/I, mob/user, params)
diff --git a/code/modules/vehicles/wheelchair.dm b/code/modules/vehicles/wheelchair.dm
new file mode 100644
index 0000000000..a5ba06e6fb
--- /dev/null
+++ b/code/modules/vehicles/wheelchair.dm
@@ -0,0 +1,110 @@
+/obj/vehicle/ridden/wheelchair //ported from Hippiestation (by Jujumatic) Then ported by Fermis from tg!
+ name = "wheelchair"
+ desc = "A chair with big wheels. It looks like you can move in this on your own."
+ icon = 'icons/obj/vehicles.dmi'
+ icon_state = "wheelchair"
+ layer = OBJ_LAYER
+ max_integrity = 100
+ armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 30) //Wheelchairs aren't super tough yo
+ legs_required = 0 //You'll probably be using this if you don't have legs
+ canmove = TRUE
+ density = FALSE //Thought I couldn't fix this one easily, phew
+ arms_required = 1
+
+/obj/vehicle/ridden/wheelchair/Initialize()
+ . = ..()
+ var/datum/component/riding/D = LoadComponent(/datum/component/riding)
+ D.vehicle_move_delay = 0
+ D.set_vehicle_dir_layer(SOUTH, OBJ_LAYER)
+ D.set_vehicle_dir_layer(NORTH, ABOVE_MOB_LAYER)
+ D.set_vehicle_dir_layer(EAST, OBJ_LAYER)
+ D.set_vehicle_dir_layer(WEST, OBJ_LAYER)
+
+/obj/vehicle/ridden/wheelchair/ComponentInitialize() //Since it's technically a chair I want it to have chair properties
+ . = ..()
+ AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE, CALLBACK(src, .proc/can_user_rotate),CALLBACK(src, .proc/can_be_rotated),null)
+
+/obj/vehicle/ridden/wheelchair/obj_destruction(damage_flag)
+ new /obj/item/stack/rods(drop_location(), 1)
+ new /obj/item/stack/sheet/metal(drop_location(), 1)
+ ..()
+
+/obj/vehicle/ridden/wheelchair/Destroy()
+ if(has_buckled_mobs())
+ var/mob/living/carbon/H = buckled_mobs[1]
+ unbuckle_mob(H)
+ return ..()
+
+/obj/vehicle/ridden/wheelchair/driver_move(mob/living/user, direction)
+ if(istype(user))
+ if(canmove && (user.get_num_arms() < arms_required))
+ to_chat(user, "You don't have enough arms to operate the wheels!")
+ canmove = FALSE
+ addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
+ return FALSE
+ var/datum/component/riding/D = GetComponent(/datum/component/riding)
+ //1.5 (movespeed as of this change) multiplied by 6.7 gets ABOUT 10 (rounded), the old constant for the wheelchair that gets divided by how many arms they have
+ //if that made no sense this simply makes the wheelchair speed change along with movement speed delay
+ D.vehicle_move_delay = round(CONFIG_GET(number/movedelay/run_delay) * 6.7) / min(user.get_num_arms(), 2)
+ return ..()
+
+/obj/vehicle/ridden/wheelchair/Moved()
+ . = ..()
+ cut_overlays()
+ playsound(src, 'sound/effects/roll.ogg', 75, 1)
+ if(has_buckled_mobs())
+ handle_rotation_overlayed()
+
+
+/obj/vehicle/ridden/wheelchair/post_buckle_mob(mob/living/user)
+ . = ..()
+ handle_rotation_overlayed()
+
+/obj/vehicle/ridden/wheelchair/post_unbuckle_mob()
+ . = ..()
+ cut_overlays()
+
+/obj/vehicle/ridden/wheelchair/setDir(newdir)
+ ..()
+ handle_rotation(newdir)
+
+/obj/vehicle/ridden/wheelchair/wrench_act(mob/living/user, obj/item/I) //Attackby should stop it attacking the wheelchair after moving away during decon
+ to_chat(user, "You begin to detach the wheels...")
+ if(I.use_tool(src, user, 40, volume=50))
+ to_chat(user, "You detach the wheels and deconstruct the chair.")
+ new /obj/item/stack/rods(drop_location(), 6)
+ new /obj/item/stack/sheet/metal(drop_location(), 4)
+ qdel(src)
+ return TRUE
+
+/obj/vehicle/ridden/wheelchair/proc/handle_rotation(direction)
+ if(has_buckled_mobs())
+ handle_rotation_overlayed()
+ for(var/m in buckled_mobs)
+ var/mob/living/buckled_mob = m
+ buckled_mob.setDir(direction)
+
+/obj/vehicle/ridden/wheelchair/proc/handle_rotation_overlayed()
+ cut_overlays()
+ var/image/V = image(icon = icon, icon_state = "wheelchair_overlay", layer = FLY_LAYER, dir = src.dir)
+ add_overlay(V)
+
+
+
+/obj/vehicle/ridden/wheelchair/proc/can_be_rotated(mob/living/user)
+ return TRUE
+
+/obj/vehicle/ridden/wheelchair/proc/can_user_rotate(mob/living/user)
+ var/mob/living/L = user
+ if(istype(L))
+ if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ return FALSE
+ if(isobserver(user) && CONFIG_GET(flag/ghost_interaction))
+ return TRUE
+ return FALSE
+
+/obj/vehicle/ridden/wheelchair/the_whip/driver_move(mob/living/user, direction)
+ if(istype(user))
+ var/datum/component/riding/D = GetComponent(/datum/component/riding)
+ D.vehicle_move_delay = round(CONFIG_GET(number/movedelay/run_delay) * 6.7) / user.get_num_arms()
+ return ..()
diff --git a/code/modules/vending/medical.dm b/code/modules/vending/medical.dm
index 5eba9b6b21..523606aa6a 100644
--- a/code/modules/vending/medical.dm
+++ b/code/modules/vending/medical.dm
@@ -32,7 +32,10 @@
/obj/item/reagent_containers/hypospray/medipen = 3,
/obj/item/storage/belt/medical = 3,
/obj/item/wrench/medical = 1,
- /obj/item/storage/briefcase/medical = 2)
+ /obj/item/storage/belt/medolier/full = 2,
+ /obj/item/gun/syringe/dart = 2,
+ /obj/item/storage/briefcase/medical = 2)
+
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
refill_canister = /obj/item/vending_refill/medical
diff --git a/code/modules/vending/medical_wall.dm b/code/modules/vending/medical_wall.dm
index 018eb09d86..514bbd8730 100644
--- a/code/modules/vending/medical_wall.dm
+++ b/code/modules/vending/medical_wall.dm
@@ -10,7 +10,8 @@
/obj/item/reagent_containers/medspray/styptic = 2,
/obj/item/reagent_containers/medspray/silver_sulf = 2,
/obj/item/reagent_containers/pill/charcoal = 2,
- /obj/item/reagent_containers/medspray/sterilizine = 1)
+ /obj/item/reagent_containers/medspray/sterilizine = 1,
+ /obj/item/reagent_containers/syringe/dart = 10)
contraband = list(/obj/item/reagent_containers/pill/tox = 2,
/obj/item/reagent_containers/pill/morphine = 2)
premium = list(/obj/item/reagent_containers/medspray/synthflesh = 2)
diff --git a/config/spaceRuinBlacklist.txt b/config/spaceRuinBlacklist.txt
index 6e74857e66..cba9a01e73 100644
--- a/config/spaceRuinBlacklist.txt
+++ b/config/spaceRuinBlacklist.txt
@@ -48,3 +48,4 @@
#_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm
#_maps/RandomRuins/SpaceRuins/bigape.dmm
#_maps/RandomRuins/SpaceRuins/arcade.dmm
+#_maps/RandomRuins/SpaceRuins/spacehermit.dmm
diff --git a/goon/browserassets/css/browserOutput.css b/goon/browserassets/css/browserOutput.css
deleted file mode 100644
index 820537e32b..0000000000
--- a/goon/browserassets/css/browserOutput.css
+++ /dev/null
@@ -1,362 +0,0 @@
-/*****************************************
-*
-* GLOBAL STYLES
-*
-******************************************/
-html, body {
- padding: 0;
- margin: 0;
- height: 100%;
- color: #000000;
-}
-body {
- background: #fff;
- font-family: Verdana, sans-serif;
- font-size: 9pt;
- line-height: 1.4;
- overflow-x: hidden;
- overflow-y: scroll;
- word-wrap: break-word;
-}
-
-em {
- font-style: normal;
- font-weight: bold;
-}
-
-img {
- margin: 0;
- padding: 0;
- line-height: 1;
-}
-img.icon {
- width: 16px;
- height: 16px;
-}
-
-a {color: #0000ff;}
-a.visited {color: #ff00ff;}
-a:visited {color: #ff00ff;}
-a.popt {text-decoration: none;}
-
-/*****************************************
-*
-* OUTPUT NOT RELATED TO ACTUAL MESSAGES
-*
-******************************************/
-#loading {
- position: fixed;
- width: 300px;
- height: 150px;
- text-align: center;
- left: 50%;
- top: 50%;
- margin: -75px 0 0 -150px;
-}
-#loading i {display: block; padding-bottom: 3px;}
-
-#messages {
- font-size: 14px;
- padding: 3px;
- margin: 0;
- word-wrap: break-word;
-}
-#newMessages {
- position: fixed;
- display: block;
- bottom: 0;
- right: 0;
- padding: 8px;
- background: #ddd;
- text-decoration: none;
- font-variant: small-caps;
- font-size: 1.1em;
- font-weight: bold;
- color: #333;
-}
-#newMessages:hover {background: #ccc;}
-#newMessages i {vertical-align: middle; padding-left: 3px;}
-#ping {
- position: fixed;
- top: 0;
- right: 40px;
- width: 45px;
- background: #ddd;
- height: 30px;
- padding: 8px 0 2px 0;
-}
-#ping i {display: block; text-align: center;}
-#ping .ms {
- display: block;
- text-align: center;
- font-size: 8pt;
- padding-top: 2px;
-}
-#options {
- position: fixed;
- top: 0;
- right: 0;
-}
-#options a {
- background: #ddd;
- height: 30px;
- padding: 5px 0;
- display: block;
- color: #333;
- text-decoration: none;
- line-height: 28px;
- border-top: 1px solid #b4b4b4;
-}
-#options a:hover {background: #ccc;}
-#options .toggle {
- width: 40px;
- background: #ccc;
- border-top: 0;
- float: right;
- text-align: center;
-}
-#options .sub {clear: both; display: none; width: 160px;}
-#options .sub.scroll {overflow-y: scroll;}
-#options .sub a {padding: 3px 0 3px 8px; line-height: 30px; font-size: 0.9em; clear: both;}
-#options .sub span {
- display: block;
- line-height: 30px;
- float: left;
-}
-#options .sub i {
- display: block;
- padding: 0 5px;
- font-size: 1.1em;
- width: 22px;
- text-align: center;
- line-height: 30px;
- float: right;
-}
-#options .decreaseFont {border-top: 0;}
-
-/* POPUPS */
-.popup {
- position: fixed;
- top: 50%;
- left: 50%;
- background: #ddd;
-}
-.popup .close {
- position: absolute;
- background: #aaa;
- top: 0;
- right: 0;
- color: #333;
- text-decoration: none;
- z-index: 2;
- padding: 0 10px;
- height: 30px;
- line-height: 30px;
-}
-.popup .close:hover {background: #999;}
-.popup .head {
- background: #999;
- color: #ddd;
- padding: 0 10px;
- height: 30px;
- line-height: 30px;
- text-transform: uppercase;
- font-size: 0.9em;
- font-weight: bold;
- border-bottom: 2px solid green;
-}
-.popup input {border: 1px solid #999; background: #fff; margin: 0; padding: 5px; outline: none; color: #333;}
-.popup input[type=text]:hover, .popup input[type=text]:active, .popup input[type=text]:focus {border-color: green;}
-.popup input[type=submit] {padding: 5px 10px; background: #999; color: #ddd; text-transform: uppercase; font-size: 0.9em; font-weight: bold;}
-.popup input[type=submit]:hover, .popup input[type=submit]:focus, .popup input[type=submit]:active {background: #aaa; cursor: pointer;}
-
-.changeFont {padding: 10px;}
-.changeFont a {display: block; text-decoration: none; padding: 3px; color: #333;}
-.changeFont a:hover {background: #ccc;}
-
-.highlightPopup {padding: 10px; text-align: center;}
-.highlightPopup input[type=text] {display: block; width: 215px; text-align: left; margin-top: 5px;}
-.highlightPopup input.highlightColor {background-color: #FFFF00;}
-.highlightPopup input.highlightTermSubmit {margin-top: 5px;}
-
-/* ADMIN CONTEXT MENU */
-.contextMenu {
- background-color: #ddd;
- position: fixed;
- margin: 2px;
- width: 150px;
-}
-.contextMenu a {
- display: block;
- padding: 2px 5px;
- text-decoration: none;
- color: #333;
-}
-
-.contextMenu a:hover {
- background-color: #ccc;
-}
-
-/* ADMIN FILTER MESSAGES MENU */
-.filterMessages {padding: 5px;}
-.filterMessages div {padding: 2px 0;}
-.filterMessages input {}
-.filterMessages label {}
-
-.icon-stack {height: 1em; line-height: 1em; width: 1em; vertical-align: middle; margin-top: -2px;}
-
-
-/*****************************************
-*
-* OUTPUT ACTUALLY RELATED TO MESSAGES
-*
-******************************************/
-
-/* MOTD */
-.motd {color: #638500; font-family: Verdana, sans-serif;}
-.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #638500; text-decoration: underline;}
-.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #638500;}
-
-/* ADD HERE FOR BOLD */
-.bold, .name, .prefix, .ooc, .looc, .adminooc, .admin, .medal, .yell {font-weight: bold;}
-
-/* ADD HERE FOR ITALIC */
-.italic, .italics, .emote {font-style: italic;}
-
-/* OUTPUT COLORS */
-.highlight {background: yellow;}
-
-h1, h2, h3, h4, h5, h6 {color: #0000ff;font-family: Georgia, Verdana, sans-serif;}
-h1.alert, h2.alert {color: #000000;}
-
-em {font-style: normal; font-weight: bold;}
-
-.adminobserverooc {color: #0099cc; font-weight: bold;}
-.adminooc {color: #b82e00; font-weight: bold;}
-.adminobserver {color: #996600; font-weight: bold;}
-.admin {color: #386aff; font-weight: bold;}
-/* SAY CLASSES */
-.say {}
-.deadsay {color: #5c00e6;}
-.siliconsay {font-family: 'Courier New', Courier, monospace;}
-/* RADIO CLASSES */
-.radio {color: #008000;}
-
-.syndradio {color: #6d3f40;}
-.centradio {color: #686868;}
-
-.aiprivradio {color: #ff00ff;}
-.comradio {color: #948f02;}
-
-.secradio {color: #a30000;}
-.engradio {color: #fb5613;}
-.medradio {color: #337296;}
-.sciradio {color: #993399;}
-.supradio {color: #a8732b;}
-.servadio {color: #6eaa2c;}
-
-.attack {color: #ff0000;}
-.disarm {color: #990000;}
-.passive {color: #660000;}
-
-.selecteddna {color: #ffffff; background-color: #001B1B}
-.alert {color: #ff0000;}
-.userdanger {color: #ff0000; font-weight: bold; font-size: 3;}
-.danger {color: #ff0000;}
-.warning {color: #ff0000; font-style: italic;}
-.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
-.announce {color: #228b22; font-weight: bold;}
-.boldannounce {color: #ff0000; font-weight: bold;}
-.greenannounce {color: #00ff00; font-weight: bold;}
-.rose {color: #ff5050;}
-.info {color: #0000CC;}
-.notice {color: #000099;}
-.boldnotice {color: #000099; font-weight: bold;}
-.adminnotice {color: #0000ff;}
-.unconscious {color: #0000ff; font-weight: bold;}
-.suicide {color: #ff5050; font-style: italic;}
-.green {color: #03ff39;}
-.shadowling {color: #3b2769;}
-.cult {color: #960000;}
-.cultitalic {color: #960000; font-style: italic;}
-.cultlarge {color: #960000; font-weight: bold; font-size: 3;}
-.narsie {color: #960000; font-weight: bold; font-size: 125px;}
-.narsiesmall {color: #960000; font-weight: bold; font-size: 6;}
-.colossus {color: #7F282A; font-size: 5;}
-.hierophant {color: #660099; font-weight: bold; font-style: italic;}
-.hierophant_warning {color: #660099; font-style: italic;}
-.purple {color: #5e2d79;}
-.holoparasite {color: #35333a;}
-.holoparasitebold {color: #35333a; font-weight: bold;}
-
-.revennotice {color: #1d2953;}
-.revenboldnotice {color: #1d2953; font-weight: bold;}
-.revenbignotice {color: #1d2953; font-weight: bold; font-size: 3;}
-.revenminor {color: #823abb}
-.revenwarning {color: #760fbb; font-style: italic;}
-.revendanger {color: #760fbb; font-weight: bold; font-size: 3;}
-.umbra {color: #5000A0;}
-.umbra_bold {color: #5000A0; font-weight: bold;}
-.umbra_italics {color: #5000A0; font-style: italic;}
-.umbra_emphasis {color: #5000A0; font-weight: bold; font-style: italic;}
-.umbra_large {color: #5000A0; font-size: 3;}
-
-.brass {color: #BE8700;}
-.heavy_brass {color: #BE8700; font-weight: bold; font-style: italic;}
-.large_brass {color: #BE8700; font-size: 3;}
-.big_brass {color: #BE8700; font-size: 3; font-weight: bold; font-style: italic;}
-.ratvar {color: #BE8700; font-size: 6; font-weight: bold; font-style: italic;}
-.alloy {color: #42474D;}
-.heavy_alloy {color: #42474D; font-weight: bold; font-style: italic;}
-.large_alloy {color: #42474D; font-size: 3;}
-.nezbere_large {color: #42474D; font-size: 3; font-weight: bold; font-style: italic;}
-.nezbere {color: #42474D; font-weight: bold; font-style: italic;}
-.nezbere_small {color: #42474D;}
-.sevtug_large {color: #AF0AAF; font-size: 3; font-weight: bold; font-style: italic;}
-.sevtug {color: #AF0AAF; font-weight: bold; font-style: italic;}
-.sevtug_small {color: #AF0AAF;}
-.inathneq_large {color: #1E8CE1; font-size: 3; font-weight: bold; font-style: italic;}
-.inathneq {color: #1E8CE1; font-weight: bold; font-style: italic;}
-.inathneq_small {color: #1E8CE1;}
-.nzcrentr_large {color: #DAAA18; font-size: 3; font-weight: bold; font-style: italic;}
-.nzcrentr {color: #DAAA18; font-weight: bold; font-style: italic;}
-.nzcrentr_small {color: #DAAA18;}
-.neovgre_large {color: #6E001A; font-size: 3; font-weight: bold; font-style: italic;}
-.neovgre {color: #6E001A; font-weight: bold; font-style: italic;}
-.neovgre_small {color: #6E001A;}
-
-.newscaster {color: #800000;}
-.ghostalert {color: #5c00e6; font-style: italic; font-weight: bold;}
-
-.alien {color: #543354;}
-.noticealien {color: #00c000;}
-.alertalien {color: #00c000; font-weight: bold;}
-.borer {color: #543354; font-style: italic;}
-.changeling {color: #800080; font-style: italic;}
-
-.interface {color: #330033;}
-
-.sans {font-family: "Comic Sans MS", cursive, sans-serif;}
-.papyrus {font-family: "Papyrus", cursive, sans-serif;}
-.robot {font-family: "Courier New", cursive, sans-serif;}
-
-.command_headset {font-weight: bold; font-size: 3;}
-.big {font-size: 3;}
-.reallybig {font-size: 4;}
-.greentext {color: #00FF00; font-size: 3;}
-.redtext {color: #FF0000; font-size: 3;}
-.clown {color: #FF69Bf; font-size: 3; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
-
-big img.icon {width: 32px; height: 32px;}
-
-.memo {color: #638500; text-align: center;}
-.memoedit {text-align: center; font-size: 2;}
-.abductor {color: #800080; font-style: italic;}
-
-.connectionClosed, .fatalError {background: red; color: white; padding: 5px;}
-.connectionClosed.restored {background: green;}
-.internal.boldnshit {color: blue; font-weight: bold;}
-
-/* HELPER CLASSES */
-.text-normal {font-weight: normal; font-style: normal;}
-.hidden {display: none; visibility: hidden;}
\ No newline at end of file
diff --git a/goon/browserassets/css/font-awesome.css b/goon/browserassets/css/font-awesome.css
deleted file mode 100644
index cc99d7b337..0000000000
--- a/goon/browserassets/css/font-awesome.css
+++ /dev/null
@@ -1,788 +0,0 @@
-@font-face{font-family:'FontAwesome';src:url('fontawesome-webfont.eot');src:url('fontawesome-webfont.eot') format('embedded-opentype'),url('fontawesome-webfont.woff') format('woff'),url('fontawesome-webfont.ttf') format('truetype'),url('fontawesome-webfont.svg') format('svg');font-weight:normal;font-style:normal;}[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;}
-[class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none;}
-.icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em;}
-a [class^="icon-"],a [class*=" icon-"]{display:inline;}
-[class^="icon-"].icon-fixed-width,[class*=" icon-"].icon-fixed-width{display:inline-block;width:1.1428571428571428em;text-align:right;padding-right:0.2857142857142857em;}[class^="icon-"].icon-fixed-width.icon-large,[class*=" icon-"].icon-fixed-width.icon-large{width:1.4285714285714286em;}
-.icons-ul{margin-left:2.142857142857143em;list-style-type:none;}.icons-ul>li{position:relative;}
-.icons-ul .icon-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;text-align:center;line-height:inherit;}
-[class^="icon-"].hide,[class*=" icon-"].hide{display:none;}
-.icon-muted{color:#eeeeee;}
-.icon-light{color:#ffffff;}
-.icon-dark{color:#333333;}
-.icon-border{border:solid 1px #eeeeee;padding:.2em .25em .15em;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
-.icon-2x{font-size:2em;}.icon-2x.icon-border{border-width:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
-.icon-3x{font-size:3em;}.icon-3x.icon-border{border-width:3px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
-.icon-4x{font-size:4em;}.icon-4x.icon-border{border-width:4px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
-.icon-5x{font-size:5em;}.icon-5x.icon-border{border-width:5px;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px;}
-.pull-right{float:right;}
-.pull-left{float:left;}
-[class^="icon-"].pull-left,[class*=" icon-"].pull-left{margin-right:.3em;}
-[class^="icon-"].pull-right,[class*=" icon-"].pull-right{margin-left:.3em;}
-[class^="icon-"],[class*=" icon-"]{display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0% 0%;background-repeat:repeat;margin-top:0;}
-.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:none;}
-.btn [class^="icon-"].icon-large,.nav [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large,.nav [class*=" icon-"].icon-large{line-height:.9em;}
-.btn [class^="icon-"].icon-spin,.nav [class^="icon-"].icon-spin,.btn [class*=" icon-"].icon-spin,.nav [class*=" icon-"].icon-spin{display:inline-block;}
-.nav-tabs [class^="icon-"],.nav-pills [class^="icon-"],.nav-tabs [class*=" icon-"],.nav-pills [class*=" icon-"],.nav-tabs [class^="icon-"].icon-large,.nav-pills [class^="icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large{line-height:.9em;}
-.btn [class^="icon-"].pull-left.icon-2x,.btn [class*=" icon-"].pull-left.icon-2x,.btn [class^="icon-"].pull-right.icon-2x,.btn [class*=" icon-"].pull-right.icon-2x{margin-top:.18em;}
-.btn [class^="icon-"].icon-spin.icon-large,.btn [class*=" icon-"].icon-spin.icon-large{line-height:.8em;}
-.btn.btn-small [class^="icon-"].pull-left.icon-2x,.btn.btn-small [class*=" icon-"].pull-left.icon-2x,.btn.btn-small [class^="icon-"].pull-right.icon-2x,.btn.btn-small [class*=" icon-"].pull-right.icon-2x{margin-top:.25em;}
-.btn.btn-large [class^="icon-"],.btn.btn-large [class*=" icon-"]{margin-top:0;}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x,.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-top:.05em;}
-.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x{margin-right:.2em;}
-.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-left:.2em;}
-.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{line-height:inherit;}
-.icon-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:-35%;}.icon-stack [class^="icon-"],.icon-stack [class*=" icon-"]{display:block;text-align:center;position:absolute;width:100%;height:100%;font-size:1em;line-height:inherit;*line-height:2em;}
-.icon-stack .icon-stack-base{font-size:2em;*line-height:1em;}
-.icon-spin{display:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear;}
-a .icon-stack,a .icon-spin{display:inline-block;text-decoration:none;}
-@-moz-keyframes spin{0%{-moz-transform:rotate(0deg);} 100%{-moz-transform:rotate(359deg);}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg);} 100%{-webkit-transform:rotate(359deg);}}@-o-keyframes spin{0%{-o-transform:rotate(0deg);} 100%{-o-transform:rotate(359deg);}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg);} 100%{-ms-transform:rotate(359deg);}}@keyframes spin{0%{transform:rotate(0deg);} 100%{transform:rotate(359deg);}}.icon-rotate-90:before{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);}
-.icon-rotate-180:before{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);}
-.icon-rotate-270:before{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);}
-.icon-flip-horizontal:before{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1);}
-.icon-flip-vertical:before{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1);}
-a .icon-rotate-90:before,a .icon-rotate-180:before,a .icon-rotate-270:before,a .icon-flip-horizontal:before,a .icon-flip-vertical:before{display:inline-block;}
-.icon-glass:before{content:"\f000";}
-.icon-music:before{content:"\f001";}
-.icon-search:before{content:"\f002";}
-.icon-envelope-alt:before{content:"\f003";}
-.icon-heart:before{content:"\f004";}
-.icon-star:before{content:"\f005";}
-.icon-star-empty:before{content:"\f006";}
-.icon-user:before{content:"\f007";}
-.icon-film:before{content:"\f008";}
-.icon-th-large:before{content:"\f009";}
-.icon-th:before{content:"\f00a";}
-.icon-th-list:before{content:"\f00b";}
-.icon-ok:before{content:"\f00c";}
-.icon-remove:before{content:"\f00d";}
-.icon-zoom-in:before{content:"\f00e";}
-.icon-zoom-out:before{content:"\f010";}
-.icon-power-off:before,.icon-off:before{content:"\f011";}
-.icon-signal:before{content:"\f012";}
-.icon-gear:before,.icon-cog:before{content:"\f013";}
-.icon-trash:before{content:"\f014";}
-.icon-home:before{content:"\f015";}
-.icon-file-alt:before{content:"\f016";}
-.icon-time:before{content:"\f017";}
-.icon-road:before{content:"\f018";}
-.icon-download-alt:before{content:"\f019";}
-.icon-download:before{content:"\f01a";}
-.icon-upload:before{content:"\f01b";}
-.icon-inbox:before{content:"\f01c";}
-.icon-play-circle:before{content:"\f01d";}
-.icon-rotate-right:before,.icon-repeat:before{content:"\f01e";}
-.icon-refresh:before{content:"\f021";}
-.icon-list-alt:before{content:"\f022";}
-.icon-lock:before{content:"\f023";}
-.icon-flag:before{content:"\f024";}
-.icon-headphones:before{content:"\f025";}
-.icon-volume-off:before{content:"\f026";}
-.icon-volume-down:before{content:"\f027";}
-.icon-volume-up:before{content:"\f028";}
-.icon-qrcode:before{content:"\f029";}
-.icon-barcode:before{content:"\f02a";}
-.icon-tag:before{content:"\f02b";}
-.icon-tags:before{content:"\f02c";}
-.icon-book:before{content:"\f02d";}
-.icon-bookmark:before{content:"\f02e";}
-.icon-print:before{content:"\f02f";}
-.icon-camera:before{content:"\f030";}
-.icon-font:before{content:"\f031";}
-.icon-bold:before{content:"\f032";}
-.icon-italic:before{content:"\f033";}
-.icon-text-height:before{content:"\f034";}
-.icon-text-width:before{content:"\f035";}
-.icon-align-left:before{content:"\f036";}
-.icon-align-center:before{content:"\f037";}
-.icon-align-right:before{content:"\f038";}
-.icon-align-justify:before{content:"\f039";}
-.icon-list:before{content:"\f03a";}
-.icon-indent-left:before{content:"\f03b";}
-.icon-indent-right:before{content:"\f03c";}
-.icon-facetime-video:before{content:"\f03d";}
-.icon-picture:before{content:"\f03e";}
-.icon-pencil:before{content:"\f040";}
-.icon-map-marker:before{content:"\f041";}
-.icon-adjust:before{content:"\f042";}
-.icon-tint:before{content:"\f043";}
-.icon-edit:before{content:"\f044";}
-.icon-share:before{content:"\f045";}
-.icon-check:before{content:"\f046";}
-.icon-move:before{content:"\f047";}
-.icon-step-backward:before{content:"\f048";}
-.icon-fast-backward:before{content:"\f049";}
-.icon-backward:before{content:"\f04a";}
-.icon-play:before{content:"\f04b";}
-.icon-pause:before{content:"\f04c";}
-.icon-stop:before{content:"\f04d";}
-.icon-forward:before{content:"\f04e";}
-.icon-fast-forward:before{content:"\f050";}
-.icon-step-forward:before{content:"\f051";}
-.icon-eject:before{content:"\f052";}
-.icon-chevron-left:before{content:"\f053";}
-.icon-chevron-right:before{content:"\f054";}
-.icon-plus-sign:before{content:"\f055";}
-.icon-minus-sign:before{content:"\f056";}
-.icon-remove-sign:before{content:"\f057";}
-.icon-ok-sign:before{content:"\f058";}
-.icon-question-sign:before{content:"\f059";}
-.icon-info-sign:before{content:"\f05a";}
-.icon-screenshot:before{content:"\f05b";}
-.icon-remove-circle:before{content:"\f05c";}
-.icon-ok-circle:before{content:"\f05d";}
-.icon-ban-circle:before{content:"\f05e";}
-.icon-arrow-left:before{content:"\f060";}
-.icon-arrow-right:before{content:"\f061";}
-.icon-arrow-up:before{content:"\f062";}
-.icon-arrow-down:before{content:"\f063";}
-.icon-mail-forward:before,.icon-share-alt:before{content:"\f064";}
-.icon-resize-full:before{content:"\f065";}
-.icon-resize-small:before{content:"\f066";}
-.icon-plus:before{content:"\f067";}
-.icon-minus:before{content:"\f068";}
-.icon-asterisk:before{content:"\f069";}
-.icon-exclamation-sign:before{content:"\f06a";}
-.icon-gift:before{content:"\f06b";}
-.icon-leaf:before{content:"\f06c";}
-.icon-fire:before{content:"\f06d";}
-.icon-eye-open:before{content:"\f06e";}
-.icon-eye-close:before{content:"\f070";}
-.icon-warning-sign:before{content:"\f071";}
-.icon-plane:before{content:"\f072";}
-.icon-calendar:before{content:"\f073";}
-.icon-random:before{content:"\f074";}
-.icon-comment:before{content:"\f075";}
-.icon-magnet:before{content:"\f076";}
-.icon-chevron-up:before{content:"\f077";}
-.icon-chevron-down:before{content:"\f078";}
-.icon-retweet:before{content:"\f079";}
-.icon-shopping-cart:before{content:"\f07a";}
-.icon-folder-close:before{content:"\f07b";}
-.icon-folder-open:before{content:"\f07c";}
-.icon-resize-vertical:before{content:"\f07d";}
-.icon-resize-horizontal:before{content:"\f07e";}
-.icon-bar-chart:before{content:"\f080";}
-.icon-twitter-sign:before{content:"\f081";}
-.icon-facebook-sign:before{content:"\f082";}
-.icon-camera-retro:before{content:"\f083";}
-.icon-key:before{content:"\f084";}
-.icon-gears:before,.icon-cogs:before{content:"\f085";}
-.icon-comments:before{content:"\f086";}
-.icon-thumbs-up-alt:before{content:"\f087";}
-.icon-thumbs-down-alt:before{content:"\f088";}
-.icon-star-half:before{content:"\f089";}
-.icon-heart-empty:before{content:"\f08a";}
-.icon-signout:before{content:"\f08b";}
-.icon-linkedin-sign:before{content:"\f08c";}
-.icon-pushpin:before{content:"\f08d";}
-.icon-external-link:before{content:"\f08e";}
-.icon-signin:before{content:"\f090";}
-.icon-trophy:before{content:"\f091";}
-.icon-github-sign:before{content:"\f092";}
-.icon-upload-alt:before{content:"\f093";}
-.icon-lemon:before{content:"\f094";}
-.icon-phone:before{content:"\f095";}
-.icon-unchecked:before,.icon-check-empty:before{content:"\f096";}
-.icon-bookmark-empty:before{content:"\f097";}
-.icon-phone-sign:before{content:"\f098";}
-.icon-twitter:before{content:"\f099";}
-.icon-facebook:before{content:"\f09a";}
-.icon-github:before{content:"\f09b";}
-.icon-unlock:before{content:"\f09c";}
-.icon-credit-card:before{content:"\f09d";}
-.icon-rss:before{content:"\f09e";}
-.icon-hdd:before{content:"\f0a0";}
-.icon-bullhorn:before{content:"\f0a1";}
-.icon-bell:before{content:"\f0a2";}
-.icon-certificate:before{content:"\f0a3";}
-.icon-hand-right:before{content:"\f0a4";}
-.icon-hand-left:before{content:"\f0a5";}
-.icon-hand-up:before{content:"\f0a6";}
-.icon-hand-down:before{content:"\f0a7";}
-.icon-circle-arrow-left:before{content:"\f0a8";}
-.icon-circle-arrow-right:before{content:"\f0a9";}
-.icon-circle-arrow-up:before{content:"\f0aa";}
-.icon-circle-arrow-down:before{content:"\f0ab";}
-.icon-globe:before{content:"\f0ac";}
-.icon-wrench:before{content:"\f0ad";}
-.icon-tasks:before{content:"\f0ae";}
-.icon-filter:before{content:"\f0b0";}
-.icon-briefcase:before{content:"\f0b1";}
-.icon-fullscreen:before{content:"\f0b2";}
-.icon-group:before{content:"\f0c0";}
-.icon-link:before{content:"\f0c1";}
-.icon-cloud:before{content:"\f0c2";}
-.icon-beaker:before{content:"\f0c3";}
-.icon-cut:before{content:"\f0c4";}
-.icon-copy:before{content:"\f0c5";}
-.icon-paperclip:before,.icon-paper-clip:before{content:"\f0c6";}
-.icon-save:before{content:"\f0c7";}
-.icon-sign-blank:before{content:"\f0c8";}
-.icon-reorder:before{content:"\f0c9";}
-.icon-list-ul:before{content:"\f0ca";}
-.icon-list-ol:before{content:"\f0cb";}
-.icon-strikethrough:before{content:"\f0cc";}
-.icon-underline:before{content:"\f0cd";}
-.icon-table:before{content:"\f0ce";}
-.icon-magic:before{content:"\f0d0";}
-.icon-truck:before{content:"\f0d1";}
-.icon-pinterest:before{content:"\f0d2";}
-.icon-pinterest-sign:before{content:"\f0d3";}
-.icon-google-plus-sign:before{content:"\f0d4";}
-.icon-google-plus:before{content:"\f0d5";}
-.icon-money:before{content:"\f0d6";}
-.icon-caret-down:before{content:"\f0d7";}
-.icon-caret-up:before{content:"\f0d8";}
-.icon-caret-left:before{content:"\f0d9";}
-.icon-caret-right:before{content:"\f0da";}
-.icon-columns:before{content:"\f0db";}
-.icon-sort:before{content:"\f0dc";}
-.icon-sort-down:before{content:"\f0dd";}
-.icon-sort-up:before{content:"\f0de";}
-.icon-envelope:before{content:"\f0e0";}
-.icon-linkedin:before{content:"\f0e1";}
-.icon-rotate-left:before,.icon-undo:before{content:"\f0e2";}
-.icon-legal:before{content:"\f0e3";}
-.icon-dashboard:before{content:"\f0e4";}
-.icon-comment-alt:before{content:"\f0e5";}
-.icon-comments-alt:before{content:"\f0e6";}
-.icon-bolt:before{content:"\f0e7";}
-.icon-sitemap:before{content:"\f0e8";}
-.icon-umbrella:before{content:"\f0e9";}
-.icon-paste:before{content:"\f0ea";}
-.icon-lightbulb:before{content:"\f0eb";}
-.icon-exchange:before{content:"\f0ec";}
-.icon-cloud-download:before{content:"\f0ed";}
-.icon-cloud-upload:before{content:"\f0ee";}
-.icon-user-md:before{content:"\f0f0";}
-.icon-stethoscope:before{content:"\f0f1";}
-.icon-suitcase:before{content:"\f0f2";}
-.icon-bell-alt:before{content:"\f0f3";}
-.icon-coffee:before{content:"\f0f4";}
-.icon-food:before{content:"\f0f5";}
-.icon-file-text-alt:before{content:"\f0f6";}
-.icon-building:before{content:"\f0f7";}
-.icon-hospital:before{content:"\f0f8";}
-.icon-ambulance:before{content:"\f0f9";}
-.icon-medkit:before{content:"\f0fa";}
-.icon-fighter-jet:before{content:"\f0fb";}
-.icon-beer:before{content:"\f0fc";}
-.icon-h-sign:before{content:"\f0fd";}
-.icon-plus-sign-alt:before{content:"\f0fe";}
-.icon-double-angle-left:before{content:"\f100";}
-.icon-double-angle-right:before{content:"\f101";}
-.icon-double-angle-up:before{content:"\f102";}
-.icon-double-angle-down:before{content:"\f103";}
-.icon-angle-left:before{content:"\f104";}
-.icon-angle-right:before{content:"\f105";}
-.icon-angle-up:before{content:"\f106";}
-.icon-angle-down:before{content:"\f107";}
-.icon-desktop:before{content:"\f108";}
-.icon-laptop:before{content:"\f109";}
-.icon-tablet:before{content:"\f10a";}
-.icon-mobile-phone:before{content:"\f10b";}
-.icon-circle-blank:before{content:"\f10c";}
-.icon-quote-left:before{content:"\f10d";}
-.icon-quote-right:before{content:"\f10e";}
-.icon-spinner:before{content:"\f110";}
-.icon-circle:before{content:"\f111";}
-.icon-mail-reply:before,.icon-reply:before{content:"\f112";}
-.icon-github-alt:before{content:"\f113";}
-.icon-folder-close-alt:before{content:"\f114";}
-.icon-folder-open-alt:before{content:"\f115";}
-.icon-expand-alt:before{content:"\f116";}
-.icon-collapse-alt:before{content:"\f117";}
-.icon-smile:before{content:"\f118";}
-.icon-frown:before{content:"\f119";}
-.icon-meh:before{content:"\f11a";}
-.icon-gamepad:before{content:"\f11b";}
-.icon-keyboard:before{content:"\f11c";}
-.icon-flag-alt:before{content:"\f11d";}
-.icon-flag-checkered:before{content:"\f11e";}
-.icon-terminal:before{content:"\f120";}
-.icon-code:before{content:"\f121";}
-.icon-reply-all:before{content:"\f122";}
-.icon-mail-reply-all:before{content:"\f122";}
-.icon-star-half-full:before,.icon-star-half-empty:before{content:"\f123";}
-.icon-location-arrow:before{content:"\f124";}
-.icon-crop:before{content:"\f125";}
-.icon-code-fork:before{content:"\f126";}
-.icon-unlink:before{content:"\f127";}
-.icon-question:before{content:"\f128";}
-.icon-info:before{content:"\f129";}
-.icon-exclamation:before{content:"\f12a";}
-.icon-superscript:before{content:"\f12b";}
-.icon-subscript:before{content:"\f12c";}
-.icon-eraser:before{content:"\f12d";}
-.icon-puzzle-piece:before{content:"\f12e";}
-.icon-microphone:before{content:"\f130";}
-.icon-microphone-off:before{content:"\f131";}
-.icon-shield:before{content:"\f132";}
-.icon-calendar-empty:before{content:"\f133";}
-.icon-fire-extinguisher:before{content:"\f134";}
-.icon-rocket:before{content:"\f135";}
-.icon-maxcdn:before{content:"\f136";}
-.icon-chevron-sign-left:before{content:"\f137";}
-.icon-chevron-sign-right:before{content:"\f138";}
-.icon-chevron-sign-up:before{content:"\f139";}
-.icon-chevron-sign-down:before{content:"\f13a";}
-.icon-html5:before{content:"\f13b";}
-.icon-css3:before{content:"\f13c";}
-.icon-anchor:before{content:"\f13d";}
-.icon-unlock-alt:before{content:"\f13e";}
-.icon-bullseye:before{content:"\f140";}
-.icon-ellipsis-horizontal:before{content:"\f141";}
-.icon-ellipsis-vertical:before{content:"\f142";}
-.icon-rss-sign:before{content:"\f143";}
-.icon-play-sign:before{content:"\f144";}
-.icon-ticket:before{content:"\f145";}
-.icon-minus-sign-alt:before{content:"\f146";}
-.icon-check-minus:before{content:"\f147";}
-.icon-level-up:before{content:"\f148";}
-.icon-level-down:before{content:"\f149";}
-.icon-check-sign:before{content:"\f14a";}
-.icon-edit-sign:before{content:"\f14b";}
-.icon-external-link-sign:before{content:"\f14c";}
-.icon-share-sign:before{content:"\f14d";}
-.icon-compass:before{content:"\f14e";}
-.icon-collapse:before{content:"\f150";}
-.icon-collapse-top:before{content:"\f151";}
-.icon-expand:before{content:"\f152";}
-.icon-euro:before,.icon-eur:before{content:"\f153";}
-.icon-gbp:before{content:"\f154";}
-.icon-dollar:before,.icon-usd:before{content:"\f155";}
-.icon-rupee:before,.icon-inr:before{content:"\f156";}
-.icon-yen:before,.icon-jpy:before{content:"\f157";}
-.icon-renminbi:before,.icon-cny:before{content:"\f158";}
-.icon-won:before,.icon-krw:before{content:"\f159";}
-.icon-bitcoin:before,.icon-btc:before{content:"\f15a";}
-.icon-file:before{content:"\f15b";}
-.icon-file-text:before{content:"\f15c";}
-.icon-sort-by-alphabet:before{content:"\f15d";}
-.icon-sort-by-alphabet-alt:before{content:"\f15e";}
-.icon-sort-by-attributes:before{content:"\f160";}
-.icon-sort-by-attributes-alt:before{content:"\f161";}
-.icon-sort-by-order:before{content:"\f162";}
-.icon-sort-by-order-alt:before{content:"\f163";}
-.icon-thumbs-up:before{content:"\f164";}
-.icon-thumbs-down:before{content:"\f165";}
-.icon-youtube-sign:before{content:"\f166";}
-.icon-youtube:before{content:"\f167";}
-.icon-xing:before{content:"\f168";}
-.icon-xing-sign:before{content:"\f169";}
-.icon-youtube-play:before{content:"\f16a";}
-.icon-dropbox:before{content:"\f16b";}
-.icon-stackexchange:before{content:"\f16c";}
-.icon-instagram:before{content:"\f16d";}
-.icon-flickr:before{content:"\f16e";}
-.icon-adn:before{content:"\f170";}
-.icon-bitbucket:before{content:"\f171";}
-.icon-bitbucket-sign:before{content:"\f172";}
-.icon-tumblr:before{content:"\f173";}
-.icon-tumblr-sign:before{content:"\f174";}
-.icon-long-arrow-down:before{content:"\f175";}
-.icon-long-arrow-up:before{content:"\f176";}
-.icon-long-arrow-left:before{content:"\f177";}
-.icon-long-arrow-right:before{content:"\f178";}
-.icon-apple:before{content:"\f179";}
-.icon-windows:before{content:"\f17a";}
-.icon-android:before{content:"\f17b";}
-.icon-linux:before{content:"\f17c";}
-.icon-dribbble:before{content:"\f17d";}
-.icon-skype:before{content:"\f17e";}
-.icon-foursquare:before{content:"\f180";}
-.icon-trello:before{content:"\f181";}
-.icon-female:before{content:"\f182";}
-.icon-male:before{content:"\f183";}
-.icon-gittip:before{content:"\f184";}
-.icon-sun:before{content:"\f185";}
-.icon-moon:before{content:"\f186";}
-.icon-archive:before{content:"\f187";}
-.icon-bug:before{content:"\f188";}
-.icon-vk:before{content:"\f189";}
-.icon-weibo:before{content:"\f18a";}
-.icon-renren:before{content:"\f18b";}
-
-.icon-large{font-size:1.3333333333333333em;margin-top:-4px;padding-top:3px;margin-bottom:-4px;padding-bottom:3px;vertical-align:middle;}
-.nav [class^="icon-"],.nav [class*=" icon-"]{vertical-align:inherit;margin-top:-4px;padding-top:3px;margin-bottom:-4px;padding-bottom:3px;}.nav [class^="icon-"].icon-large,.nav [class*=" icon-"].icon-large{vertical-align:-25%;}
-.nav-pills [class^="icon-"].icon-large,.nav-tabs [class^="icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large{line-height:.75em;margin-top:-7px;padding-top:5px;margin-bottom:-5px;padding-bottom:4px;}
-.btn [class^="icon-"].pull-left,.btn [class*=" icon-"].pull-left,.btn [class^="icon-"].pull-right,.btn [class*=" icon-"].pull-right{vertical-align:inherit;}
-.btn [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large{margin-top:-0.5em;}
-a [class^="icon-"],a [class*=" icon-"]{cursor:pointer;}
-.icon-glass{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-music{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-search{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-envelope-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-heart{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-star{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-star-empty{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-user{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-film{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-th-large{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-th{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-th-list{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-ok{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-remove{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-zoom-in{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-zoom-out{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-off{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-power-off{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-signal{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-cog{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-gear{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-trash{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-home{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-file-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-time{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-road{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-download-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-download{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-upload{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-inbox{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-play-circle{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-repeat{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-rotate-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-refresh{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-list-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-lock{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-flag{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-headphones{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-volume-off{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-volume-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-volume-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-qrcode{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-barcode{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-tag{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-tags{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-book{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bookmark{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-print{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-camera{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-font{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bold{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-italic{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-text-height{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-text-width{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-align-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-align-center{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-align-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-align-justify{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-list{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-indent-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-indent-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-facetime-video{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-picture{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-pencil{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-map-marker{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-adjust{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-tint{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-edit{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-share{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-check{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-move{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-step-backward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-fast-backward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-backward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-play{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-pause{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-stop{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-forward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-fast-forward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-step-forward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-eject{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-chevron-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-chevron-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-plus-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-minus-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-remove-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-ok-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-question-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-info-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-screenshot{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-remove-circle{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-ok-circle{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-ban-circle{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-arrow-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-arrow-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-arrow-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-arrow-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-share-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-mail-forward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-resize-full{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-resize-small{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-plus{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-minus{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-asterisk{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-exclamation-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-gift{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-leaf{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-fire{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-eye-open{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-eye-close{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-warning-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-plane{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-calendar{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-random{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-comment{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-magnet{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-chevron-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-chevron-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-retweet{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-shopping-cart{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-folder-close{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-folder-open{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-resize-vertical{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-resize-horizontal{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bar-chart{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-twitter-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-facebook-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-camera-retro{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-key{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-cogs{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-gears{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-comments{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-thumbs-up-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-thumbs-down-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-star-half{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-heart-empty{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-signout{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-linkedin-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-pushpin{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-external-link{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-signin{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-trophy{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-github-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-upload-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-lemon{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-phone{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-check-empty{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-unchecked{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bookmark-empty{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-phone-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-twitter{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-facebook{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-github{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-unlock{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-credit-card{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-rss{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-hdd{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bullhorn{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bell{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-certificate{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-hand-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-hand-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-hand-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-hand-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-circle-arrow-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-circle-arrow-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-circle-arrow-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-circle-arrow-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-globe{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-wrench{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-tasks{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-filter{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-briefcase{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-fullscreen{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-group{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-link{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-cloud{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-beaker{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-cut{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-copy{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-paper-clip{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-paperclip{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-save{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-sign-blank{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-reorder{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-list-ul{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-list-ol{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-strikethrough{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-underline{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-table{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-magic{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-truck{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-pinterest{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-pinterest-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-google-plus-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-google-plus{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-money{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-caret-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-caret-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-caret-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-caret-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-columns{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-sort{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-sort-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-sort-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-envelope{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-linkedin{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-undo{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-rotate-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-legal{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-dashboard{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-comment-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-comments-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bolt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-sitemap{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-umbrella{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-paste{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-lightbulb{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-exchange{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-cloud-download{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-cloud-upload{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-user-md{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-stethoscope{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-suitcase{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bell-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-coffee{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-food{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-file-text-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-building{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-hospital{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-ambulance{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-medkit{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-fighter-jet{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-beer{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-h-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-plus-sign-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-double-angle-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-double-angle-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-double-angle-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-double-angle-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-angle-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-angle-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-angle-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-angle-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-desktop{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-laptop{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-tablet{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-mobile-phone{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-circle-blank{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-quote-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-quote-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-spinner{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-circle{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-reply{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-mail-reply{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-github-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-folder-close-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-folder-open-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-expand-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-collapse-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-smile{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-frown{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-meh{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-gamepad{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-keyboard{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-flag-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-flag-checkered{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-terminal{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-code{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-reply-all{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-mail-reply-all{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-star-half-empty{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-star-half-full{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-location-arrow{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-crop{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-code-fork{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-unlink{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-question{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-info{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-exclamation{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-superscript{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-subscript{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-eraser{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-puzzle-piece{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-microphone{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-microphone-off{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-shield{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-calendar-empty{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-fire-extinguisher{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-rocket{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-maxcdn{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-chevron-sign-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-chevron-sign-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-chevron-sign-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-chevron-sign-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-html5{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-css3{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-anchor{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-unlock-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bullseye{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-ellipsis-horizontal{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-ellipsis-vertical{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-rss-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-play-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-ticket{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-minus-sign-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-check-minus{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-level-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-level-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-check-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-edit-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-external-link-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-share-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-compass{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-collapse{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-collapse-top{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-expand{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-eur{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-euro{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-gbp{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-usd{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-dollar{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-inr{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-rupee{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-jpy{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-yen{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-cny{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-renminbi{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-krw{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-won{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-btc{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bitcoin{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-file{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-file-text{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-sort-by-alphabet{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-sort-by-alphabet-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-sort-by-attributes{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-sort-by-attributes-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-sort-by-order{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-sort-by-order-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-thumbs-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-thumbs-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-youtube-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-youtube{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-xing{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-xing-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-youtube-play{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-dropbox{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-stackexchange{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-instagram{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-flickr{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-adn{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bitbucket{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bitbucket-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-tumblr{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-tumblr-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-long-arrow-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-long-arrow-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-long-arrow-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-long-arrow-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-apple{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-windows{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-android{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-linux{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-dribbble{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-skype{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-foursquare{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-trello{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-female{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-male{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-gittip{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-sun{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-moon{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-archive{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-bug{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-vk{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-weibo{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
-.icon-renren{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '');}
\ No newline at end of file
diff --git a/goon/browserassets/html/browserOutput.html b/goon/browserassets/html/browserOutput.html
deleted file mode 100644
index 74212fd815..0000000000
--- a/goon/browserassets/html/browserOutput.html
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
- Chat
-
-
-
-
-
-
-
-
-
-
-
- Loading...
- If this takes longer than 30 seconds, it will automatically reload a maximum of 5 times.
- If it still doesn't work, use the bug report button at the top right of the window.
-
Choose up to '+opts.highlightLimit+' strings that will highlight the line when they appear in chat.
' +
- '' +
- '
';
- createPopup(popupContent, 250);
- });
-
- $('body').on('keyup', '#highlightColor', function() {
- var color = $('#highlightColor').val();
- color = color.trim();
- if (!color || color.charAt(0) != '#') return;
- $('#highlightColor').css('background-color', color);
- });
-
- $('body').on('submit', '#highlightTermForm', function(e) {
- e.preventDefault();
-
- var count = 0;
- while (count < opts.highlightLimit) {
- var term = $('#highlightTermInput'+count).val();
- if (term) {
- term = term.trim();
- if (term === '') {
- opts.highlightTerms[count] = null;
- } else {
- opts.highlightTerms[count] = term.toLowerCase();
- }
- } else {
- opts.highlightTerms[count] = null;
- }
- count++;
- }
-
- var color = $('#highlightColor').val();
- color = color.trim();
- if (color == '' || color.charAt(0) != '#') {
- opts.highlightColor = '#FFFF00';
- } else {
- opts.highlightColor = color;
- }
- var $popup = $('#highlightPopup').closest('.popup');
- $popup.remove();
-
- setCookie('highlightterms', JSON.stringify(opts.highlightTerms), 365);
- setCookie('highlightcolor', opts.highlightColor, 365);
- });
-
- $('#clearMessages').click(function() {
- $messages.empty();
- opts.messageCount = 0;
- });
-
-
- /*****************************************
- *
- * KICK EVERYTHING OFF
- *
- ******************************************/
-
- runByond('?_src_=chat&proc=doneLoading');
- if ($('#loading').is(':visible')) {
- $('#loading').remove();
- }
- $('#userBar').show();
- opts.priorChatHeight = $(window).height();
-});
\ No newline at end of file
diff --git a/goon/browserassets/js/json2.min.js b/goon/browserassets/js/json2.min.js
deleted file mode 100644
index d867407f26..0000000000
--- a/goon/browserassets/js/json2.min.js
+++ /dev/null
@@ -1 +0,0 @@
-"object"!=typeof JSON&&(JSON={}),function(){"use strict";function f(t){return 10>t?"0"+t:t}function this_value(){return this.valueOf()}function quote(t){return rx_escapable.lastIndex=0,rx_escapable.test(t)?'"'+t.replace(rx_escapable,function(t){var e=meta[t];return"string"==typeof e?e:"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+t+'"'}function str(t,e){var r,n,o,u,f,a=gap,i=e[t];switch(i&&"object"==typeof i&&"function"==typeof i.toJSON&&(i=i.toJSON(t)),"function"==typeof rep&&(i=rep.call(e,t,i)),typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";if(gap+=indent,f=[],"[object Array]"===Object.prototype.toString.apply(i)){for(u=i.length,r=0;u>r;r+=1)f[r]=str(r,i)||"null";return o=0===f.length?"[]":gap?"[\n"+gap+f.join(",\n"+gap)+"\n"+a+"]":"["+f.join(",")+"]",gap=a,o}if(rep&&"object"==typeof rep)for(u=rep.length,r=0;u>r;r+=1)"string"==typeof rep[r]&&(n=rep[r],o=str(n,i),o&&f.push(quote(n)+(gap?": ":":")+o));else for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(o=str(n,i),o&&f.push(quote(n)+(gap?": ":":")+o));return o=0===f.length?"{}":gap?"{\n"+gap+f.join(",\n"+gap)+"\n"+a+"}":"{"+f.join(",")+"}",gap=a,o}}var rx_one=/^[\],:{}\s]*$/,rx_two=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,rx_three=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,rx_four=/(?:^|:|,)(?:\s*\[)+/g,rx_escapable=/[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,rx_dangerous=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},Boolean.prototype.toJSON=this_value,Number.prototype.toJSON=this_value,String.prototype.toJSON=this_value);var gap,indent,meta,rep;"function"!=typeof JSON.stringify&&(meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},JSON.stringify=function(t,e,r){var n;if(gap="",indent="","number"==typeof r)for(n=0;r>n;n+=1)indent+=" ";else"string"==typeof r&&(indent=r);if(rep=e,e&&"function"!=typeof e&&("object"!=typeof e||"number"!=typeof e.length))throw new Error("JSON.stringify");return str("",{"":t})}),"function"!=typeof JSON.parse&&(JSON.parse=function(text,reviver){function walk(t,e){var r,n,o=t[e];if(o&&"object"==typeof o)for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(n=walk(o,r),void 0!==n?o[r]=n:delete o[r]);return reviver.call(t,e,o)}var j;if(text=String(text),rx_dangerous.lastIndex=0,rx_dangerous.test(text)&&(text=text.replace(rx_dangerous,function(t){return"\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)})),rx_one.test(text.replace(rx_two,"@").replace(rx_three,"]").replace(rx_four,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}();
\ No newline at end of file
diff --git a/goon/code/datums/browserOutput.dm b/goon/code/datums/browserOutput.dm
deleted file mode 100644
index d928397728..0000000000
--- a/goon/code/datums/browserOutput.dm
+++ /dev/null
@@ -1,289 +0,0 @@
-/*********************************
-For the main html chat area
-*********************************/
-
-//Precaching a bunch of shit
-GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of icons for the browser output
-
-//On client, created on login
-/datum/chatOutput
- var/client/owner //client ref
- var/loaded = FALSE // Has the client loaded the browser output area?
- var/list/messageQueue //If they haven't loaded chat, this is where messages will go until they do
- var/cookieSent = FALSE // Has the client sent a cookie for analysis
- var/list/connectionHistory //Contains the connection history passed from chat cookie
- var/broken = FALSE
-
-/datum/chatOutput/New(client/C)
- owner = C
- messageQueue = list()
- connectionHistory = list()
- // log_world("chatOutput: New()")
-
-/datum/chatOutput/proc/start()
- //Check for existing chat
- if(!owner)
- return FALSE
-
- if(!winexists(owner, "browseroutput")) // Oh goddamnit.
- alert(owner.mob, "Updated chat window does not exist. If you are using a custom skin file please allow the game to update.")
- broken = TRUE
- return FALSE
-
- if(winget(owner, "browseroutput", "is-disabled") == "false") //Already setup
- doneLoading()
-
- else //Not setup
- load()
-
- return TRUE
-
-/datum/chatOutput/proc/load()
- set waitfor = FALSE
- if(!owner)
- return
-
- var/static/list/chatResources = list(
- "code/modules/html_interface/js/jquery.min.js",
- "goon/browserassets/js/json2.min.js",
- "goon/browserassets/js/browserOutput.js",
- "tgui/assets/fonts/fontawesome-webfont.eot",
- "tgui/assets/fonts/fontawesome-webfont.svg",
- "tgui/assets/fonts/fontawesome-webfont.ttf",
- "tgui/assets/fonts/fontawesome-webfont.woff",
- "goon/browserassets/css/font-awesome.css",
- "goon/browserassets/css/browserOutput.css"
- )
-
- // to_chat(world.log, "chatOutput: load()")
- for(var/attempts in 1 to 5)
- for(var/asset in chatResources)
- owner << browse_rsc(file(asset))
-
- //log_world("Sending main chat window to client [owner.ckey]")
- owner << browse(file("goon/browserassets/html/browserOutput.html"), "window=browseroutput")
- sleep(14 + (chatResources.len * 7))
- if(!owner || loaded)
- break
-
- if(owner && !loaded)
- doneLoading() // try doing this manually
- CRASH("[owner] failed to load chat. Attempting doneLoading() manually")
- // log_world("chatOutput: [owner.ckey] load() completed")
-
-/datum/chatOutput/Topic(href, list/href_list)
- if(usr.client != owner)
- return TRUE
-
- // Build arguments.
- // Arguments are in the form "param[paramname]=thing"
- var/list/params = list()
- for(var/key in href_list)
- if(length(key) > 7 && findtext(key, "param")) // 7 is the amount of characters in the basic param key template.
- var/param_name = copytext(key, 7, -1)
- var/item = href_list[key]
-
- params[param_name] = item
-
- var/data // Data to be sent back to the chat.
- switch(href_list["proc"])
- if("doneLoading")
- data = doneLoading(arglist(params))
-
- if("debug")
- data = debug(arglist(params))
-
- if("ping")
- data = ping(arglist(params))
-
- if("analyzeClientData")
- data = analyzeClientData(arglist(params))
-
- if(data)
- ehjax_send(data = data)
-
-//Called on chat output done-loading by JS.
-/datum/chatOutput/proc/doneLoading()
- if(loaded)
- return
-
- loaded = TRUE
- winset(owner, "browseroutput", "is-disabled=false")
- for(var/message in messageQueue)
- to_chat(owner, message)
-
- messageQueue = null
- sendClientData()
-
- pingLoop()
-
-/datum/chatOutput/proc/pingLoop()
- set waitfor = FALSE
-
- while (owner)
- ehjax_send(data = owner.is_afk(29) ? "softPang" : "pang") // SoftPang isn't handled anywhere but it'll always reset the opts.lastPang.
- sleep(30)
-
-/datum/chatOutput/proc/ehjax_send(client/C = owner, window = "browseroutput", data)
- if(islist(data))
- data = json_encode(data)
- C << output("[data]", "[window]:ehjaxCallback")
-
-//Sends client connection details to the chat to handle and save
-/datum/chatOutput/proc/sendClientData()
- //Get dem deets
- var/list/deets = list("clientData" = list())
- deets["clientData"]["ckey"] = owner.ckey
- deets["clientData"]["ip"] = owner.address
- deets["clientData"]["compid"] = owner.computer_id
- var/data = json_encode(deets)
- ehjax_send(data = data)
-
-//Called by client, sent data to investigate (cookie history so far)
-/datum/chatOutput/proc/analyzeClientData(cookie = "")
- if(!cookie)
- return
-
- if(cookie != "none")
- var/list/connData = json_decode(cookie)
- if (connData && islist(connData) && connData.len > 0 && connData["connData"])
- connectionHistory = connData["connData"] //lol fuck
- var/list/found = new()
- for(var/i in connectionHistory.len to 1 step -1)
- var/list/row = src.connectionHistory[i]
- if (!row || row.len < 3 || (!row["ckey"] && !row["compid"] && !row["ip"])) //Passed malformed history object
- return
- if (world.IsBanned(row["ckey"], row["compid"], row["ip"]))
- found = row
- break
-
- //Uh oh this fucker has a history of playing on a banned account!!
- if (found.len > 0)
- //TODO: add a new evasion ban for the CURRENT client details, using the matched row details
- message_admins("[key_name(src.owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])")
- log_admin("[key_name(src.owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])")
-
- cookieSent = TRUE
-
-//Called by js client every 60 seconds
-/datum/chatOutput/proc/ping()
- return "pong"
-
-//Called by js client on js error
-/datum/chatOutput/proc/debug(error)
- log_world("\[[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]\] Client: [(src.owner.key ? src.owner.key : src.owner)] triggered JS error: [error]")
-
-#ifdef TESTING
-/client/verb/debug_chat()
- set hidden = TRUE
- chatOutput.ehjax_send(data = list("firebug" = TRUE))
-#endif
-//Global chat procs
-
-GLOBAL_LIST_EMPTY(bicon_cache)
-
-//Converts an icon to base64. Operates by putting the icon in the iconCache savefile,
-// exporting it as text, and then parsing the base64 from that.
-// (This relies on byond automatically storing icons in savefiles as base64)
-/proc/icon2base64(icon/icon, iconKey = "misc")
- if (!isicon(icon))
- return FALSE
- GLOB.iconCache[iconKey] << icon
- var/iconData = GLOB.iconCache.ExportText(iconKey)
- var/list/partial = splittext(iconData, "{")
- return replacetext(copytext(partial[2], 3, -5), "\n", "")
-
-/proc/bicon(obj)
- if (!obj)
- return
-
- if (isicon(obj))
- //Icons get pooled constantly, references are no good here.
- /*if (!bicon_cache["\ref[obj]"]) // Doesn't exist yet, make it.
- bicon_cache["\ref[obj]"] = icon2base64(obj)
- return ""*/
- return ""
-
- // Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with.
- var/atom/A = obj
- var/key = "[istype(A.icon, /icon) ? "\ref[A.icon]" : A.icon]:[A.icon_state]"
- if (!GLOB.bicon_cache[key]) // Doesn't exist, make it.
- var/icon/I = icon(A.icon, A.icon_state, SOUTH, 1)
- if (ishuman(obj)) // Shitty workaround for a BYOND issue.
- var/icon/temp = I
- I = icon()
- I.Insert(temp, dir = SOUTH)
- GLOB.bicon_cache[key] = icon2base64(I, key)
-
- return ""
-
-//Costlier version of bicon() that uses getFlatIcon() to account for overlays, underlays, etc. Use with extreme moderation, ESPECIALLY on mobs.
-/proc/costly_bicon(obj)
- if (!obj)
- return
-
- if (isicon(obj))
- return bicon(obj)
-
- var/icon/I = getFlatIcon(obj)
- return bicon(I)
-
-/proc/to_chat(target, message)
- if(isnull(target))
- return
- //Ok so I did my best but I accept that some calls to this will be for shit like sound and images
- //It stands that we PROBABLY don't want to output those to the browser output so just handle them here
- if (istype(message, /image) || istype(message, /sound) || istype(target, /savefile) || !(ismob(target) || islist(target) || istype(target, /client) || istype(target, /datum/log) || target == world))
- target << message
- if (!istype(target, /atom)) // Really easy to mix these up, and not having to make sure things are mobs makes the code cleaner.
- CRASH("DEBUG: Boutput called with invalid message")
- return
-
- //Otherwise, we're good to throw it at the user
- else if (istext(message))
- if (istext(target))
- return
-
- //Some macros remain in the string even after parsing and fuck up the eventual output
- if (findtext(message, "\improper"))
- message = replacetext(message, "\improper", "")
- if (findtext(message, "\proper"))
- message = replacetext(message, "\proper", "")
-
- //Grab us a client if possible
- var/client/C = grab_client(target)
-
- if (C && C.chatOutput)
- if(C.chatOutput.broken) // A player who hasn't updated his skin file.
- to_chat(C, message)
- return TRUE
- if(!C.chatOutput.loaded && C.chatOutput.messageQueue && islist(C.chatOutput.messageQueue))
- //Client sucks at loading things, put their messages in a queue
- C.chatOutput.messageQueue.Add(message)
- return
-
- if(istype(target, /datum/log))
- var/datum/log/L = target
- L.log += (message + "\n")
- return
-
- message = replacetext(message, "\n", " ")
- message = replacetext(message, "\t", " ")
-
- // url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript.
- target << output(url_encode(url_encode(message)), "browseroutput:output")
-
-/proc/grab_client(target)
- if(istype(target, /client))
- return target
- else if(istype(target, /mob))
- var/mob/M = target
- if(M.client)
- return M.client
- else if(istype(target, /datum/mind))
- var/datum/mind/M = target
- if(M.current && M.current.client)
- return M.current.client
-
-/datum/log //exists purely to capture to_chat() output
- var/log = ""
\ No newline at end of file
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-8602.yml b/html/changelogs/AutoChangeLog-pr-8602.yml
new file mode 100644
index 0000000000..4974c1ae79
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8602.yml
@@ -0,0 +1,5 @@
+author: "Poojawa"
+delete-after: True
+changes:
+ - rscadd: "Added an underwear toggle button under 'Object' tab"
+ - tweak: "Genitals now layer under underwear. Hide these if they're too obnoxious."
diff --git a/html/changelogs/AutoChangeLog-pr-8658.yml b/html/changelogs/AutoChangeLog-pr-8658.yml
new file mode 100644
index 0000000000..ad35118c3f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8658.yml
@@ -0,0 +1,5 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - tweak: "Moving some tablecrafting recipes to the appropriate categories: Kitty ears and lizard cloche hats to \"clothing\"; Hot dogs to \"Sandwichs\"; Cuban carb, fish and chips and fish fingers to \"Fish\"."
+ - bugfix: "Fixes the not-a-sandwich recipe being M.I.A."
diff --git a/html/changelogs/AutoChangeLog-pr-8659.yml b/html/changelogs/AutoChangeLog-pr-8659.yml
new file mode 100644
index 0000000000..6287f1307f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8659.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by ninjanomnom)"
+delete-after: True
+changes:
+ - bugfix: "Orbiting is a little more aggressive about staying in orbit. The wisp as a result now correctly follows you over shuttle moves."
diff --git a/html/changelogs/AutoChangeLog-pr-8665.yml b/html/changelogs/AutoChangeLog-pr-8665.yml
new file mode 100644
index 0000000000..fc34f9ac3e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8665.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - balance: "Buffed wizard and artificier's Magic Missile, wizard and xeno queen's Repulse and juggernaut's Gauntlet Echo."
diff --git a/html/changelogs/AutoChangeLog-pr-8666.yml b/html/changelogs/AutoChangeLog-pr-8666.yml
new file mode 100644
index 0000000000..df2e2e3af0
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8666.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by YPOQ)"
+delete-after: True
+changes:
+ - bugfix: "Fixing roffle waffle, mushroom halluginogen and some invalid reagents."
diff --git a/html/changelogs/AutoChangeLog-pr-8667.yml b/html/changelogs/AutoChangeLog-pr-8667.yml
new file mode 100644
index 0000000000..1f80a2917d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8667.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by Anturk)"
+delete-after: True
+changes:
+ - rscadd: "Recipe for fabled secret sauce can now be found in the deepest reaches of space."
diff --git a/html/changelogs/AutoChangeLog-pr-8669.yml b/html/changelogs/AutoChangeLog-pr-8669.yml
new file mode 100644
index 0000000000..20770e8cc2
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8669.yml
@@ -0,0 +1,5 @@
+author: "Ghommie (original PRs by Denton and Skoglol)"
+delete-after: True
+changes:
+ - tweak: "Reorganized the syndicate uplinks. Items are now mostly alphabetical, some misplaced items moved to more fitting categories. Bundles, random item and TC have been moved into a new category called \"Bundles and Telecrystals\". Gloves of the North Star and Box of Throwing Weapons have been moved to Conspicuous and Dangerous Weapons. Combat Gloves Plus have been moved to Stealthy and Inconspicuous Weapons. Moved all implants into the Implants category."
+ - tweak: "Added a new category to the uplink: Grenades and Explosives."
diff --git a/html/changelogs/AutoChangeLog-pr-8671.yml b/html/changelogs/AutoChangeLog-pr-8671.yml
new file mode 100644
index 0000000000..bb01481d5c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8671.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by wesoda25)"
+delete-after: True
+changes:
+ - balance: "disembowelment no longer works on mobs that aren't dead or in critical condition"
diff --git a/html/changelogs/AutoChangeLog-pr-8674.yml b/html/changelogs/AutoChangeLog-pr-8674.yml
new file mode 100644
index 0000000000..3277946844
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8674.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - bugfix: "fixing cat code that dosnt work, my bad"
diff --git a/html/changelogs/AutoChangeLog-pr-8675.yml b/html/changelogs/AutoChangeLog-pr-8675.yml
new file mode 100644
index 0000000000..170a44ca25
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8675.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - bugfix: "Arcades stealing from noodles"
diff --git a/html/changelogs/AutoChangeLog-pr-8677.yml b/html/changelogs/AutoChangeLog-pr-8677.yml
new file mode 100644
index 0000000000..181f6d2932
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8677.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - tweak: "speedy quirk"
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-8687.yml b/html/changelogs/AutoChangeLog-pr-8687.yml
new file mode 100644
index 0000000000..65347093ef
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8687.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by monster860)"
+delete-after: True
+changes:
+ - bugfix: "fixes advanced proccall"
diff --git a/html/changelogs/AutoChangeLog-pr-8688.yml b/html/changelogs/AutoChangeLog-pr-8688.yml
new file mode 100644
index 0000000000..b22c2c52fd
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8688.yml
@@ -0,0 +1,5 @@
+author: "Ghommie (Original PR by nemvar)"
+delete-after: True
+changes:
+ - rscadd: "Botanists can now get beeplushies (or cultivator and bucket) as an heirloom."
+ - bugfix: "Clowns and mimes will now properly pick either a can of paint or their brand as heirloom now."
diff --git a/html/changelogs/AutoChangeLog-pr-8689.yml b/html/changelogs/AutoChangeLog-pr-8689.yml
new file mode 100644
index 0000000000..bf44770c76
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8689.yml
@@ -0,0 +1,4 @@
+author: "Fermis"
+delete-after: True
+changes:
+ - rscadd: "Added a panda simplemob"
diff --git a/html/changelogs/AutoChangeLog-pr-8690.yml b/html/changelogs/AutoChangeLog-pr-8690.yml
new file mode 100644
index 0000000000..3ac76333a2
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8690.yml
@@ -0,0 +1,4 @@
+author: "Fermis"
+delete-after: True
+changes:
+ - bugfix: "fixes empathy exploit."
diff --git a/html/changelogs/AutoChangeLog-pr-8691.yml b/html/changelogs/AutoChangeLog-pr-8691.yml
new file mode 100644
index 0000000000..680904cc5c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8691.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (Original PRs by nemvar and Rowell)"
+delete-after: True
+changes:
+ - rscadd: "Added beekini bras and panties, thigh-high and knee-high bee socks."
diff --git a/html/changelogs/AutoChangeLog-pr-8692.yml b/html/changelogs/AutoChangeLog-pr-8692.yml
new file mode 100644
index 0000000000..f1d87676ab
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8692.yml
@@ -0,0 +1,7 @@
+author: "Ghommie (original PRs by ShizCalev)"
+delete-after: True
+changes:
+ - bugfix: "Fixed a bug that allowed you to teleport an ID in your possession to a PDA anywhere ingame."
+ - bugfix: "Fixed an exploit allowing you to steal ID's/pens from PDA's not in your possession."
+ - bugfix: "Fixed an exploit allowing you unlimited control of a PDA's interface even if it wasn't near you/in your possession."
+ - bugfix: "Fixed Pride Mirror exploits."
diff --git a/html/changelogs/AutoChangeLog-pr-8695.yml b/html/changelogs/AutoChangeLog-pr-8695.yml
new file mode 100644
index 0000000000..671eaa519e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8695.yml
@@ -0,0 +1,6 @@
+author: "Ghommie (original PRs by grandpawalton and Mickyan)"
+delete-after: True
+changes:
+ - tweak: "the contents on the smartfridge icon now change depending on how many items it contains"
+ - bugfix: "opening the maintenance panel of smartfridges now correctly updates the icon"
+ - bugfix: "Screwing a disk compartmentalizer no longer makes it look like a smartfridge."
diff --git a/html/changelogs/AutoChangeLog-pr-8698.yml b/html/changelogs/AutoChangeLog-pr-8698.yml
new file mode 100644
index 0000000000..464f74427e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8698.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixes flashlights being unable to be used for rudimentary eyes and mouth exams."
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-8711.yml b/html/changelogs/AutoChangeLog-pr-8711.yml
new file mode 100644
index 0000000000..f836783659
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8711.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - rscadd: "Adds in a grey jumpsuit to the loadout choices, restricted to Assistants."
diff --git a/html/changelogs/AutoChangeLog-pr-8715.yml b/html/changelogs/AutoChangeLog-pr-8715.yml
new file mode 100644
index 0000000000..b99309cdd9
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8715.yml
@@ -0,0 +1,5 @@
+author: "Sishen1542"
+delete-after: True
+changes:
+ - rscadd: "Pentetic Jelly, new chemical made through mixing 1:1 slime jelly and pentetic acid."
+ - tweak: "Anatomic panacea now gives pent jelly instead of pent acid. Medbeams now have TRUE tox healing to heal TOXINLOVER as well."
diff --git a/html/changelogs/AutoChangeLog-pr-8718.yml b/html/changelogs/AutoChangeLog-pr-8718.yml
new file mode 100644
index 0000000000..102fbd4f23
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8718.yml
@@ -0,0 +1,4 @@
+author: "Linzolle"
+delete-after: True
+changes:
+ - rscadd: "ability to quickly max sensors"
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-8721.yml b/html/changelogs/AutoChangeLog-pr-8721.yml
new file mode 100644
index 0000000000..4b616e9923
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8721.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by XDTM)"
+delete-after: True
+changes:
+ - bugfix: "Reagents now stop their passive effects (for example, stun immunity) if the liver stops working while they're active."
diff --git a/html/changelogs/AutoChangeLog-pr-8722.yml b/html/changelogs/AutoChangeLog-pr-8722.yml
new file mode 100644
index 0000000000..fe858768af
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8722.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - bugfix: "I didn't code it right it in the first place"
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-8732.yml b/html/changelogs/AutoChangeLog-pr-8732.yml
new file mode 100644
index 0000000000..69a79b93ac
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8732.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by Nicjh)"
+delete-after: True
+changes:
+ - rscadd: "Abductor console's select disguise option now uses a radial"
diff --git a/html/changelogs/AutoChangeLog-pr-8733.yml b/html/changelogs/AutoChangeLog-pr-8733.yml
new file mode 100644
index 0000000000..593c06bd90
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8733.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by Swindly)"
+delete-after: True
+changes:
+ - rscadd: "Arm-mounted implants that contain more than one item use a radial menu instead of a list menu."
diff --git a/html/changelogs/AutoChangeLog-pr-8736.yml b/html/changelogs/AutoChangeLog-pr-8736.yml
new file mode 100644
index 0000000000..68d64e2410
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8736.yml
@@ -0,0 +1,6 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - rscadd: "gear harness and a conflict merg"
+ - rscdel: "Nudity permits"
+ - bugfix: "nothing"
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-8742.yml b/html/changelogs/AutoChangeLog-pr-8742.yml
new file mode 100644
index 0000000000..03428fc8d1
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8742.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - rscadd: "Donner item"
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-8747.yml b/html/changelogs/AutoChangeLog-pr-8747.yml
new file mode 100644
index 0000000000..c8a4689c60
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8747.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - rscadd: "Luna's Gauntlets"
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/html/changelogs/AutoChangeLog-pr-8779.yml b/html/changelogs/AutoChangeLog-pr-8779.yml
new file mode 100644
index 0000000000..b5e90f7ecb
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8779.yml
@@ -0,0 +1,4 @@
+author: "Sishen1542"
+delete-after: True
+changes:
+ - balance: "Roundstart carbon jetpacks now have full_speed FALSE."
diff --git a/html/changelogs/AutoChangeLog-pr-8784.yml b/html/changelogs/AutoChangeLog-pr-8784.yml
new file mode 100644
index 0000000000..7d6d9d4739
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8784.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - rscadd: "Donor item"
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/custom_w.dmi b/icons/mob/custom_w.dmi
index 22f5e85977..d974d0ca6c 100644
Binary files a/icons/mob/custom_w.dmi and b/icons/mob/custom_w.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/neck.dmi b/icons/mob/neck.dmi
index 3c126daba6..3463065bc7 100644
Binary files a/icons/mob/neck.dmi and b/icons/mob/neck.dmi differ
diff --git a/icons/mob/pets.dmi b/icons/mob/pets.dmi
index 45b0ab1f04..fe0146ccc4 100644
Binary files a/icons/mob/pets.dmi and b/icons/mob/pets.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 cf16eb9e32..5e6725cec7 100644
Binary files a/icons/mob/underwear.dmi and b/icons/mob/underwear.dmi differ
diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi
index 2ed1783941..3d281606de 100644
Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ
diff --git a/icons/obj/clothing/belts.dmi b/icons/obj/clothing/belts.dmi
index dc5dde9cb6..3e56574fbf 100644
Binary files a/icons/obj/clothing/belts.dmi and b/icons/obj/clothing/belts.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/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index 84155bfe43..3e3a1cefcb 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/obj/custom.dmi b/icons/obj/custom.dmi
index f9660c6b38..eb4f5813c8 100644
Binary files a/icons/obj/custom.dmi and b/icons/obj/custom.dmi differ
diff --git a/icons/obj/dart.dmi b/icons/obj/dart.dmi
new file mode 100644
index 0000000000..50ba4fc1ab
Binary files /dev/null and b/icons/obj/dart.dmi differ
diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi
index e4a39903b3..7d44d35f55 100644
Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.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/plushes.dmi b/icons/obj/plushes.dmi
index 8e845d9710..586bca61aa 100644
Binary files a/icons/obj/plushes.dmi and b/icons/obj/plushes.dmi differ
diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi
index d276655ae8..bff1b631c3 100644
Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.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/icons/obj/syringe.dmi b/icons/obj/syringe.dmi
index f77735fc3e..80e681399a 100644
Binary files a/icons/obj/syringe.dmi and b/icons/obj/syringe.dmi differ
diff --git a/icons/obj/vehicles.dmi b/icons/obj/vehicles.dmi
index 5e3757cedd..67079de3e2 100644
Binary files a/icons/obj/vehicles.dmi and b/icons/obj/vehicles.dmi differ
diff --git a/icons/obj/vending.dmi b/icons/obj/vending.dmi
index e5d474f01d..553336115b 100644
Binary files a/icons/obj/vending.dmi and b/icons/obj/vending.dmi differ
diff --git a/modular_citadel/code/datums/uplink_items_cit.dm b/modular_citadel/code/datums/uplink_items_cit.dm
deleted file mode 100644
index 16130de96d..0000000000
--- a/modular_citadel/code/datums/uplink_items_cit.dm
+++ /dev/null
@@ -1,177 +0,0 @@
-/*/datum/uplink_item/stealthy_tools/syndi_borer
- name = "Syndicate Brain Slug"
- desc = "A small cortical borer, modified to be completely loyal to the owner. \
- Genetically infertile, these brain slugs can assist medically in a support role, or take direct action \
- to assist their host."
- item = /obj/item/antag_spawner/syndi_borer
- refundable = TRUE
- cost = 10
- surplus = 20 //Let's not have this be too common
- exclude_modes = list(/datum/game_mode/nuclear) */
-
-/datum/uplink_item/stealthy_tools/holoparasite
- name="Holoparasite Injector"
- desc="An injector containing a swarm of holographic parasites. \
- They mimic the function of the guardians employed by the Space Wizard Federation, and their form can be selected upon application \
- NOTE: The precise nature of the symbiosis required by the parasites renders them incompatible with changelings" //updated to actually describe what they do and warn traitorchans not to buy it
- item = /obj/item/storage/box/syndie_kit/holoparasite
- refundable = TRUE
- cant_discount = TRUE
- cost = 15
- surplus = 20 //Nobody needs a ton of parasites
- exclude_modes = list(/datum/game_mode/nuclear)
- refund_path = /obj/item/guardiancreator/tech/choose/traitor
-
-
-/obj/item/storage/box/syndie_kit/holoparasite
- name = "box"
-
-/obj/item/storage/box/syndie_kit/holoparasite/PopulateContents()
- new /obj/item/guardiancreator/tech/choose/traitor(src)
- new /obj/item/paper/guides/antag/guardian(src)
-
-/datum/uplink_item/dangerous/antitank
- name = "Anti Tank Pistol"
- desc = "Essentially amounting to a sniper rifle with no stock and barrel (or indeed, any rifling at all), \
- this extremely dubious pistol is guaranteed to dislocate your wrists and hit the broad side of a barn! \
- Uses sniper ammo. \
- Bullets tend to veer off-course. We are not responsible for any unintentional damage or injury resulting from inaacuracy."
- item = /obj/item/gun/ballistic/automatic/pistol/antitank/syndicate
- cost = 14
- surplus = 25
- include_modes = list(/datum/game_mode/nuclear)
-
-/* Commented out due to introduction of reskinnable stetchkins. May still have a niche if people decide it somehow has value.
-/datum/uplink_item/dangerous/stealthpistol
- name = "Stealth Pistol"
- desc = "A compact, easily concealable bullpup pistol that fires 10mm auto rounds in 8 round magazines. \
- Has an integrated suppressor."
- item = /obj/item/gun/ballistic/automatic/pistol/stealth
- cost = 10
- surplus = 30
-*/
-
-///Soporific 10mm mags///
-
-/datum/uplink_item/ammo/pistolzzz
- name = "10mm Soporific Magazine"
- desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. Loaded with soporific rounds that put the target to sleep. \
- NOTE: Soporific is not instant acting due to the constraints of the round's scale. Will usually require three shots to take effect."
- item = /obj/item/ammo_box/magazine/m10mm/soporific
- cost = 2
-
-///flechette memes///
-
-/datum/uplink_item/dangerous/flechettegun
- name = "Flechette Launcher"
- desc = "A compact bullpup that fires micro-flechettes.\
- Flechettes have very poor performance idividually, but can be very deadly in numbers. \
- Pre-loaded with armor piercing flechettes that are capable of puncturing most kinds of armor."
- item = /obj/item/gun/ballistic/automatic/flechette
- cost = 12
- surplus = 30
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/ammo/flechetteap
- name = "Armor Piercing Flechette Magazine"
- desc = "An additional 40-round flechette magazine; compatible with the Flechette Launcer. \
- Loaded with armor piercing flechettes that very nearly ignore armor, but are not very effective agaisnt flesh."
- item = /obj/item/ammo_box/magazine/flechette
- cost = 2
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/ammo/flechettes
- name = "Serrated Flechette Magazine"
- desc = "An additional 40-round flechette magazine; compatible with the Flechette Launcer. \
- Loaded with serrated flechettes that shreds flesh, but is stopped dead in its tracks by armor. \
- These flechettes are highly likely to sever arteries, and even limbs."
- item = /obj/item/ammo_box/magazine/flechette/s
- cost = 2
- include_modes = list(/datum/game_mode/nuclear)
-
-///shredder///
-
-/datum/uplink_item/nukeoffer/shredder
- name = "Shredder bundle"
- desc = "A truly horrific weapon designed simply to maim its victim, the CX Shredder is banned by several intergalactic treaties. \
- You'll get two of them with this. And spare ammo to boot. And we'll throw in an extra elite hardsuit and chest rig to hold them all!"
- item = /obj/item/storage/backpack/duffelbag/syndie/shredderbundle
- cost = 30 // normally 41
-
-///Modular Pistols///
-
-/datum/uplink_item/bundle/modular
- name="Modular Pistol Kit"
- desc="A heavy briefcase containing one modular pistol (chambered in 10mm), one supressor, and spare ammunition, including a box of soporific ammo. \
- Includes a suit jacket that is padded with a robust liner."
- item = /obj/item/storage/briefcase/modularbundle
- cost = 12
-
-//////Bundle stuff//////
-
-///bundle category///
-
-/datum/uplink_item/bundle
- category = "Bundles"
- surplus = 0
- cant_discount = TRUE
-
-///place bundle storage items here I guess///
-
-/obj/item/storage/briefcase/modularbundle
- name = "briefcase"
- desc = "It's label reads genuine hardened Captain leather, but suspiciously has no other tags or branding."
- icon_state = "briefcase"
- flags_1 = CONDUCT_1
- force = 10
- hitsound = "swing_hit"
- throw_speed = 2
- throw_range = 4
- w_class = WEIGHT_CLASS_BULKY
- attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked")
- resistance_flags = FLAMMABLE
- max_integrity = 150
-
-/obj/item/storage/briefcase/modularbundle/PopulateContents()
- new /obj/item/gun/ballistic/automatic/pistol/modular(src)
- new /obj/item/suppressor(src)
- new /obj/item/ammo_box/magazine/m10mm(src)
- new /obj/item/ammo_box/magazine/m10mm/soporific(src)
- new /obj/item/ammo_box/c10mm/soporific(src)
- new /obj/item/clothing/under/lawyer/blacksuit(src)
- new /obj/item/clothing/accessory/waistcoat(src)
- new /obj/item/clothing/suit/toggle/lawyer/black/syndie(src)
-
-/obj/item/clothing/suit/toggle/lawyer/black/syndie
- desc = "A snappy dress jacket. Suspiciously has no tags or branding."
- armor = list(melee = 10, bullet = 10, laser = 10, energy = 10, bomb = 10)
-
-/obj/item/storage/backpack/duffelbag/syndie/shredderbundle
- desc = "A large duffel bag containing two CX Shredders, some magazines, an elite hardsuit, and a chest rig."
-
-/obj/item/storage/backpack/duffelbag/syndie/shredderbundle/PopulateContents()
- new /obj/item/ammo_box/magazine/flechette/shredder(src)
- new /obj/item/ammo_box/magazine/flechette/shredder(src)
- new /obj/item/ammo_box/magazine/flechette/shredder(src)
- new /obj/item/ammo_box/magazine/flechette/shredder(src)
- new /obj/item/gun/ballistic/automatic/flechette/shredder(src)
- new /obj/item/gun/ballistic/automatic/flechette/shredder(src)
- new /obj/item/storage/belt/military(src)
- new /obj/item/clothing/suit/space/hardsuit/syndi/elite(src)
-
-///End of Bundle stuff///
-
-
-/*/////////////////////////////////////////////////////////////////////////
-///////////// The TRUE Energy Sword ///////////////////////////
-*//////////////////////////////////////////////////////////////////////////
-
-/datum/uplink_item/dangerous/cxneb
- name = "Dragon's Tooth Non-Eutactic Blade"
- desc = "An illegal modification of a weapon that is functionally identical to the energy sword, \
- the Non-Eutactic Blade (NEB) forges a hardlight blade on-demand, \
- generating an extremely sharp, unbreakable edge that is guaranteed to satisfy your every need. \
- This particular model has a polychromic hardlight generator, allowing you to murder in style! \
- The illegal modifications bring this weapon up to par with the classic energy sword, and also gives it the energy sword's distinctive sounds."
- item = /obj/item/melee/transforming/energy/sword/cx/traitor
- cost = 8
\ No newline at end of file
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/devices/flashlight.dm b/modular_citadel/code/game/objects/items/devices/flashlight.dm
deleted file mode 100644
index 3a373c9277..0000000000
--- a/modular_citadel/code/game/objects/items/devices/flashlight.dm
+++ /dev/null
@@ -1,31 +0,0 @@
-/obj/item/flashlight
- light_color = "#FFCC66"
- flashlight_power = 0.8
-
-/obj/item/flashlight/pen
- light_color = "#FFDDCC"
- flashlight_power = 0.3
-
-/obj/item/flashlight/seclite
- light_color = "#CDDDFF"
- flashlight_power = 0.9
-
-/obj/item/flashlight/lamp
- light_color = "#FFDDBB"
- flashlight_power = 0.8
-
-/obj/item/flashlight/flare
- light_color = "#FA421A"
- flashlight_power = 0.8
-
-/obj/item/flashlight/flare/torch
- light_color = "#FAA44B"
- flashlight_power = 0.8
-
-/obj/item/flashlight/lantern
- light_color = "#FFAA44"
- flashlight_power = 0.75
-
-/obj/item/flashlight/slime
- light_color = "#FFEEAA"
- flashlight_power = 0.6
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/arousal.dm b/modular_citadel/code/modules/arousal/arousal.dm
index 846a8cff62..27f7576e7f 100644
--- a/modular_citadel/code/modules/arousal/arousal.dm
+++ b/modular_citadel/code/modules/arousal/arousal.dm
@@ -14,6 +14,10 @@
var/saved_underwear = ""//saves their underwear so it can be toggled later
var/saved_undershirt = ""
+ var/saved_socks = ""
+ var/hidden_underwear = FALSE
+ var/hidden_undershirt = FALSE
+ var/hidden_socks = FALSE
/mob/living/carbon/human/New()
..()
@@ -29,6 +33,33 @@
var/list/femcum_fluids = list("femcum")
//Mob procs
+/mob/living/carbon/human/proc/underwear_toggle()
+ set name = "Toggle undergarments"
+ set category = "Object"
+ if(ishuman(src))
+ var/mob/living/carbon/human/humz = src
+ var/confirm = input(src, "Select what part of your form to alter", "Undergarment Toggling", "Cancel") in list("Top", "Bottom", "Socks", "All", "Cancel")
+ if(confirm == "Top")
+ humz.hidden_undershirt = !humz.hidden_undershirt
+
+ if(confirm == "Bottom")
+ humz.hidden_underwear = !humz.hidden_underwear
+
+ if(confirm == "Socks")
+ humz.hidden_socks = !humz.hidden_socks
+
+ if(confirm == "All")
+ humz.hidden_undershirt = !humz.hidden_undershirt
+ humz.hidden_underwear = !humz.hidden_underwear
+ humz.hidden_socks = !humz.hidden_socks
+
+ if(confirm == "Cancel")
+ return
+ src.update_body()
+
+ else
+ to_chat(src, "Humans only. How the fuck did you get this verb anyway.")
+
/mob/living/proc/handle_arousal()
diff --git a/modular_citadel/code/modules/arousal/organs/genitals.dm b/modular_citadel/code/modules/arousal/organs/genitals.dm
index 52508d7803..63d6834409 100644
--- a/modular_citadel/code/modules/arousal/organs/genitals.dm
+++ b/modular_citadel/code/modules/arousal/organs/genitals.dm
@@ -73,7 +73,7 @@
owner.exposed_genitals += src
if("Hidden by clothes")
through_clothes = FALSE
- hidden = FALSE
+ hidden = TRUE
if(src in owner.exposed_genitals)
owner.exposed_genitals -= src
if("Always hidden")
@@ -303,6 +303,8 @@
for(var/obj/item/organ/O in H.internal_organs)
if(isgenital(O))
var/obj/item/organ/genital/G = O
+ if(G.hidden)
+ return //we're gunna just hijack this for updates.
if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes
genitals_to_add += H.getorganslot(G.slot)
//Now we added all genitals that aren't internal and should be rendered
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/cargo/console.dm b/modular_citadel/code/modules/cargo/console.dm
index 35a1a0e52f..f54a6c577a 100644
--- a/modular_citadel/code/modules/cargo/console.dm
+++ b/modular_citadel/code/modules/cargo/console.dm
@@ -4,11 +4,6 @@
/obj/machinery/computer/cargo/request
req_access = list()
-/obj/machinery/computer/cargo/emag_act(mob/user)
- . = ..()
- if(.)
- req_access = list()
-
/obj/machinery/computer/cargo/ui_act(action, params, datum/tgui/ui)
if(!allowed(usr))
to_chat(usr, "Access denied.")
diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm
index d8168d01a6..ab03e83b44 100644
--- a/modular_citadel/code/modules/client/loadout/__donator.dm
+++ b/modular_citadel/code/modules/client/loadout/__donator.dm
@@ -404,3 +404,27 @@ datum/gear/darksabresheath
category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/commjacket
ckeywhitelist = list("sadisticbatter")
+
+/datum/gear/mw2_russian_para
+ name = "Russian Paratrooper Jumper"
+ category = SLOT_WEAR_SUIT
+ path = /obj/item/clothing/suit/mw2_russian_para
+ ckeywhitelist = list("investigator77")
+
+/datum/gear/longblackgloves
+ name = "Luna's Gauntlets"
+ category = SLOT_GLOVES
+ path = /obj/item/clothing/gloves/longblackgloves
+ ckeywhitelist = list("bigmanclancy")
+
+/datum/gear/trendy_fit
+ name = "Trendy Fit"
+ category = SLOT_W_UNIFORM
+ path = /obj/item/clothing/under/trendy_fit
+ ckeywhitelist = list("midgetdragon")
+
+/datum/gear/csheet
+ name = "NT Bedsheet"
+ category = SLOT_NECK
+ path = /obj/item/bedsheet/captain
+ ckeywhitelist = list("tikibomb")
\ No newline at end of file
diff --git a/modular_citadel/code/modules/client/loadout/_service.dm b/modular_citadel/code/modules/client/loadout/_service.dm
index 9b508bb93f..062e22f966 100644
--- a/modular_citadel/code/modules/client/loadout/_service.dm
+++ b/modular_citadel/code/modules/client/loadout/_service.dm
@@ -1,3 +1,9 @@
+/datum/gear/greytidestationwide
+ name = "Grey jumpsuit"
+ category = SLOT_W_UNIFORM
+ path = /obj/item/clothing/under/color/grey
+ restricted_roles = list("Assistant")
+
/datum/gear/plushvar
name = "Ratvar Plushie"
category = SLOT_IN_BACKPACK
diff --git a/modular_citadel/code/modules/client/loadout/uniform.dm b/modular_citadel/code/modules/client/loadout/uniform.dm
index 4172230dbf..abdf8e3a24 100644
--- a/modular_citadel/code/modules/client/loadout/uniform.dm
+++ b/modular_citadel/code/modules/client/loadout/uniform.dm
@@ -309,8 +309,8 @@
restricted_desc = "Engineering and Security"
restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster")
-//memes
-/datum/gear/nudepermit
- name = "Nudity Permit"
+//Memes
+/datum/gear/gear_harnesses
+ name = "Gear Harness"
category = SLOT_W_UNIFORM
- path = /obj/item/clothing/under/permit
\ No newline at end of file
+ path = /obj/item/clothing/under/gear_harness
\ No newline at end of file
diff --git a/modular_citadel/code/modules/custom_loadout/custom_items.dm b/modular_citadel/code/modules/custom_loadout/custom_items.dm
index 0338a4f48e..4fd628f9d3 100644
--- a/modular_citadel/code/modules/custom_loadout/custom_items.dm
+++ b/modular_citadel/code/modules/custom_loadout/custom_items.dm
@@ -417,7 +417,6 @@
icon_state = "flagcape"
item_state = "flagcape"
-
/obj/item/clothing/shoes/lucky
name = "Lucky Jackboots"
icon = 'icons/obj/custom.dmi'
@@ -504,4 +503,28 @@
alternate_worn_icon = 'icons/mob/custom_w.dmi'
mutantrace_variation = NO_MUTANTRACE_VARIATION
+/obj/item/clothing/suit/mw2_russian_para
+ name = "Russian Paratrooper Jumper"
+ desc = "A Russian made old paratrooper jumpsuit, has many pockets for easy storage of gear from a by gone era. As bulky as it looks, its shockingly light!"
+ icon_state = "mw2_russian_para"
+ item_state = "mw2_russian_para"
+ icon = 'icons/obj/custom.dmi'
+ alternate_worn_icon = 'icons/mob/custom_w.dmi'
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
+/obj/item/clothing/gloves/longblackgloves
+ name = "Luna's Gauntlets"
+ desc = "These gloves seem to have a coating of slime fluid on them, you should possibly return them to their rightful owner."
+ icon_state = "longblackgloves"
+ item_state = "longblackgloves"
+ icon = 'icons/obj/custom.dmi'
+ alternate_worn_icon = 'icons/mob/custom_w.dmi'
+
+/obj/item/clothing/under/trendy_fit
+ name = "Trendy Fitting Clothing"
+ desc = "An outfit straight from the boredom of space, its the type of thing only someone trying to entertain themselves on the way to their next destination would wear."
+ icon_state = "trendy_fit"
+ item_state = "trendy_fit"
+ icon = 'icons/obj/custom.dmi'
+ alternate_worn_icon = 'icons/mob/custom_w.dmi'
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
\ No newline at end of file
diff --git a/modular_citadel/code/modules/mob/cit_emotes.dm b/modular_citadel/code/modules/mob/cit_emotes.dm
index a314baa852..aff1739ae4 100644
--- a/modular_citadel/code/modules/mob/cit_emotes.dm
+++ b/modular_citadel/code/modules/mob/cit_emotes.dm
@@ -183,6 +183,7 @@
key_third_person = "suddenly hits a dab"
message = "suddenly hits a dab!"
emote_type = EMOTE_AUDIBLE
+ restraint_check = TRUE
diff --git a/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm b/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm
index e552c2cbdd..bf811b777c 100644
--- a/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm
+++ b/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm
@@ -191,6 +191,32 @@
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
+/datum/sprite_accessory/ears/human/bigwolf
+ name = "Big Wolf"
+ icon_state = "bigwolf"
+ icon = 'modular_citadel/icons/mob/mam_ears.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/ears/human/bigwolfinner
+ name = "Big Wolf (ALT)"
+ icon_state = "bigwolfinner"
+ hasinner = 1
+ icon = 'modular_citadel/icons/mob/mam_ears.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/ears/human/bigwolfdark
+ name = "Dark Big Wolf"
+ icon_state = "bigwolfdark"
+ icon = 'modular_citadel/icons/mob/mam_ears.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/ears/human/bigwolfinnerdark
+ name = "Dark Big Wolf (ALT)"
+ icon_state = "bigwolfinnerdark"
+ hasinner = 1
+ icon = 'modular_citadel/icons/mob/mam_ears.dmi'
+ color_src = MATRIXED
+
/datum/sprite_accessory/ears/human/cow
name = "Cow"
icon_state = "cow"
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 0f71a71add..00063c22d4 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -17,13 +17,13 @@
M.adjustStaminaLoss(-5*REM)
. = ..()
-/datum/reagent/syndicateadrenals/on_mob_add(mob/living/M)
+/datum/reagent/syndicateadrenals/on_mob_metabolize(mob/living/M)
. = ..()
if(istype(M))
M.next_move_modifier *= 0.5
to_chat(M, "You feel an intense surge of energy rushing through your veins.")
-/datum/reagent/syndicateadrenals/on_mob_delete(mob/living/M)
+/datum/reagent/syndicateadrenals/on_mob_end_metabolize(mob/living/M)
. = ..()
if(istype(M))
M.next_move_modifier *= 2
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/code/modules/uplink/uplink_items.dm b/modular_citadel/code/modules/uplink/uplink_items.dm
deleted file mode 100644
index df076c3994..0000000000
--- a/modular_citadel/code/modules/uplink/uplink_items.dm
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-// PUT ALL YOUR NEW UPLINK STUFF HERE, OVERRIDES GO IN HERE TOO
-*/
-
-/datum/uplink_item/device_tools/emagrecharge
- name = "Electromagnet Charging Device"
- desc = "A small device intended for recharging Cryptographic Sequencers. Using it will add five extra charges to the Cryptographic Sequencer."
- item = /obj/item/emagrecharge
- cost = 2
-
-/datum/uplink_item/dangerous/revolver
- item = /obj/item/gun/ballistic/revolver/syndie
-
-/datum/uplink_item/dangerous/phantomthief
- name = "Syndicate Mask"
- desc = "A cheap plastic mask fitted with an adrenaline autoinjector, which can be used by simply tensing your muscles"
- item = /obj/item/clothing/glasses/phantomthief/syndicate
- cost = 2
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/genitals/breasts_onmob.dmi b/modular_citadel/icons/obj/genitals/breasts_onmob.dmi
index 69a531bd11..c4b75b1172 100644
Binary files a/modular_citadel/icons/obj/genitals/breasts_onmob.dmi and b/modular_citadel/icons/obj/genitals/breasts_onmob.dmi differ
diff --git a/modular_citadel/icons/obj/genitals/penis_onmob.dmi b/modular_citadel/icons/obj/genitals/penis_onmob.dmi
index 2457759b73..434f171e22 100644
Binary files a/modular_citadel/icons/obj/genitals/penis_onmob.dmi and b/modular_citadel/icons/obj/genitals/penis_onmob.dmi differ
diff --git a/modular_citadel/icons/obj/genitals/testicles_onmob.dmi b/modular_citadel/icons/obj/genitals/testicles_onmob.dmi
index 581bcb0583..33659cf13c 100644
Binary files a/modular_citadel/icons/obj/genitals/testicles_onmob.dmi and b/modular_citadel/icons/obj/genitals/testicles_onmob.dmi differ
diff --git a/modular_citadel/icons/obj/genitals/vagina_onmob.dmi b/modular_citadel/icons/obj/genitals/vagina_onmob.dmi
index f5daa3fea1..c4cf891eac 100644
Binary files a/modular_citadel/icons/obj/genitals/vagina_onmob.dmi and b/modular_citadel/icons/obj/genitals/vagina_onmob.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 37df11d40c..bb47c443ff 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -130,6 +130,7 @@
#include "code\__HELPERS\qdel.dm"
#include "code\__HELPERS\radiation.dm"
#include "code\__HELPERS\radio.dm"
+#include "code\__HELPERS\reagents.dm"
#include "code\__HELPERS\roundend.dm"
#include "code\__HELPERS\sanitize_values.dm"
#include "code\__HELPERS\shell.dm"
@@ -247,7 +248,6 @@
#include "code\controllers\subsystem\moods.dm"
#include "code\controllers\subsystem\nightshift.dm"
#include "code\controllers\subsystem\npcpool.dm"
-#include "code\controllers\subsystem\orbit.dm"
#include "code\controllers\subsystem\overlays.dm"
#include "code\controllers\subsystem\pai.dm"
#include "code\controllers\subsystem\parallax.dm"
@@ -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"
@@ -360,6 +359,7 @@
#include "code\datums\components\mood.dm"
#include "code\datums\components\nanites.dm"
#include "code\datums\components\ntnet_interface.dm"
+#include "code\datums\components\orbiter.dm"
#include "code\datums\components\paintable.dm"
#include "code\datums\components\rad_insulation.dm"
#include "code\datums\components\radioactive.dm"
@@ -494,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"
@@ -638,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"
@@ -2103,6 +2108,7 @@
#include "code\modules\mob\living\simple_animal\friendly\gondola.dm"
#include "code\modules\mob\living\simple_animal\friendly\lizard.dm"
#include "code\modules\mob\living\simple_animal\friendly\mouse.dm"
+#include "code\modules\mob\living\simple_animal\friendly\panda.dm"
#include "code\modules\mob\living\simple_animal\friendly\penguin.dm"
#include "code\modules\mob\living\simple_animal\friendly\pet.dm"
#include "code\modules\mob\living\simple_animal\friendly\sloth.dm"
@@ -2264,7 +2270,6 @@
#include "code\modules\NTNet\network.dm"
#include "code\modules\NTNet\relays.dm"
#include "code\modules\NTNet\services\_service.dm"
-#include "code\modules\orbit\orbit.dm"
#include "code\modules\paperwork\clipboard.dm"
#include "code\modules\paperwork\contract.dm"
#include "code\modules\paperwork\filingcabinet.dm"
@@ -2480,6 +2485,7 @@
#include "code\modules\reagents\chemistry\recipes\others.dm"
#include "code\modules\reagents\chemistry\recipes\pyrotechnics.dm"
#include "code\modules\reagents\chemistry\recipes\slime_extracts.dm"
+#include "code\modules\reagents\chemistry\recipes\special.dm"
#include "code\modules\reagents\chemistry\recipes\toxins.dm"
#include "code\modules\reagents\reagent_containers\blood_pack.dm"
#include "code\modules\reagents\reagent_containers\borghydro.dm"
@@ -2773,6 +2779,7 @@
#include "code\modules\vehicles\speedbike.dm"
#include "code\modules\vehicles\vehicle_actions.dm"
#include "code\modules\vehicles\vehicle_key.dm"
+#include "code\modules\vehicles\wheelchair.dm"
#include "code\modules\vehicles\cars\car.dm"
#include "code\modules\vehicles\cars\clowncar.dm"
#include "code\modules\vending\_vending.dm"
@@ -2824,7 +2831,6 @@
#include "modular_citadel\code\controllers\configuration\entries\general.dm"
#include "modular_citadel\code\controllers\subsystem\job.dm"
#include "modular_citadel\code\controllers\subsystem\shuttle.dm"
-#include "modular_citadel\code\datums\uplink_items_cit.dm"
#include "modular_citadel\code\datums\components\material_container.dm"
#include "modular_citadel\code\datums\components\phantomthief.dm"
#include "modular_citadel\code\datums\components\souldeath.dm"
@@ -2879,8 +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\flashlight.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"
@@ -3035,7 +3039,6 @@
#include "modular_citadel\code\modules\research\techweb\_techweb.dm"
#include "modular_citadel\code\modules\research\techweb\all_nodes.dm"
#include "modular_citadel\code\modules\research\xenobiology\xenobio_camera.dm"
-#include "modular_citadel\code\modules\uplink\uplink_items.dm"
#include "modular_citadel\code\modules\vehicles\secway.dm"
#include "modular_citadel\code\modules\vore\hook-defs_vr.dm"
#include "modular_citadel\code\modules\vore\persistence.dm"