Your station has been selected to carry out the Gateway Project.
The equipment will be shipped to you at the start of the next quarter. You are to prepare a secure location to house the equipment as outlined in the attached documents.
Your station has been selected to carry out the Gateway Project.
The equipment will be shipped to you at the start of the next quarter. You are to prepare a secure location to house the equipment as outlined in the attached documents.
Hello there, proud operator of an NT-Sec Prisoner Rehabilitation Center. A solution to rising crime rates and falling productivity, these facilities are specifically designed for the safe, productive imprisonment of your most dangerous criminals.
To press a long-term prisoner into the service of the station, replace his equipment with prisoners' garb at one of the prison lockers, as per normal operating procedure. Before assigning a prisoner his ID, insert the ID into a prisoner management console and assign the prisoner a quota, based on the severity of his crime. A single sheet of most materials produces five points for the prisoner, and points can be expected to be produced at a rate of about 100 per minute, though punishments as severe as forced labor should be reserved for serious crimes of sentences not less than five minutes long. Once you have prepared the prisoner, place him in the secure northern half of the labor shuttle, and send him to the station. Once he meets his quota by feeding sheets to the stacker, he will be allowed to return to the station, and will be able to open the secure door to the prisoner release area.
Hello there, proud operator of an NT-Sec Prisoner Rehabilitation Center. A solution to rising crime rates and falling productivity, these facilities are specifically designed for the safe, productive imprisonment of your most dangerous criminals.
To press a long-term prisoner into the service of the station, replace his equipment with prisoners' garb at one of the prison lockers, as per normal operating procedure. Before assigning a prisoner his ID, insert the ID into a prisoner management console and assign the prisoner a quota, based on the severity of his crime. A single sheet of most materials produces five points for the prisoner, and points can be expected to be produced at a rate of about 100 per minute, though punishments as severe as forced labor should be reserved for serious crimes of sentences not less than five minutes long. Once you have prepared the prisoner, place him in the secure northern half of the labor shuttle, and send him to the station. Once he meets his quota by feeding sheets to the stacker, he will be allowed to return to the station, and will be able to open the secure door to the prisoner release area.
Your station has been selected to carry out the Gateway Project.
The equipment will be shipped to you at the start of the next quarter. You are to prepare a secure location to house the equipment as outlined in the attached documents.
Your station has been selected to carry out the Gateway Project.
The equipment will be shipped to you at the start of the next quarter. You are to prepare a secure location to house the equipment as outlined in the attached documents.
Install circuit board, glass and wiring to complete Teleporter Control Console
Use a screwdriver, wirecutter and screwdriver again on the Teleporter Station to connect it
Set destination with Teleporter Control Computer
Activate Teleporter Hub with Teleporter Station
"; name = "Teleporter Instructions"},/turf/simulated/floor/plasteel/shuttle{icon_state = "shuttlefloor4"},/area/shuttle/syndicate)
+"oJ" = (/obj/machinery/teleport/hub/syndicate,/turf/simulated/floor/plasteel/shuttle{icon_state = "shuttlefloor4"},/area/shuttle/syndicate)
+"oK" = (/obj/effect/forcefield,/turf/simulated/floor/plasteel/cult{icon_state = "cultdamage3"},/area/wizard_station)
+"oL" = (/obj/structure/shuttle/engine/propulsion,/turf/simulated/floor/plating,/area/shuttle/syndicate)
+"oM" = (/obj/structure/shuttle/engine/propulsion{icon_state = "propulsion_l"},/turf/simulated/floor/plating,/area/shuttle/syndicate)
+"oN" = (/obj/structure/shuttle/engine/propulsion{icon_state = "propulsion_r"},/turf/simulated/floor/plating,/area/shuttle/syndicate)
+"oO" = (/obj/machinery/door/poddoor{id = "thunderdomehea"; name = "Heavy Supply"},/turf/simulated/floor/plasteel/black,/area/tdome/arena)
+"oP" = (/turf/simulated/floor/plasteel/cult/airless{icon_state = "cultdamage2"},/area/wizard_station)
+"oQ" = (/obj/effect/decal/remains/human,/turf/simulated/floor/plasteel/cult{icon_state = "cultdamage"},/area/wizard_station)
+"oR" = (/obj/effect/forcefield,/turf/space,/area/wizard_station)
+"oS" = (/turf/simulated/floor/plasteel/cult/airless{icon_state = "cultdamage5"},/area/wizard_station)
+"oT" = (/obj/structure/rack,/obj/item/clothing/under/color/red,/obj/item/clothing/shoes/sneakers/brown,/obj/item/clothing/suit/armor/vest,/obj/item/clothing/head/helmet/swat,/obj/item/weapon/gun/energy/laser,/turf/simulated/floor/plasteel/black,/area/tdome/arena)
+"oU" = (/turf/indestructible/fakeglass{icon_state = "fakewindows"; dir = 8},/area/tdome/tdomeadmin)
+"oV" = (/turf/indestructible/fakeglass{icon_state = "fakewindows2"; dir = 8},/area/tdome/tdomeadmin)
+"oW" = (/turf/indestructible/fakeglass{icon_state = "fakewindows"; dir = 4},/area/tdome/tdomeadmin)
+"oX" = (/obj/structure/rack,/obj/item/clothing/under/color/green,/obj/item/clothing/shoes/sneakers/brown,/obj/item/clothing/suit/armor/vest,/obj/item/clothing/head/helmet/swat,/obj/item/weapon/gun/energy/laser,/turf/simulated/floor/plasteel/black,/area/tdome/arena)
+"oY" = (/obj/structure/lattice,/obj/effect/forcefield,/turf/space,/area/wizard_station)
+"oZ" = (/obj/effect/forcefield,/turf/space/transit,/area/wizard_station)
+"pa" = (/turf/simulated/floor/plasteel/redyellow,/area/tdome/tdomeadmin)
+"pb" = (/obj/structure/stool/bed/chair{dir = 1},/obj/effect/landmark{name = "tdomeadmin"},/turf/simulated/floor/plasteel/redyellow,/area/tdome/tdomeadmin)
+"pc" = (/obj/structure/table,/obj/machinery/computer/security/telescreen{pixel_y = 0},/turf/simulated/floor/plasteel/redyellow,/area/tdome/tdomeadmin)
+"pd" = (/obj/machinery/button/flasher{id = "tdomeflash"; pixel_x = 0; pixel_y = 0},/obj/structure/table,/turf/simulated/floor/plasteel/redyellow,/area/tdome/tdomeadmin)
+"pe" = (/obj/structure/stool/bed/chair/comfy/brown{dir = 1},/turf/simulated/floor/plasteel/redyellow,/area/tdome/tdomeadmin)
+"pf" = (/obj/machinery/door/airlock{icon = 'icons/obj/doors/airlocks/station/uranium.dmi'; name = "Personal Quarters"},/turf/simulated/floor/plasteel/cult,/area/wizard_station)
+"pg" = (/turf/indestructible/riveted,/area/tdome/tdomeadmin)
+"ph" = (/obj/machinery/computer/security/telescreen{pixel_y = -32},/turf/simulated/floor/plasteel/redyellow,/area/tdome/tdomeadmin)
+"pi" = (/turf/simulated/floor/plasteel,/area/tdome/tdomeadmin)
+"pj" = (/turf/simulated/floor/carpet,/area/wizard_station)
+"pk" = (/obj/structure/table/wood,/obj/effect/landmark{name = "Teleport-Scroll"},/obj/item/weapon/dice/d20,/obj/item/weapon/dice,/turf/simulated/floor/carpet,/area/wizard_station)
+"pl" = (/turf/simulated/floor/plasteel/cult,/turf/simulated/wall/shuttle{dir = 2; icon_state = "swall_f10"; layer = 2},/area/wizard_station)
+"pm" = (/turf/simulated/floor/plasteel/cult/airless{icon_state = "cultdamage6"},/area/wizard_station)
+"pn" = (/turf/indestructible/fakedoor{name = "Thunderdome Admin"},/area/tdome/tdomeadmin)
+"po" = (/obj/structure/table,/obj/machinery/button/door{id = "thunderdomehea"; name = "Heavy Supply Control"; pixel_y = 0; req_access_txt = "102"},/turf/simulated/floor/plasteel,/area/tdome/tdomeadmin)
+"pp" = (/obj/structure/table,/obj/machinery/button/door{id = "thunderdomegen"; name = "General Supply Control"; pixel_y = 0; req_access_txt = "102"},/turf/simulated/floor/plasteel,/area/tdome/tdomeadmin)
+"pq" = (/obj/structure/table,/obj/machinery/button/door{id = "thunderdome"; name = "Main Blast Doors Control"; pixel_y = 0; req_access_txt = "102"},/turf/simulated/floor/plasteel,/area/tdome/tdomeadmin)
+"pr" = (/obj/structure/stool/bed,/obj/item/weapon/bedsheet/wiz,/turf/simulated/floor/carpet,/area/wizard_station)
+"ps" = (/turf/simulated/wall/shuttle{icon_state = "swall1"; dir = 2},/area/wizard_station)
+"pt" = (/obj/effect/decal/cleanable/blood/gibs/body,/turf/simulated/floor/plasteel/cult/airless{icon_state = "cultdamage"},/area/wizard_station)
+"pu" = (/turf/simulated/wall/shuttle{icon_state = "swall3"; dir = 2},/area/wizard_station)
+"pv" = (/turf/simulated/floor/plasteel/cult/airless{icon_state = "cultdamage7"},/area/wizard_station)
+"pw" = (/obj/structure/dresser,/obj/item/weapon/storage/backpack/satchel,/turf/simulated/floor/carpet,/area/wizard_station)
+"px" = (/obj/structure/table/wood,/obj/item/weapon/storage/bag/tray,/obj/item/weapon/reagent_containers/food/snacks/burger/spell,/turf/simulated/floor/carpet,/area/wizard_station)
+"py" = (/turf/indestructible/fakedoor{name = "Squad 2 Pod"},/area/wizard_station)
+"pz" = (/turf/simulated/wall/shuttle,/area/wizard_station)
+"pA" = (/obj/structure/shuttle/engine/heater,/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating/airless,/area/wizard_station)
+"pB" = (/turf/indestructible/riveted,/area/centcom/holding)
+"pC" = (/obj/structure/table/wood,/obj/item/weapon/gun/magic/wand{desc = "Used in emergencies to reignite magma engines."; max_charges = 0; name = "wand of emergency engine ignition"},/turf/simulated/floor/plasteel/cult,/area/wizard_station)
+"pD" = (/obj/structure/table/wood,/turf/simulated/floor/plasteel/cult,/area/wizard_station)
+"pE" = (/obj/structure/shuttle/engine/propulsion{icon_state = "propulsion_l"},/turf/space,/area/wizard_station)
+"pF" = (/obj/structure/table,/turf/simulated/floor/plasteel/freezer{dir = 2},/area/centcom/holding)
+"pG" = (/obj/structure/closet/secure_closet/bar{req_access_txt = "25"},/turf/simulated/floor/plasteel/freezer{dir = 2},/area/centcom/holding)
+"pH" = (/turf/simulated/floor/plasteel/freezer{dir = 2},/area/centcom/holding)
+"pI" = (/obj/structure/reagent_dispensers/beerkeg,/turf/simulated/floor/plasteel/freezer{dir = 2},/area/centcom/holding)
+"pJ" = (/obj/structure/table,/obj/item/weapon/storage/box/donkpockets{pixel_x = 3; pixel_y = 3},/obj/item/weapon/storage/box/donkpockets{pixel_x = 3; pixel_y = 3},/obj/item/weapon/storage/box/donkpockets{pixel_x = 3; pixel_y = 3},/obj/item/weapon/storage/box/donkpockets{pixel_x = 3; pixel_y = 3},/turf/simulated/floor/plasteel/freezer{dir = 2},/area/centcom/holding)
+"pK" = (/obj/structure/rack,/obj/item/toy/sword,/turf/simulated/floor/plasteel/cafeteria,/area/centcom/holding)
+"pL" = (/obj/structure/rack,/obj/item/device/camera,/turf/simulated/floor/plasteel/cafeteria,/area/centcom/holding)
+"pM" = (/turf/simulated/floor/plasteel/cafeteria,/area/centcom/holding)
+"pN" = (/obj/structure/rack,/obj/item/toy/gun,/turf/simulated/floor/plasteel/cafeteria,/area/centcom/holding)
+"pO" = (/obj/effect/overlay/palmtree_r,/obj/effect/overlay/coconut,/turf/simulated/floor/plating/beach/sand,/area/centcom/holding)
+"pP" = (/turf/simulated/floor/plating/beach/sand,/area/centcom/holding)
+"pQ" = (/obj/effect/overlay/palmtree_l,/turf/simulated/floor/plating/beach/sand,/area/centcom/holding)
+"pR" = (/obj/machinery/door/airlock{icon = 'icons/obj/doors/airlocks/station/uranium.dmi'; name = "Engine Room B"},/turf/space,/area/wizard_station)
+"pS" = (/obj/structure/table,/obj/item/clothing/head/that,/turf/simulated/floor/plasteel/freezer{dir = 2},/area/centcom/holding)
+"pT" = (/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/plasteel/cafeteria,/area/centcom/holding)
+"pU" = (/obj/item/device/camera,/turf/simulated/floor/plating/beach/sand,/area/centcom/holding)
+"pV" = (/obj/structure/cult/forge{desc = "A engine used in powering the wizards ship"; name = "magma engine"},/turf/simulated/floor/plasteel/cult,/area/wizard_station)
+"pW" = (/obj/structure/table,/obj/item/ammo_box/foambox,/turf/simulated/floor/plasteel/freezer{dir = 2},/area/centcom/holding)
+"pX" = (/obj/structure/table,/obj/item/weapon/reagent_containers/food/drinks/shaker,/turf/simulated/floor/plasteel/freezer{dir = 2},/area/centcom/holding)
+"pY" = (/obj/structure/table,/obj/item/weapon/lighter,/turf/simulated/floor/plasteel/freezer{dir = 2},/area/centcom/holding)
+"pZ" = (/obj/structure/table,/obj/item/weapon/dice/d20,/turf/simulated/floor/plasteel/freezer{dir = 2},/area/centcom/holding)
+"qa" = (/obj/structure/table,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola,/turf/simulated/floor/plasteel/freezer{dir = 2},/area/centcom/holding)
+"qb" = (/obj/structure/stool{pixel_y = 8},/obj/item/clothing/head/bandana{pixel_y = -10},/obj/item/clothing/glasses/sunglasses,/turf/simulated/floor/plating/beach/sand,/area/centcom/holding)
+"qc" = (/obj/structure/stool{pixel_y = 8},/turf/simulated/floor/plating/beach/sand,/area/centcom/holding)
+"qd" = (/obj/structure/window/reinforced{color = "#008000"; dir = 1},/turf/simulated/floor/plating/lava/airless,/area/wizard_station)
+"qe" = (/obj/structure/rack,/obj/item/clothing/head/that,/obj/item/clothing/under/suit_jacket,/obj/item/clothing/tie/waistcoat,/turf/simulated/floor/plasteel/cafeteria,/area/centcom/holding)
+"qf" = (/obj/item/toy/beach_ball,/turf/simulated/floor/plating/beach/sand,/area/centcom/holding)
+"qg" = (/obj/structure/shuttle/engine/heater,/turf/simulated/floor/plating/lava/airless,/area/wizard_station)
+"qh" = (/obj/structure/rack,/obj/item/weapon/storage/crayons,/obj/item/weapon/gun/projectile/automatic/toy/pistol,/turf/simulated/floor/plasteel/cafeteria,/area/centcom/holding)
+"qi" = (/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plasteel/cafeteria,/area/centcom/holding)
+"qj" = (/obj/structure/shuttle/engine/propulsion,/turf/space,/area/space)
+"qk" = (/obj/structure/rack,/obj/item/weapon/storage/crayons,/obj/item/weapon/gun/projectile/shotgun/toy/crossbow,/turf/simulated/floor/plasteel/cafeteria,/area/centcom/holding)
+"ql" = (/turf/simulated/floor/plating/beach/coastline,/area/centcom/holding)
+"qm" = (/obj/item/clothing/head/collectable/paper,/turf/simulated/floor/plating/beach/coastline,/area/centcom/holding)
+"qn" = (/obj/structure/rack,/obj/item/clothing/shoes/laceup,/obj/item/clothing/under/suit_jacket/female{desc = "A black trouser suit for women. Very formal."; name = "black suit"; pixel_x = 3; pixel_y = 1},/turf/simulated/floor/plasteel/cafeteria,/area/centcom/holding)
+"qo" = (/obj/structure/table,/obj/item/weapon/gun/projectile/automatic/toy/pistol,/turf/simulated/floor/plasteel/cafeteria,/area/centcom/holding)
+"qp" = (/turf/simulated/floor/plating/beach/water,/area/centcom/holding)
+"qq" = (/turf/simulated/floor/plasteel/delivery,/area/centcom/holding)
+"qr" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plasteel,/area/centcom/holding)
+"qs" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plasteel,/area/centcom/holding)
+"qt" = (/obj/effect/landmark{name = "Holding Facility"},/turf/simulated/floor/engine,/area/centcom/holding)
+"qu" = (/turf/indestructible/abductor{icon_state = "alien21"},/area/abductor_ship)
+"qv" = (/turf/indestructible/abductor{icon_state = "alien20"},/area/abductor_ship)
+"qw" = (/turf/indestructible/abductor{icon_state = "alien23"},/area/abductor_ship)
+"qx" = (/turf/indestructible/abductor{icon_state = "alien22"},/area/abductor_ship)
+"qy" = (/turf/indestructible/abductor{icon_state = "alien24"},/area/abductor_ship)
+"qz" = (/turf/indestructible/abductor{icon_state = "alien16"},/area/abductor_ship)
+"qA" = (/obj/machinery/abductor/experiment{team = 1},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qB" = (/turf/indestructible/abductor{icon_state = "alien17"},/area/abductor_ship)
+"qC" = (/obj/machinery/abductor/pad{team = 1},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qD" = (/obj/effect/landmark/abductor/console,/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qE" = (/turf/indestructible/abductor{icon_state = "alien19"},/area/abductor_ship)
+"qF" = (/turf/indestructible/abductor{icon_state = "alien18"},/area/abductor_ship)
+"qG" = (/obj/machinery/abductor/experiment{team = 4},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qH" = (/obj/machinery/abductor/pad{team = 4},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qI" = (/obj/effect/landmark/abductor/console{team = 4},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qJ" = (/turf/indestructible/abductor{icon_state = "alien14"},/area/abductor_ship)
+"qK" = (/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qL" = (/obj/machinery/computer/camera_advanced/abductor{team = 1},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qM" = (/turf/indestructible/abductor{icon_state = "alien15"},/area/abductor_ship)
+"qN" = (/obj/structure/closet/abductor,/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qO" = (/obj/machinery/computer/camera_advanced/abductor{team = 4},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qP" = (/turf/indestructible/abductor{icon_state = "alien12"},/area/abductor_ship)
+"qQ" = (/obj/effect/landmark/abductor/scientist,/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qR" = (/obj/item/weapon/retractor/alien,/obj/item/weapon/hemostat/alien,/obj/structure/table/abductor,/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qS" = (/obj/effect/landmark/abductor/agent,/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qT" = (/obj/structure/optable/abductor,/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qU" = (/turf/indestructible/abductor{icon_state = "alien13"},/area/abductor_ship)
+"qV" = (/obj/structure/table/abductor,/obj/item/weapon/storage/box/alienhandcuffs,/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qW" = (/obj/effect/landmark/abductor/scientist{team = 4},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qX" = (/obj/effect/landmark/abductor/agent{team = 4},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"qY" = (/turf/indestructible/abductor{icon_state = "alien10"},/area/abductor_ship)
+"qZ" = (/obj/item/weapon/surgical_drapes,/obj/item/weapon/paper/abductor,/obj/item/weapon/scalpel/alien,/obj/structure/table/abductor,/obj/item/weapon/cautery/alien,/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"ra" = (/turf/indestructible/abductor{icon_state = "alien11"},/area/abductor_ship)
+"rb" = (/turf/indestructible/abductor{icon_state = "alien6"},/area/abductor_ship)
+"rc" = (/obj/machinery/abductor/gland_dispenser,/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"rd" = (/turf/indestructible/abductor{icon_state = "alien7"},/area/abductor_ship)
+"re" = (/obj/structure/stool/bed/abductor,/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"rf" = (/obj/structure/table/abductor,/obj/item/weapon/surgicaldrill/alien,/obj/item/weapon/circular_saw/alien,/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"rg" = (/turf/indestructible/abductor{icon_state = "alien9"},/area/abductor_ship)
+"rh" = (/turf/indestructible/abductor{icon_state = "alien8"},/area/abductor_ship)
+"ri" = (/turf/indestructible/abductor{icon_state = "alien2"},/area/abductor_ship)
+"rj" = (/turf/indestructible/abductor,/area/abductor_ship)
+"rk" = (/turf/indestructible/abductor{icon_state = "alien4"},/area/abductor_ship)
+"rl" = (/turf/indestructible/abductor{icon_state = "alien3"},/area/abductor_ship)
+"rm" = (/turf/indestructible/abductor{icon_state = "alien5"},/area/abductor_ship)
+"rn" = (/obj/machinery/abductor/experiment{team = 2},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"ro" = (/obj/machinery/abductor/pad{team = 2},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"rp" = (/obj/effect/landmark/abductor/console{team = 2},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"rq" = (/obj/machinery/abductor/experiment{team = 3},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"rr" = (/obj/machinery/abductor/pad{team = 3},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"rs" = (/obj/effect/landmark/abductor/console{team = 3},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"rt" = (/obj/machinery/computer/camera_advanced/abductor{team = 2},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"ru" = (/obj/machinery/computer/camera_advanced/abductor{team = 3},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"rv" = (/obj/effect/landmark/abductor/scientist{team = 2},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"rw" = (/obj/effect/landmark/abductor/agent{team = 2},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"rx" = (/obj/effect/landmark/abductor/scientist{team = 3},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+"ry" = (/obj/effect/landmark/abductor/agent{team = 3},/turf/simulated/floor/plating/abductor,/area/abductor_ship)
+
+(1,1,1) = {"
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacabababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacadaeaeaeaeaeadaeaeaeaeaeadaeaeaeaeaeadaeaeaeaeaead
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacabababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacafagagagagagahaiaiaiaiaiahajajajajajahalakakakanam
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacabababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacafagaoagaoagahaiaiaiaiaiahajapajapajaharaqaqaqasam
diff --git a/_maps/map_files/generic/z3.dmm b/_maps/map_files/generic/z3.dmm
index de3d265f3ac..96b671a035f 100644
--- a/_maps/map_files/generic/z3.dmm
+++ b/_maps/map_files/generic/z3.dmm
@@ -119,7 +119,7 @@
"cL" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plasteel/airless{icon_state = "dark"},/area/tcommsat/chamber)
"cM" = (/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plasteel/airless{icon_state = "dark"},/area/tcommsat/chamber)
"cN" = (/obj/structure/window/reinforced,/turf/simulated/floor/plasteel/airless{icon_state = "dark"},/area/tcommsat/chamber)
-"cO" = (/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/item/weapon/airlock_electronics,/turf/simulated/floor/plasteel/airless{icon_state = "dark"},/area/tcommsat/chamber)
+"cO" = (/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 1},/obj/item/weapon/electronics/airlock,/turf/simulated/floor/plasteel/airless{icon_state = "dark"},/area/tcommsat/chamber)
"cP" = (/obj/structure/door_assembly/door_assembly_hatch,/turf/simulated/floor/plasteel/airless,/area/tcommsat/chamber)
"cQ" = (/obj/item/weapon/cigbutt,/turf/simulated/floor/plasteel/airless,/area/tcommsat/chamber)
"cR" = (/obj/machinery/vending/snack,/turf/simulated/floor/plasteel/airless,/area/tcommsat/chamber)
@@ -241,7 +241,7 @@
"fe" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating/airless,/area/AIsattele)
"ff" = (/obj/effect/decal/cleanable/blood/old,/turf/simulated/floor/plating/airless,/area/AIsattele)
"fg" = (/obj/effect/decal/cleanable/oil,/turf/simulated/floor/plating/airless,/area/AIsattele)
-"fh" = (/obj/item/weapon/shard,/obj/item/weapon/module/power_control,/turf/simulated/floor/plating/airless,/area/AIsattele)
+"fh" = (/obj/item/weapon/shard,/obj/item/weapon/electronics/apc,/turf/simulated/floor/plating/airless,/area/AIsattele)
"fi" = (/obj/structure/closet,/turf/simulated/floor/plating/airless,/area/AIsattele)
"fj" = (/obj/item/weapon/storage/toolbox/electrical{pixel_x = 1; pixel_y = -1},/turf/simulated/floor/plating/airless,/area/AIsattele)
"fk" = (/obj/structure/closet/crate,/obj/item/device/aicard,/obj/item/device/multitool,/obj/item/weapon/weldingtool,/obj/item/weapon/wrench,/obj/item/weapon/circuitboard/teleporter,/turf/simulated/floor/plating/airless,/area/AIsattele)
diff --git a/_maps/map_files/generic/z4.dmm b/_maps/map_files/generic/z4.dmm
index e420d816869..b5703abbccf 100644
--- a/_maps/map_files/generic/z4.dmm
+++ b/_maps/map_files/generic/z4.dmm
@@ -338,7 +338,6 @@
"gz" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/turf/simulated/floor/plating/airless,/area/derelict/hallway/primary)
"gA" = (/obj/structure/window/fulltile{dir = 4},/turf/simulated/floor/plating/airless,/area/derelict/hallway/primary)
"gB" = (/obj/structure/lattice,/obj/structure/window/fulltile{dir = 1},/turf/space,/area/space)
-"gC" = (/obj/structure/lattice,/obj/structure/lattice,/obj/structure/window/fulltile{dir = 1},/turf/space,/area/space)
"gD" = (/turf/simulated/floor/plating,/area/derelict/arrival)
"gE" = (/obj/machinery/door/airlock/medical{name = "Morgue"; req_access_txt = "6"},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/derelict/medical/chapel)
"gF" = (/obj/machinery/light{icon_state = "tube1"; dir = 8},/turf/simulated/floor/plasteel/airless{icon_state = "white"},/area/derelict/medical)
@@ -358,7 +357,7 @@
"gT" = (/obj/structure/window/reinforced,/turf/simulated/floor/plasteel/airless{icon_state = "white"},/area/space)
"gU" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plasteel/airless{icon_state = "damaged2"},/area/derelict/hallway/primary)
"gV" = (/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plasteel,/area/derelict/arrival)
-"gW" = (/obj/structure/table,/obj/machinery/light/small{dir = 1},/obj/item/weapon/airlock_electronics,/turf/simulated/floor/plasteel/airless,/area/derelict/bridge/access)
+"gW" = (/obj/structure/table,/obj/machinery/light/small{dir = 1},/obj/item/weapon/electronics/airlock,/turf/simulated/floor/plasteel/airless,/area/derelict/bridge/access)
"gX" = (/obj/structure/rack,/obj/item/weapon/circuitboard/autolathe,/obj/item/weapon/circuitboard/protolathe{pixel_x = -5; pixel_y = -3},/turf/simulated/floor/plasteel,/area/derelict/bridge/ai_upload)
"gY" = (/turf/simulated/floor/plasteel{dir = 4; icon_state = "chapel"},/area/derelict/medical/chapel)
"gZ" = (/turf/simulated/floor/plasteel{dir = 1; icon_state = "chapel"},/area/derelict/medical/chapel)
@@ -584,7 +583,7 @@
"ll" = (/obj/machinery/door/window{base_state = "right"; dir = 4; icon_state = "right"},/turf/simulated/floor/plasteel/airless,/area/space)
"lm" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/turf/simulated/floor/plasteel/airless{icon_state = "bcircuit"; tag = "icon-bcircuit"},/area/derelict/bridge/ai_upload)
"ln" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating/airless,/area/derelict/gravity_generator)
-"lo" = (/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/item/apc_frame,/turf/simulated/floor/plating/airless,/area/derelict/gravity_generator)
+"lo" = (/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/item/wallframe/apc,/turf/simulated/floor/plating/airless,/area/derelict/gravity_generator)
"lp" = (/obj/machinery/door/window,/turf/simulated/floor/plasteel,/area/derelict/bridge/ai_upload)
"lq" = (/obj/item/weapon/ore/slag,/turf/simulated/floor/plasteel/airless{icon_state = "damaged4"},/area/derelict/gravity_generator)
"lr" = (/obj/structure/rack,/obj/item/weapon/circuitboard/smes,/turf/simulated/floor/plasteel,/area/derelict/bridge/access)
@@ -700,7 +699,7 @@
"nx" = (/obj/machinery/light/small,/turf/simulated/floor/plasteel,/area/derelict/solar_control)
"ny" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/turf/simulated/wall,/area/derelict/bridge/access)
"nz" = (/obj/machinery/door/airlock/maintenance,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plasteel,/area/derelict/bridge/access)
-"nA" = (/obj/structure/rack,/obj/item/weapon/module/power_control,/turf/simulated/floor/plasteel,/area/derelict/bridge/access)
+"nA" = (/obj/structure/rack,/obj/item/weapon/electronics/apc,/turf/simulated/floor/plasteel,/area/derelict/bridge/access)
"nB" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/wall,/area/derelict/bridge/access)
"nC" = (/turf/simulated/floor/plasteel/airless{icon_state = "damaged2"},/area/derelict/atmospherics)
"nD" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"},/turf/simulated/floor/plasteel,/area/derelict/bridge/access)
@@ -856,7 +855,7 @@
"qx" = (/obj/structure/rack,/obj/item/weapon/circuitboard/solar_control,/turf/simulated/floor/plasteel,/area/derelict/bridge/ai_upload)
"qy" = (/obj/item/ammo_casing/a357{pixel_x = -5},/obj/item/ammo_casing/a357{pixel_x = 5; pixel_y = 6},/obj/item/ammo_casing/a357,/turf/simulated/floor/plasteel/airless,/area/derelict/hallway/primary)
"qz" = (/obj/machinery/porta_turret_cover,/turf/simulated/floor/plasteel/airless,/area/derelict/bridge/ai_upload)
-"qA" = (/obj/structure/table,/obj/item/device/flash/handheld,/turf/simulated/floor/plasteel/airless,/area/derelict/bridge/access)
+"qA" = (/obj/structure/table,/obj/item/device/assembly/flash/handheld,/turf/simulated/floor/plasteel/airless,/area/derelict/bridge/access)
"qB" = (/obj/structure/table,/obj/effect/spawner/lootdrop/maintenance{lootcount = 8; name = "8maintenance loot spawner"},/turf/simulated/floor/plating/airless,/area/derelict/atmospherics)
"qC" = (/obj/item/weapon/storage/bag/ore,/turf/simulated/floor/mineral/bananium/airless,/area/space)
"qD" = (/obj/item/weapon/shovel,/turf/simulated/floor/mineral/bananium/airless,/area/space)
@@ -958,7 +957,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafYfYfYfYfYfYfYfYfYfYfYfYfYaaaaaaaaaaaaaaaaaaaaaaaadgdfdgaeaefDecevdBdBdBfPdxdxdydbdbdBcIcIaafFfMfmfdfgfgfgfffQfgfdfdfdgcgcbwbwbwfRfOfOfOfOfOfOfSfTfUfVfUfWfXfOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafYgigigigiggggggggggghgifYaaaaaaaaaaaaaaaaaaaafZaadfdfgaaeaedfgbdBdbdbfadBdBdbdcdddBdBcIcIaafFfFfmfdfdfdfgfdfdfdfdfdfdbwfxbjbjfxfxgdgdgegegffOodfSodfUfUfXfUfOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafYfYfYgigKggggggfYfYgEfYfYfYfYfYgjgkgkgkgjglgmgngogjgpaegqaedBdBdbdcdcdcdbdBdBdbdccIcIcIcIaaflfmfffdfgfufffufdfufugrfubjfxfxfxbjfxgegdgfgfgegsfUfUfUfUfUfUfUfOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagqfYiPfYfYfYfYfYgPfYgQggghggggggfYgtgtgtgugtolocgngnoeaeaeaeaecIcIdBgydddbdBcIcIcIcIcIcIaeaefFgzfmfffgfgfffFfufugrfufFgAbwbwgBgBgCgBfNfNfNfNfNfNfUfUgDfUfUfUfUfOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagqfYiPfYfYfYfYfYgPfYgQggghggggggfYgtgtgtgugtolocgngnoeaeaeaeaecIcIdBgydddbdBcIcIcIcIcIcIaeaefFgzfmfffgfgfffFfufugrfufFgAbwbwgBgBgBgBfNfNfNfNfNfNfUfUgDfUfUfUfUfOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaofomgYgZgYoggYgZgYfYgQgggQgggQggfYgFgtgtgtgtgGgvgwgnohgngnaeaecIcIcIcIdfcIcIcIcIcIcIaeaabjfdhtfmfffffdfgfffffFfkfkfkfkfkaeaeaeaaaaaagHfygHbjcBfNfSfSfUfSgIfUgJfOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaofhgojoiokhihhhihhfYgQgggQgggQgggEgtgtgtgtgtgtgvonotgngngnaaaeaecIcIgLhuoDcIcIaeaeaeaaaabjfdfmfmhvfffdfdfdfdfufkfIfxfIgMaaaeaaaaaaaaaaaagHaegMfNgNgNfUgNgOfUfUfOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahooooGhrhshrgZgYgZgYfYgQopgQoqgQggfYorgtgtgtgtoHosgvgwgngngnaaaaaeaecIcIcIcIcIaeaeaaaagSgSgTfdffgUfffgfdfgfufffufkfxgMfxfxaaaeaaaacDaaaaaaaagMaefNfUfUfUfUgVfSodfOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/_maps/map_files/generic/z5.dmm b/_maps/map_files/generic/z5.dmm
index 09ac6b41d04..f7d043a6a82 100644
--- a/_maps/map_files/generic/z5.dmm
+++ b/_maps/map_files/generic/z5.dmm
@@ -25,7 +25,7 @@
"ay" = (/turf/simulated/floor/plating/airless,/area/space)
"az" = (/obj/item/stack/rods,/obj/structure/window/reinforced{dir = 4},/obj/item/weapon/shard,/turf/simulated/floor/plating/airless,/area/mine/abandoned)
"aA" = (/obj/item/stack/rods,/turf/simulated/floor/plasteel/airless,/area/mine/abandoned)
-"aB" = (/obj/structure/lattice,/obj/structure/lattice,/turf/space,/area/space)
+"aB" = (/obj/structure/lattice,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/space,/area/mine/explored)
"aC" = (/obj/structure/lattice,/obj/item/weapon/shard{icon_state = "medium"},/turf/space,/area/space)
"aD" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced,/turf/simulated/floor/plating/airless,/area/mine/abandoned)
"aE" = (/obj/item/clothing/mask/facehugger{icon_state = "facehugger_dead"; stat = 2},/turf/simulated/floor/plasteel/airless,/area/mine/abandoned)
@@ -271,7 +271,7 @@
"fk" = (/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/turf/simulated/floor/plating/airless{icon_state = "asteroidplating"},/area/mine/explored)
"fl" = (/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/floor/plating/airless{icon_state = "asteroidplating"},/area/mine/explored)
"fm" = (/obj/machinery/door/airlock/glass_security{name = "Labor Camp Shuttle Security Airlock"; req_access_txt = "2"},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/mine/laborcamp)
-"fn" = (/obj/machinery/light/small{dir = 1},/obj/machinery/door_control{id = "Labor"; name = "Labor Camp Lockdown"; pixel_x = 0; pixel_y = 28; req_access_txt = "2"},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/mine/laborcamp)
+"fn" = (/obj/machinery/light/small{dir = 1},/obj/machinery/button/door{id = "Labor"; name = "Labor Camp Lockdown"; pixel_x = 0; pixel_y = 28; req_access_txt = "2"},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/mine/laborcamp)
"fo" = (/obj/machinery/door/poddoor/preopen{id = "Labor"; name = "labor camp blast door"},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/mine/laborcamp)
"fp" = (/turf/simulated/floor/plasteel,/area/mine/laborcamp)
"fq" = (/obj/machinery/mineral/processing_unit_console{machinedir = 6},/turf/simulated/wall,/area/mine/laborcamp)
@@ -332,7 +332,7 @@
"gt" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'HIGH VOLTAGE'"; icon_state = "shock"; name = "HIGH VOLTAGE"},/turf/simulated/wall/r_wall,/area/mine/laborcamp/security)
"gu" = (/obj/machinery/light{icon_state = "tube1"; dir = 8},/turf/simulated/floor/plasteel,/area/mine/laborcamp/security)
"gv" = (/obj/structure/stool/bed/chair/office/dark,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plasteel,/area/mine/laborcamp/security)
-"gw" = (/obj/machinery/door_control{id = "Labor"; name = "Labor Camp Lockdown"; pixel_x = 28; pixel_y = 7; req_access_txt = "2"},/obj/machinery/flasher_button{id = "Labor"; pixel_x = 26; pixel_y = -3},/obj/machinery/atmospherics/components/unary/vent_pump{dir = 1; on = 1},/turf/simulated/floor/plasteel,/area/mine/laborcamp/security)
+"gw" = (/obj/machinery/button/door{id = "Labor"; name = "Labor Camp Lockdown"; pixel_x = 28; pixel_y = 7; req_access_txt = "2"},/obj/machinery/button/flasher{id = "Labor"; pixel_x = 26; pixel_y = -3},/obj/machinery/atmospherics/components/unary/vent_pump{dir = 1; on = 1},/turf/simulated/floor/plasteel,/area/mine/laborcamp/security)
"gx" = (/obj/machinery/power/terminal{icon_state = "term"; dir = 1},/obj/structure/cable{icon_state = "0-2"; d2 = 2},/turf/simulated/floor/plating,/area/mine/laborcamp/security)
"gy" = (/turf/simulated/floor/plating,/area/mine/laborcamp/security)
"gz" = (/obj/machinery/atmospherics/pipe/manifold{dir = 8},/obj/machinery/meter,/turf/simulated/floor/plating,/area/mine/laborcamp/security)
@@ -374,7 +374,6 @@
"hj" = (/obj/machinery/telecomms/relay/preset/mining,/obj/machinery/light/small{dir = 1},/turf/simulated/floor/plasteel{icon_state = "vault"; dir = 1},/area/mine/maintenance)
"hk" = (/obj/machinery/alarm{pixel_y = 24},/obj/machinery/atmospherics/components/unary/vent_pump{on = 1},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/mine/maintenance)
"hl" = (/obj/structure/lattice,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/turf/space,/area/mine/explored)
-"hm" = (/obj/structure/lattice,/obj/structure/lattice,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/space,/area/mine/explored)
"hn" = (/obj/structure/lattice,/turf/space,/area/mine/explored)
"ho" = (/turf/space,/area/mine/unexplored)
"hp" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/bluegrid,/area/mine/maintenance)
@@ -389,7 +388,7 @@
"hy" = (/obj/item/clothing/under/rank/miner,/obj/effect/decal/remains/human,/turf/simulated/floor/plating/airless{icon_state = "asteroidplating"},/area/mine/explored)
"hz" = (/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosia/vulgaris,/turf/simulated/floor/plasteel/airless{icon_state = "asteroidfloor"},/area/mine/explored)
"hA" = (/obj/structure/stool/bed,/obj/item/weapon/bedsheet/brown,/turf/simulated/floor/carpet,/area/mine/living_quarters)
-"hB" = (/obj/machinery/light/small{dir = 4},/obj/machinery/door_control{id = "miningdorm1"; name = "Door Bolt Control"; normaldoorcontrol = 1; pixel_x = 25; pixel_y = 0; req_access_txt = "0"; specialfunctions = 4},/turf/simulated/floor/carpet,/area/mine/living_quarters)
+"hB" = (/obj/machinery/light/small{dir = 4},/obj/machinery/button/door{id = "miningdorm1"; name = "Door Bolt Control"; normaldoorcontrol = 1; pixel_x = 25; pixel_y = 0; req_access_txt = "0"; specialfunctions = 4},/turf/simulated/floor/carpet,/area/mine/living_quarters)
"hC" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple,/turf/simulated/floor/plasteel,/area/mine/living_quarters)
"hD" = (/obj/structure/lattice,/obj/structure/window/reinforced{dir = 4},/obj/machinery/light,/turf/space,/area/mine/west_outpost)
"hE" = (/obj/structure/table,/turf/simulated/floor/carpet,/area/mine/living_quarters)
@@ -398,7 +397,7 @@
"hH" = (/obj/structure/disposalpipe/trunk,/obj/structure/disposaloutlet{dir = 1},/turf/simulated/floor/plating/airless{icon_state = "asteroidplating"},/area/mine/explored)
"hI" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple,/obj/machinery/light/small{dir = 4},/turf/simulated/floor/plasteel,/area/mine/living_quarters)
"hJ" = (/obj/structure/disposalpipe/segment,/turf/simulated/mineral/random,/area/mine/unexplored)
-"hK" = (/obj/machinery/light/small{dir = 4},/obj/machinery/door_control{id = "miningdorm2"; name = "Door Bolt Control"; normaldoorcontrol = 1; pixel_x = 25; pixel_y = 0; req_access_txt = "0"; specialfunctions = 4},/turf/simulated/floor/carpet,/area/mine/living_quarters)
+"hK" = (/obj/machinery/light/small{dir = 4},/obj/machinery/button/door{id = "miningdorm2"; name = "Door Bolt Control"; normaldoorcontrol = 1; pixel_x = 25; pixel_y = 0; req_access_txt = "0"; specialfunctions = 4},/turf/simulated/floor/carpet,/area/mine/living_quarters)
"hL" = (/obj/structure/grille,/obj/structure/window/reinforced/fulltile,/turf/simulated/floor/plating,/area/mine/living_quarters)
"hM" = (/turf/simulated/floor/plating/airless{icon_state = "asteroidplating"},/area/mine/west_outpost)
"hN" = (/obj/machinery/door/airlock{id_tag = "miningdorm2"; name = "Room 2"},/turf/simulated/floor/plasteel,/area/mine/living_quarters)
@@ -414,7 +413,7 @@
"hX" = (/obj/machinery/disposal/bin,/obj/structure/disposalpipe/trunk{dir = 1},/turf/simulated/floor/plasteel{icon_state = "bar"},/area/mine/living_quarters)
"hY" = (/obj/machinery/vending/cigarette,/obj/machinery/newscaster{pixel_y = 32},/turf/simulated/floor/plasteel{icon_state = "bar"},/area/mine/living_quarters)
"hZ" = (/obj/machinery/vending/snack,/turf/simulated/floor/plasteel{icon_state = "bar"},/area/mine/living_quarters)
-"ia" = (/obj/machinery/light/small{dir = 4},/obj/machinery/door_control{id = "miningdorm3"; name = "Door Bolt Control"; normaldoorcontrol = 1; pixel_x = 25; pixel_y = 0; req_access_txt = "0"; specialfunctions = 4},/turf/simulated/floor/carpet,/area/mine/living_quarters)
+"ia" = (/obj/machinery/light/small{dir = 4},/obj/machinery/button/door{id = "miningdorm3"; name = "Door Bolt Control"; normaldoorcontrol = 1; pixel_x = 25; pixel_y = 0; req_access_txt = "0"; specialfunctions = 4},/turf/simulated/floor/carpet,/area/mine/living_quarters)
"ib" = (/obj/structure/table,/obj/item/weapon/pickaxe,/turf/simulated/floor/plasteel,/area/mine/west_outpost)
"ic" = (/obj/machinery/newscaster{pixel_y = 32},/turf/simulated/floor/plasteel,/area/mine/west_outpost)
"id" = (/obj/structure/table,/obj/machinery/microwave,/turf/simulated/floor/plasteel,/area/mine/west_outpost)
@@ -768,7 +767,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarasakajalaaababababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacabababaaaaaaaaaaaaaaaaaaaaafafafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaratauavalalababababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacabababalalalalalalalalalalafafafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaawakaxabababababacacacacacacacacacacacacacacacacacacacacacacacacacaeacacacacacacacacacacacacaeacacacacacacacacacabababayayayayayayayayayayafafafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalalazaAakaxabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacabababababalalalalalaBalalalafafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalalazaAakaxabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacabababababalalalalalalalalalafafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalalaCaDaEaFaxabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacababababaaaaaaaaaaaaaaaaaaaaaaafafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalalaGaHaIaxaJaKaxaxaxaxacacacacacacaeacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacababaaaaaaaaaaaaaaaaaaaaaaaaaaafafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalaLaMaraNaOaPagaQaFaxaRaRaxacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacababaaaaaaaaaaaaaaaaaaaaaaaaaaafafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -880,7 +879,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababababababacacacacacacacacacacacac
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababababacacacacacacacacacacacacacacacacacabababafafafafafafafafafafafgXgYhaafababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacabababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafafafaiaiafafafbGbGbGewewbGafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababaaaaabababacacacacacacacacacacacacacacacacacababafbGbGdhdhhbdjdjdjdjdjdjhcgYhaafabababacacacacacacacacacacacacacacacacacacamacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachdhdhdhdhdhdhdacacabababaaaaaaaaaaaaaaaaaaaaaaaaaaaaafafafaiaiafafafbGbGbGewewbGafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababacacacacacacacacacacacacacacacacacabafbGbGbGbGgWhehehehehehehehfhghaafababababababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachdhhhihjhkhhhdacacabababaaaaaaaaaaaaaaaaaaaaaaaaaaafafafafaiaiafafafafbGbGewewbGafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababacacacacacacacacacacacacacacacacabafbGbGbGdhdhdGdGdGdGdGdGhlgYhmhnhoafafafafabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachdhhhphqhrhshdacacabababaaaaaaaaaaaaaaaaaaaaaaaaaaafafafafaiaiafafafafbGbGewewbGafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababacacacacacacacacacacacacacacacacabafbGbGbGdhdhdGdGdGdGdGdGhlgYaBhnhoafafafafabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachdhhhphqhrhshdacacabababaaaaaaaaaaaaaaaaaaaaaaaaaaafafafafaiaiafafafafbGbGewewbGafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababacacacacacacacacacacacacacacacacababafbGbGbGafhohohohohohogXgYhahohohobGbGbGafababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachthuhvachwhdhdhdhxhdhdhdacacabababaaaaaaaaaaaaaaaaaaaaaaaaafafafafafaiaiafafafafbGbGewewbGafafafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababacacacacacacacacacacacacacacacacacabafbGbGafhohohohohohohogXgYhahobGbGbGbGbGafafabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachyhvhzachwhAhBhwhChwafafabacabababaaaaaaaaaaaaaaaaaaaaaaafafafafafafaiaiafafafafafbGewewbGbGafafafafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabababababacacacacacacacacaeacacacacacacacacababafbGafhohohohohohohohDgYhabGbGbGbGbGbGbGafabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacachtdQachwhEhFhGhChwbGafafababababaaaaaaaaaaaaaaaaaaaaafafafafafafafaiaiafafafafafbGewewbGbGbGbGafafafafafaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiaiafafafafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/_maps/metastation.dm b/_maps/metastation.dm
index 4d5c43e9d02..ee707ba021a 100644
--- a/_maps/metastation.dm
+++ b/_maps/metastation.dm
@@ -15,7 +15,7 @@ z7 = empty space
#if !defined(MAP_FILE)
- #include "map_files\MetaStation\MetaStation.v41F.dmm"
+ #include "map_files\MetaStation\MetaStation.v41G.dmm"
#include "map_files\MetaStation\z2.dmm"
#include "map_files\MetaStation\z3.dmm"
#include "map_files\MetaStation\z4.dmm"
diff --git a/bot/NanoTrasenBot.py b/bot/NanoTrasenBot.py
index 1e1aac5087d..518f18d1a2b 100644
--- a/bot/NanoTrasenBot.py
+++ b/bot/NanoTrasenBot.py
@@ -25,7 +25,6 @@ import irchat
#
# PSYCO
write_to_a_file = False #Only affects psyco
-write_youtube_to_file = True #True = YTCV4 will load, false = YTCV3 will load
try:
import psyco
except ImportError:
@@ -82,16 +81,12 @@ from random import choice as fsample
from C_rtd import rtd
from C_heaortai import heaortai
from C_srtd import srtd
-if write_youtube_to_file:
- from YTCv4 import YTCV4 as YTCV2
-else:
- from YTCv3 import YTCV2 #Downgraded version supports Cache disabling, but is slower
from save_load import save,load
if psyco_exists:
def psyco_bond(func):
psyco.bind(func)
return func.__name__+" Psycofied"
- for a in [rtd,srtd,C_heaortai.heaortai,sbna,YTCV2,fsample,C_rot13.rot13,C_eightball.eightball,fsample,
+ for a in [rtd,srtd,C_heaortai.heaortai,sbna,fsample,C_rot13.rot13,C_eightball.eightball,fsample,
C_eightball.eightball,C_sarcasticball.sarcasticball,Marakov_Chain.form_sentence,Marakov_Chain.give_data]:
print psyco_bond(a)
@@ -843,144 +838,6 @@ while True:
elif influx.split(" ")[0].lower().replace(",","").replace(":","") in SName+[Name.lower()] and "who created you" in influx.lower():
conn.privmsg(targetchannel, "I was created by Skibiliano.")
# The part ends here >
- elif parse_xkcd and "xkcd.com/" in influx.lower():
- if influx.lower()[0:3] == "www":
- data = "http://"+influx
- elif influx.lower()[0:3] == "xkc":
- data = "http://"+influx
- else:
- data = influx
- data = data.split(" ")
- for i in data:
- if "http://" in i and "xkcd" in i:
- churn = xkcdparser.xkcd(i)
- if churn == "NOTHING":
- pass
- else:
- conn.privmsg(targetchannel,sender+" : XKCD - "+churn)
- break
- else:
- pass
- elif automatic_youtube_reveal and "youtube.com/watch?v=" in influx.lower():
- temporal_list2 = []
- temporal_data = influx.split(" ")
- temporal_list = []
- for block in temporal_data:
- if "youtube.com/watch?v=" in block:
- temporal_list.append(block)
- for temdata in temporal_list:
-
- if temdata[0:3] == "you":
- temdata = "http://www."+temdata
- elif temdata[0:3] == "www":
- temdata = "http://"+temdata
- elif temdata[0:4] == "http":
- pass
- #Obscure ones
- elif temdata[0:3] == "ww.":
- temdata = "http://w"+temdata
- elif temdata[0:3] == "w.y":
- temdata = "http://ww"+temdata
- elif temdata[0:3] == ".yo":
- temdata = "http://www"+temdata
- elif temdata[0:3] == "ttp":
- temdata = "h"+temdata
- elif temdata[0:3] == "tp:":
- temdata = "ht"+temdata
- elif temdata[0:3] == "p:/" or temdata[0:3] == "p:\\":
- temdata = "htt"+temdata
- elif temdata[0:3] == "://" or temdata[0:3] == ":\\\\":
- temdata = "http"+temdata
- elif temdata[0:2] == "//" or temdata[0:2] == "\\\\":
- if temdata[2] == "y":
- temdata = "http://www."+temdata[2:]
- elif temdata[2] == "w":
- temdata = "http:"+temdata
- else:
- pass
- if debug:
- print truesender+":"+temdata
- arg = temdata
- check = temdata.lower()
-
- if cache_youtube_links == True:
- result = YTCV2(arg)
- else:
- result = YTCV2(arg,0)
- if type(result) == str:
- ### To remove ="
- if result[0:4] == 'nt="':
- result = result[4:]
- pass
- elif result[0:2] == '="':
- result = result[2:]
- pass
- else:
- pass
- if """ in result:
- result.replace(""",'"')
- if len(temporal_list) == 1:
- conn.privmsg(targetchannel,sender+" : "+result)
- break
- else:
- temporal_list2.append(result)
- else:
- if len(temporal_list) == 1:
- conn.privmsg(targetchannel,sender+" : The video does not exist")
- break
- else:
- temporal_list2.append("The video does not exist")
- if len(temporal_list) == 1:
- pass
- else:
- conn.privmsg(targetchannel,sender+" : "+str(reduce(lambda x,y: x+" :-And-: "+y,temporal_list2)))
- elif RegExpCheckerForWebPages("((http://)|(https://))|([a-zA-Z0-9]+[.])|([a-zA-Z0-9](3,)\.+[a-zA-Z](2,))",influx,1):
- arg2 = RegExpCheckerForWebPages("(http://)|([a-zA-Z0-9]+[.])|([a-zA-Z0-9](3,)\.+[a-zA-Z](2,))",influx,0)
- if arg2 == 404:
- pass
- else:
- if arg2[:7] == "http://":
- pass
- elif arg2[:4] == "www.":
- arg2 = "http://"+arg2
- else:
- arg2 = "http://"+arg2
- try:
- arg = Whoopshopchecker.TitleCheck(arg2)
- if len(arg2) == 0:
- pass
- else:
- conn.privmsg(targetchannel,sender+" : "+arg)
- except:
- #conn.privmsg(targetchannel,sender+" : An odd error occurred")
- pass
- elif respond_of_course and "take over the" in influx.lower() or respond_of_course and "conquer the" in influx.lower():
- if debug:
- print truesender+"::"+influx
- conn.privmsg(targetchannel,"Of course!")
- elif respond_khan and "khan" in influx.lower():
- if respond_khan:
- if debug:
- print truesender+"::"+influx
- if "khan " in influx.lower():
- conn.privmsg(targetchannel,"KHAAAAAAN!")
- elif " khan" in influx.lower():
- conn.privmsg(targetchannel,"KHAAAAAN!")
- elif influx.lower() == "khan":
- conn.privmsg(targetchannel,"KHAAAAAAAAAN!")
- elif influx.lower() == "khan?":
- conn.privmsg(targetchannel,"KHAAAAAAAAAAAAAN!")
- elif influx.lower() == "khan!":
- conn.privmsg(targetchannel,"KHAAAAAAAAAAAAAAAAAAN!")
- elif respond_khan and influx.lower().count("k") + influx.lower().count("h") + influx.lower().count("a") + influx.lower().count("n") + influx.lower().count("!") + influx.lower().count("?") == len(influx):
- if "k" in influx.lower() and "h" in influx.lower() and "a" in influx.lower() and "n" in influx.lower():
- if debug:
- print truesender+"::"+influx
- conn.privmsg(targetchannel,"KHAAAAN!")
- elif influx.split(" ")[0].lower() in ["thanks","danke","tack"] and len(influx.split(" ")) > 1 and influx.split(" ")[1].lower().replace("!","").replace("?","").replace(".","").replace(",","") in SName+[lowname]:
- conn.privmsg(targetchannel,"No problem %s" %(sender))
- elif "happy birthday" in influx.lower() and birthday_announced == time.gmtime(time.time())[0]:
- conn.privmsg(targetchannel,sender+" : Thanks :)")
elif influx.split(" ")[0].lower().replace(",","").replace(".","").replace("!","").replace("?","") in SName+[lowname] and "call me" in influx.lower():
if allow_callnames == True:
arg = influx.split(" ")
@@ -1189,20 +1046,6 @@ while True:
else:
conn.privmsg(targetchannel,"Hiya "+sender)
secdice = random.randint(0,10)
- if time.gmtime(time.time())[1] == 12 and time.gmtime(time.time())[2] == 15 and birthday_announced < time.gmtime(time.time())[0]:
- birthday_announced = time.gmtime(time.time())[0]
- conn.privmsg(channel,"Hey everybody! I just noticed it's my birthday!")
- time.sleep(0.5)
- tag = random.choice(["birthday","robot+birthday","happy+birthday+robot"])
- arg1 = urllib2.urlopen("http://www.youtube.com/results?search_query=%s&page=&utm_source=opensearch"%tag)
- arg1 = arg1.read().split("\n")
- arg2 = []
- for i in arg1:
- if "watch?v=" in i:
- arg2.append(i)
- arg3 = random.choice(arg2)
-
- conn.privmsg(channel,"Here's a video of '%s' which I found! %s (%s)"%(tag.replace("+"," "),"http://www.youtube.com"+arg3[arg3.find('/watch?v='):arg3.find('/watch?v=')+20],YTCV2("http://www.youtube.com"+arg3[arg3.find('/watch?v='):arg3.find('/watch?v=')+20])))
if truesender.lower() in tell_list.keys():
try:
conn.privmsg(channel, "Also, "+truesender+" : "+tell_list[truesender.lower()][0])
diff --git a/bot/YTCv3.py b/bot/YTCv3.py
deleted file mode 100644
index a4e0542e85d..00000000000
--- a/bot/YTCv3.py
+++ /dev/null
@@ -1,72 +0,0 @@
-from urllib2 import urlopen
-from CORE_DATA import directory,no_absolute_paths
-def YTCV2(youtube_url,cache=1,debug=0):
- import time
- __doc__ = "Cache 0 = No cache access, Cache 1 = Cache access (Default)"
- if cache == 1:
- import md5
- import pickle
- crypt = md5.md5(youtube_url)
- try:
- cryp = crypt.hexdigest()
- if no_absolute_paths:
- tiedosto = open("YTCache/"+cryp,"r")
- else:
- tiedosto = open(directory+"\NanoTrasen\YTCache\\"+cryp,"r")
- aha = pickle.load(tiedosto)
- tiedosto.close()
- return aha[0]
- except:
- if no_absolute_paths:
- tiedosto = open("YTCache/"+crypt.hexdigest(),"w")
- else:
- tiedosto = open(directory+"\NanoTrasen\YTCache\\"+crypt.hexdigest(),"w")
- else:
- pass
- youtube_url = youtube_url.replace("http//","http://")
- if youtube_url.lower()[0:7] != "http://" and youtube_url[0:4] == "www.":
- youtube_url = "http://" + youtube_url
- if youtube_url.count("/") + youtube_url.count("\\") < 3:
- return "Reflex: Video cannot exist"
- try:
- website = urlopen(youtube_url)
- except:
- return "Reflex: Incorrect link!"
- for i in website:
- if i.count(' 11: #Longer than normal, presume troll.
- youtube_url.replace(cut_down,cut_down[:11])
- elif len(cut_down) < 11: #Shorter than normal
- pass
- except IndexError:
- return "Reflex: Where's the watch?v=?"
- first_two = cut_down[0:2]
- try:
- if no_absolute_paths:
- tiedosto = open("YTCache/"+first_two+".tcc","r")
- else:
- tiedosto = open(directory+"YTCache/"+first_two+".tcc","r")
- except:
- prev_dict = {}
- else:
- try:
- prev_dict = pickle.load(tiedosto)
- except EOFError: # Cache is corrupt
- os.remove(directory+tiedosto.name)
- print "REMOVED CORRUPT CACHE: "+tiedosto.name
- prev_dict = {}
- tiedosto.close() # I think this should belong here.
- if cut_down in prev_dict.keys():
- return prev_dict[cut_down]
- else:
- pass
- try:
- if no_absolute_paths:
- tiedosto = open("YTCache/"+first_two+".tcc","w")
- else:
- tiedosto = open(directory+"YTCache/"+first_two+".tcc","w")
- except IOError,error:
- if len(prev_dict.keys()) > 0:
- try:
- tiedosto = open(directory+"YTCache/"+first_two+".tcc","w") #This is a Just In Case
- except IOError:
- if did_tell == False:
- did_tell = True
- return "COULD NOT ACCESS FILE "+first_two+".tcc! The next time you run this link, it checks it through the web"
- Do_not_open = False
- else:
- did_tell = False
- pickle.dump(prev_dict,tiedosto)
- tiedosto.close()
- else:
- pass
- return "Very odd error occurred: " + str(error)
- youtube_url = youtube_url.replace("http//","http://")
- if youtube_url.lower()[0:7] != "http://" and youtube_url[0:4] == "www.":
- youtube_url = "http://" + youtube_url
- if youtube_url.count("/") + youtube_url.count("\\") < 3:
- if len(prev_dict.keys()) > 0:
- if Do_not_open == True:
- tiedosto = open(directory+"YTCache/"+first_two+".tcc","w") #This is a Just In Case
- pickle.dump(prev_dict,tiedosto)
- tiedosto.close()
- else:
- pass
- return "Reflex: Video cannot exist"
- else:
- if "http://" in youtube_url[0:12].lower() and youtube_url[0:7].lower() != "http://":
- youtube_url = youtube_url[youtube_url.find("http://"):]
- if "?feature=player_embedded&" in youtube_url:
- youtube_url = youtube_url.replace("?feature=player_embedded&","?")
- try:
- website = urlopen(youtube_url)
- except:
- if len(prev_dict.keys()) > 0:
- if Do_not_open == True:
- tiedosto = open(directory+"YTCache/"+first_two+".tcc","w") #This is a Just In Case
- pickle.dump(prev_dict,tiedosto)
- tiedosto.close()
- else:
- pass
- return "Reflex: Incorrect link!"
- for i in website.readlines():
- if i.count('',contentvar)]
- if """ in result:
- result = result.replace(""",'"')
- else:
- pass
- if "&" in result:
- result = result.replace("&","&")
- else:
- pass
- if "'" in result:
- result = result.replace("'","'")
- else:
- pass
- if Do_not_open == True:
- tiedosto = open(directory+"YTCache/"+first_two+".tcc","w") #This is a Just In Case
- prev_dict[cut_down] = result
- pickle.dump(prev_dict,tiedosto)
- tiedosto.close()
- return result
- if Do_not_open == True:
- tiedosto = open(directory+"YTCache/"+first_two+".tcc","w") #This is a Just In Case
- prev_dict[cut_down] = "No title for video, Removed / Needs Age verification / Does not exist"
- pickle.dump(prev_dict,tiedosto)
- tiedosto.close()
- return "No title for video, Removed / Needs age verification / Does not exist"
diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm
index 321e172522d..4b6d445a3db 100644
--- a/code/ATMOSPHERICS/atmospherics.dm
+++ b/code/ATMOSPHERICS/atmospherics.dm
@@ -9,7 +9,6 @@ Pipes -> Pipelines
Pipelines + Other Objects -> Pipe network
*/
-
/obj/machinery/atmospherics
anchored = 1
idle_power_usage = 0
@@ -25,7 +24,11 @@ Pipelines + Other Objects -> Pipe network
var/image/pipe_vision_img = null
+ var/device_type = 0
+ var/list/obj/machinery/atmospherics/nodes = list()
+
/obj/machinery/atmospherics/New()
+ nodes.len = device_type
..()
SSair.atmos_machinery += src
SetInitDirections()
@@ -33,10 +36,13 @@ Pipelines + Other Objects -> Pipe network
stored = new(src, make_from=src)
/obj/machinery/atmospherics/Destroy()
+ for(DEVICE_TYPE_LOOP)
+ nullifyNode(I)
+
SSair.atmos_machinery -= src
- if (stored)
+ if(stored)
qdel(stored)
- stored = null
+ stored = null
for(var/mob/living/L in src)
L.remove_ventcrawl()
@@ -44,15 +50,50 @@ Pipelines + Other Objects -> Pipe network
if(pipe_vision_img)
qdel(pipe_vision_img)
- ..()
+ return ..()
+ //return QDEL_HINT_FINDREFERENCE
+
+/obj/machinery/atmospherics/proc/nullifyNode(I)
+ if(NODE_I)
+ var/obj/machinery/atmospherics/N = NODE_I
+ N.disconnect(src)
+ NODE_I = null
//this is called just after the air controller sets up turfs
-/obj/machinery/atmospherics/proc/atmosinit()
- return
+/obj/machinery/atmospherics/proc/atmosinit(var/list/node_connects)
+ if(!node_connects) //for pipes where order of nodes doesn't matter
+ node_connects = list()
+ node_connects.len = device_type
+
+ for(DEVICE_TYPE_LOOP)
+ for(var/D in cardinal)
+ if(D & GetInitDirections())
+ if(D in node_connects)
+ continue
+ node_connects[I] = D
+ break
+
+ for(DEVICE_TYPE_LOOP)
+ for(var/obj/machinery/atmospherics/target in get_step(src,node_connects[I]))
+ if(can_be_node(target, I))
+ NODE_I = target
+ break
+
+ update_icon()
+
+/obj/machinery/atmospherics/proc/can_be_node(obj/machinery/atmospherics/target)
+ if(target.initialize_directions & get_dir(target,src))
+ return 1
+
+/obj/machinery/atmospherics/proc/pipeline_expansion()
+ return nodes
/obj/machinery/atmospherics/proc/SetInitDirections()
return
+/obj/machinery/atmospherics/proc/GetInitDirections()
+ return initialize_directions
+
/obj/machinery/atmospherics/proc/returnPipenet()
return
@@ -70,7 +111,12 @@ Pipelines + Other Objects -> Pipe network
return
/obj/machinery/atmospherics/proc/disconnect(obj/machinery/atmospherics/reference)
- return
+ if(istype(reference, /obj/machinery/atmospherics/pipe))
+ var/obj/machinery/atmospherics/pipe/P = reference
+ qdel(P.parent)
+ var/I = nodes.Find(reference)
+ NODE_I = null
+ update_icon()
/obj/machinery/atmospherics/update_icon()
return
@@ -129,16 +175,12 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/Deconstruct()
if(can_unwrench)
- var/turf/T = loc
- stored.loc = T
+ stored.loc = src.loc
transfer_fingerprints_to(stored)
stored = null
qdel(src)
-/obj/machinery/atmospherics/proc/nullifyPipenet(datum/pipeline/P)
- P.other_atmosmch -= src
-
/obj/machinery/atmospherics/proc/getpipeimage(iconset, iconstate, direction, col=rgb(255,255,255))
//Add identifiers for the iconset
@@ -160,13 +202,11 @@ Pipelines + Other Objects -> Pipe network
return img
-/obj/machinery/atmospherics/construction(D, P, pipe_type, obj_color)
- dir = D
- initialize_directions = P
+/obj/machinery/atmospherics/construction(pipe_type, obj_color)
if(can_unwrench)
color = obj_color
pipe_color = obj_color
- stored.dir = D //need to define them here, because the obj directions...
+ stored.dir = src.dir //need to define them here, because the obj directions...
stored.pipe_type = pipe_type //... were not set at the time the stored pipe was created
stored.color = obj_color
var/turf/T = loc
diff --git a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
index b78301584cb..e4858d432e6 100644
--- a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
@@ -19,7 +19,6 @@
Iconnery
*/
/obj/machinery/atmospherics/components/binary/hide(intact)
- showpipe = !intact
update_icon()
..(intact)
@@ -28,10 +27,8 @@ Housekeeping and pipe network stuff
*/
/obj/machinery/atmospherics/components/binary/atmosinit()
-
var/node2_connect = dir
var/node1_connect = turn(dir, 180)
- var/list/node_connects = new/list()
- node_connects.Add(node1_connect, node2_connect)
+ var/list/node_connects = list(node1_connect, node2_connect)
..(node_connects)
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/components/binary_devices/circulator.dm b/code/ATMOSPHERICS/components/binary_devices/circulator.dm
index f5da3152aae..1d76aa2bfbe 100644
--- a/code/ATMOSPHERICS/components/binary_devices/circulator.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/circulator.dm
@@ -12,14 +12,14 @@
var/last_pressure_delta = 0
- anchored = 1.0
+ anchored = 1
density = 1
/obj/machinery/atmospherics/components/binary/circulator/proc/return_transfer_air()
- var/datum/gas_mixture/air1 = airs[AIR1]
- var/datum/gas_mixture/air2 = airs[AIR2]
+ var/datum/gas_mixture/air1 = AIR1
+ var/datum/gas_mixture/air2 = AIR2
var/output_starting_pressure = air1.return_pressure()
var/input_starting_pressure = air2.return_pressure()
diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
index 9cecf78413f..bde761f802d 100644
--- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
@@ -35,15 +35,15 @@ Acts like a normal vent, but has an input AND output.
/obj/machinery/atmospherics/components/binary/dp_vent_pump/Destroy()
if(radio_controller)
radio_controller.remove_object(src, frequency)
- ..()
+ return ..()
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume
name = "large dual-port air vent"
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/New()
..()
- var/datum/gas_mixture/air1 = airs[AIR1]
- var/datum/gas_mixture/air2 = airs[AIR2]
+ var/datum/gas_mixture/air1 = AIR1
+ var/datum/gas_mixture/air2 = AIR2
air1.volume = 1000
air2.volume = 1000
@@ -66,8 +66,8 @@ Acts like a normal vent, but has an input AND output.
if(!on)
return 0
- var/datum/gas_mixture/air1 = airs[AIR1]
- var/datum/gas_mixture/air2 = airs[AIR2]
+ var/datum/gas_mixture/air1 = AIR1
+ var/datum/gas_mixture/air2 = AIR2
var/datum/gas_mixture/environment = loc.return_air()
var/environment_pressure = environment.return_pressure()
@@ -89,7 +89,7 @@ Acts like a normal vent, but has an input AND output.
loc.assume_air(removed)
air_update_turf()
- var/datum/pipeline/parent1 = parents[PARENT1]
+ var/datum/pipeline/parent1 = PARENT1
parent1.update = 1
else //external -> output
@@ -109,7 +109,7 @@ Acts like a normal vent, but has an input AND output.
air2.merge(removed)
air_update_turf()
- var/datum/pipeline/parent2 = parents[PARENT2]
+ var/datum/pipeline/parent2 = PARENT2
parent2.update = 1
return 1
diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
index d75d045a636..d927ffab88a 100644
--- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
@@ -25,7 +25,7 @@ Passive gate is similar to the regular pump except:
/obj/machinery/atmospherics/components/binary/passive_gate/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
+ return ..()
/obj/machinery/atmospherics/components/binary/passive_gate/update_icon_nopipes()
if(!on)
@@ -40,8 +40,8 @@ Passive gate is similar to the regular pump except:
if(!on)
return 0
- var/datum/gas_mixture/air1 = airs[AIR1]
- var/datum/gas_mixture/air2 = airs[AIR2]
+ var/datum/gas_mixture/air1 = AIR1
+ var/datum/gas_mixture/air2 = AIR2
var/output_starting_pressure = air2.return_pressure()
var/input_starting_pressure = air1.return_pressure()
diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm
index 73482b9c864..91467898b27 100644
--- a/code/ATMOSPHERICS/components/binary_devices/pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm
@@ -29,8 +29,9 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/components/binary/pump/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
-
+ if(radio_connection)
+ radio_connection = null
+ return ..()
/obj/machinery/atmospherics/components/binary/pump/on
on = 1
@@ -48,8 +49,8 @@ Thus, the two variables affect pump operation are set in New():
if(!on)
return 0
- var/datum/gas_mixture/air1 = airs[AIR1]
- var/datum/gas_mixture/air2 = airs[AIR2]
+ var/datum/gas_mixture/air1 = AIR1
+ var/datum/gas_mixture/air2 = AIR2
var/output_starting_pressure = air2.return_pressure()
diff --git a/code/ATMOSPHERICS/components/binary_devices/valve.dm b/code/ATMOSPHERICS/components/binary_devices/valve.dm
index 3239d3a6ec4..a99fa0df02b 100644
--- a/code/ATMOSPHERICS/components/binary_devices/valve.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/valve.dm
@@ -28,7 +28,7 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
open = 1
update_icon_nopipes()
update_parents()
- var/datum/pipeline/parent1 = parents[PARENT1]
+ var/datum/pipeline/parent1 = PARENT1
parent1.reconcile_air()
investigate_log("was opened by [usr ? key_name(usr) : "a remote signal"]", "atmos")
diff --git a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
index a87f2964480..010a10fb5de 100644
--- a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
@@ -29,7 +29,7 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/components/binary/volume_pump/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
+ return ..()
/obj/machinery/atmospherics/components/binary/volume_pump/on
on = 1
@@ -48,8 +48,8 @@ Thus, the two variables affect pump operation are set in New():
if(!on)
return 0
- var/datum/gas_mixture/air1 = airs[AIR1]
- var/datum/gas_mixture/air2 = airs[AIR2]
+ var/datum/gas_mixture/air1 = AIR1
+ var/datum/gas_mixture/air2 = AIR2
// Pump mechanism just won't do anything if the pressure is too high/too low
@@ -125,7 +125,7 @@ Thus, the two variables affect pump operation are set in New():
on = !on
if("set_transfer_rate" in signal.data)
- var/datum/gas_mixture/air1 = airs[AIR1]
+ var/datum/gas_mixture/air1 = AIR1
transfer_rate = Clamp(
text2num(signal.data["set_transfer_rate"]),
0,
diff --git a/code/ATMOSPHERICS/components/components_base.dm b/code/ATMOSPHERICS/components/components_base.dm
index 78bd351c9f4..4429f181721 100644
--- a/code/ATMOSPHERICS/components/components_base.dm
+++ b/code/ATMOSPHERICS/components/components_base.dm
@@ -3,50 +3,31 @@ So much of atmospherics.dm was used solely by components, so separating this mak
On top of that, now people can add component-speciic procs/vars if they want!
*/
-#define UNARY 1
-#define BINARY 2
-#define TRINARY 3
-
-#define AIR1 "a1"
-#define AIR2 "a2"
-#define AIR3 "a3"
-
-#define PARENT1 "p1"
-#define PARENT2 "p2"
-#define PARENT3 "p3"
-
-#define NODE1 "n1"
-#define NODE2 "n2"
-#define NODE3 "n3"
-
/obj/machinery/atmospherics/components/
- var/welded //Used on pumps and scrubbers
+ var/welded = 0 //Used on pumps and scrubbers
var/showpipe = 0
- var/device_type = 0//used for initialization stuff
- //UNARY = 1
- //BINARY = 2
- //TRINARY = 3
-
- var/list/obj/machinery/atmospherics/nodes = list()
var/list/datum/pipeline/parents = list()
var/list/datum/gas_mixture/airs = list()
/obj/machinery/atmospherics/components/New()
+ parents.len = device_type
+ airs.len = device_type
..()
- for(var/I = 1; I <= device_type; I++)
+
+ for(DEVICE_TYPE_LOOP)
var/datum/gas_mixture/A = new
A.volume = 200
- airs["a[I]"] = A
+ AIR_I = A
/*
Iconnery
*/
-/obj/machinery/atmospherics/components/proc/icon_addintact(var/obj/machinery/atmospherics/node, var/connected = 0)
+/obj/machinery/atmospherics/components/proc/icon_addintact(var/obj/machinery/atmospherics/node)
var/image/img = getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', "pipe_intact", get_dir(src,node), node.pipe_color)
underlays += img
- return connected | img.dir
+ return img.dir
/obj/machinery/atmospherics/components/proc/icon_addbroken(var/connected = 0)
var/unconnected = (~connected) & initialize_directions
@@ -57,18 +38,25 @@ Iconnery
/obj/machinery/atmospherics/components/proc/update_icon_nopipes()
return
-/obj/machinery/atmospherics/components/update_icon() //not working
+/obj/machinery/atmospherics/components/update_icon()
update_icon_nopipes()
underlays.Cut()
+
+ var/turf/T = loc
+ if(level == 2 || !T.intact)
+ showpipe = 1
+ else
+ showpipe = 0
+
if(!showpipe)
return //no need to update the pipes if they aren't showing
var/connected = 0
- for(var/I = 1; I <= device_type; I++) //adds intact pieces
- if(nodes["n[I]"])
- connected = icon_addintact(nodes["n[I]"], connected)
+ for(DEVICE_TYPE_LOOP) //adds intact pieces
+ if(NODE_I)
+ connected |= icon_addintact(NODE_I)
icon_addbroken(connected) //adds broken pieces
@@ -76,84 +64,53 @@ Iconnery
/*
Pipenet stuff; housekeeping
*/
-/obj/machinery/atmospherics/components/Destroy()
- for(var/I = 1; I <= device_type; I++)
- var/obj/machinery/atmospherics/N = nodes["n[I]"]
- if(N)
- N.disconnect(src)
- nodes["n[I]"] = null
- nullifyPipenet(parents["p[I]"])
- ..()
-/obj/machinery/atmospherics/components/atmosinit(var/list/node_connects)
- for(var/I = 1; I <= device_type; I++)
- for(var/obj/machinery/atmospherics/target in get_step(src,node_connects[I]))
- if(target.initialize_directions & get_dir(target,src))
- nodes["n[I]"] = target
- break
- if(level == 2)
- showpipe = 1
- update_icon()
+/obj/machinery/atmospherics/components/nullifyNode(I)
+ ..()
+ if(NODE_I)
+ nullifyPipenet(PARENT_I)
+ qdel(AIR_I)
+ AIR_I = null
/obj/machinery/atmospherics/components/construction()
..()
update_parents()
/obj/machinery/atmospherics/components/build_network()
- for(var/I = 1; I <= device_type; I++)
- if(!parents["p[I]"])
- parents["p[I]"] = new /datum/pipeline()
- var/datum/pipeline/P = parents["p[I]"]
+ for(DEVICE_TYPE_LOOP)
+ if(!PARENT_I)
+ PARENT_I = new /datum/pipeline()
+ var/datum/pipeline/P = PARENT_I
P.build_pipeline(src)
-/obj/machinery/atmospherics/components/disconnect(obj/machinery/atmospherics/reference)
- for(var/I = 1; I <= device_type; I++)
- if(reference == nodes["n[I]"])
- if(istype(nodes["n[I]"], /obj/machinery/atmospherics/pipe))
- qdel(parents["p[I]"])
- nodes["n[I]"] = null
- break
- update_icon()
-
-/obj/machinery/atmospherics/components/nullifyPipenet(datum/pipeline/reference)
- ..()
- for(var/I = 1; I <= device_type; I++)
- if(reference == parents["p[I]"])
- var/datum/pipeline/P = parents["p[I]"]
- P.other_airs -= airs["a[I]"]
- parents["p[I]"] = null
+/obj/machinery/atmospherics/components/proc/nullifyPipenet(datum/pipeline/reference)
+ var/I = parents.Find(reference)
+ reference.other_airs -= AIR_I
+ reference.other_atmosmch -= src
+ PARENT_I = null
/obj/machinery/atmospherics/components/returnPipenetAir(datum/pipeline/reference)
- for(var/I = 1; I <= device_type; I++)
- if(reference == parents["p[I]"])
- return airs["a[I]"]
+ var/I = parents.Find(reference)
+ return AIR_I
/obj/machinery/atmospherics/components/pipeline_expansion(datum/pipeline/reference)
if(reference)
- for(var/I = 1; I <= device_type; I++)
- if(parents["p[I]"] == reference)
- return list(nodes["n[I]"])
+ var/I = parents.Find(reference)
+ return list(NODE_I)
else
- var/list/obj/machinery/atmospherics/return_nodes = list()
- for(var/I = 1; I <= device_type; I++)
- return_nodes += nodes["n[I]"]
- return return_nodes
+ return ..()
/obj/machinery/atmospherics/components/setPipenet(datum/pipeline/reference, obj/machinery/atmospherics/A)
- for(var/I = 1; I <= device_type; I++)
- if(A == nodes["n[I]"])
- parents["p[I]"] = reference
- break
+ var/I = nodes.Find(A)
+ PARENT_I = reference
-/obj/machinery/atmospherics/components/returnPipenet(obj/machinery/atmospherics/A = nodes[NODE1]) //returns PARENT1 if called without argument
- for(var/I = 1; I <= device_type; I++)
- if(A == nodes["n[I]"])
- return parents["p[I]"]
+/obj/machinery/atmospherics/components/returnPipenet(obj/machinery/atmospherics/A = NODE1) //returns PARENT1 if called without argument
+ var/I = nodes.Find(A)
+ return PARENT_I
/obj/machinery/atmospherics/components/replacePipenet(datum/pipeline/Old, datum/pipeline/New)
- for(var/I = 1; I <= device_type; I++)
- if(parents["p[I]"] == Old)
- parents["p[I]"] = New
+ var/I = parents.Find(Old)
+ PARENT_I = New
/obj/machinery/atmospherics/components/unsafe_pressure_release(var/mob/user, var/pressures)
..()
@@ -164,15 +121,15 @@ Pipenet stuff; housekeeping
var/datum/gas_mixture/environment = T.return_air()
var/lost = null
var/times_lost = 0
- for(var/I = 1; I <= device_type; I++)
- var/datum/gas_mixture/air = airs["a[I]"]
+ for(DEVICE_TYPE_LOOP)
+ var/datum/gas_mixture/air = AIR_I
lost += pressures*environment.volume/(air.temperature * R_IDEAL_GAS_EQUATION)
times_lost++
var/shared_loss = lost/times_lost
var/datum/gas_mixture/to_release
- for(var/I = 1; I <= device_type; I++)
- var/datum/gas_mixture/air = airs["a[I]"]
+ for(DEVICE_TYPE_LOOP)
+ var/datum/gas_mixture/air = AIR_I
if(!to_release)
to_release = air.remove(shared_loss)
continue
@@ -195,6 +152,6 @@ Helpers
*/
/obj/machinery/atmospherics/components/proc/update_parents()
- for(var/I = 1; I <= device_type; I++)
- var/datum/pipeline/parent = parents["p[I]"]
+ for(DEVICE_TYPE_LOOP)
+ var/datum/pipeline/parent = PARENT_I
parent.update = 1
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
index a56bdd14c0c..b2464c2a129 100644
--- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
@@ -47,7 +47,7 @@ Filter types:
/obj/machinery/atmospherics/components/trinary/filter/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
+ return ..()
/obj/machinery/atmospherics/components/trinary/filter/update_icon()
overlays.Cut()
@@ -62,7 +62,7 @@ Filter types:
/obj/machinery/atmospherics/components/trinary/filter/update_icon_nopipes()
- if(!(stat & NOPOWER) && on && nodes[NODE1] && nodes[NODE2] && nodes[NODE3])
+ if(!(stat & NOPOWER) && on && NODE1 && NODE2 && NODE3)
icon_state = "filter_on[flipped?"_f":""]"
return
@@ -80,12 +80,12 @@ Filter types:
..()
if(!on)
return 0
- if(!(nodes[NODE1] && nodes[NODE2] && nodes[NODE3]))
+ if(!(NODE1 && NODE2 && NODE3))
return 0
- var/datum/gas_mixture/air1 = airs[AIR1]
- var/datum/gas_mixture/air2 = airs[AIR2]
- var/datum/gas_mixture/air3 = airs[AIR3]
+ var/datum/gas_mixture/air1 = AIR1
+ var/datum/gas_mixture/air2 = AIR2
+ var/datum/gas_mixture/air3 = AIR3
var/output_starting_pressure = air3.return_pressure()
diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
index 8b8850744ec..14c3c47adf7 100644
--- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
@@ -29,10 +29,10 @@
overlays += getpipeimage('icons/obj/atmospherics/components/trinary_devices.dmi', "cap", direction, node.pipe_color)
continue
overlays += getpipeimage('icons/obj/atmospherics/components/trinary_devices.dmi', "cap", direction)
- ..()
+ return ..()
/obj/machinery/atmospherics/components/trinary/mixer/update_icon_nopipes()
- if(!(stat & NOPOWER) && on && nodes[NODE1] && nodes[NODE2] && nodes[NODE3])
+ if(!(stat & NOPOWER) && on && NODE1 && NODE2 && NODE3)
icon_state = "mixer_on[flipped?"_f":""]"
return
@@ -48,20 +48,20 @@
/obj/machinery/atmospherics/components/trinary/mixer/New()
..()
- var/datum/gas_mixture/air3 = airs[AIR3]
+ var/datum/gas_mixture/air3 = AIR3
air3.volume = 300
- airs[AIR3] = air3
+ AIR3 = air3
/obj/machinery/atmospherics/components/trinary/mixer/process_atmos()
..()
if(!on)
return 0
- if(!(nodes[NODE1] && nodes[NODE2] && nodes[NODE3]))
+ if(!(NODE1 && NODE2 && NODE3))
return 0
- var/datum/gas_mixture/air1 = airs[AIR1]
- var/datum/gas_mixture/air2 = airs[AIR2]
- var/datum/gas_mixture/air3 = airs[AIR3]
+ var/datum/gas_mixture/air1 = AIR1
+ var/datum/gas_mixture/air2 = AIR2
+ var/datum/gas_mixture/air3 = AIR3
var/output_starting_pressure = air3.return_pressure()
@@ -107,14 +107,14 @@
air3.merge(removed2)
if(transfer_moles1)
- var/datum/pipeline/parent1 = parents[PARENT1]
+ var/datum/pipeline/parent1 = PARENT1
parent1.update = 1
if(transfer_moles2)
- var/datum/pipeline/parent2 = parents[PARENT2]
+ var/datum/pipeline/parent2 = PARENT2
parent2.update = 1
- var/datum/pipeline/parent3 = parents[PARENT3]
+ var/datum/pipeline/parent3 = PARENT3
parent3.update = 1
return 1
diff --git a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
index cec9c7ed27b..d2c37ec30e0 100644
--- a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
@@ -43,7 +43,5 @@ Housekeeping and pipe network stuff
node1_connect = turn(node1_connect, 180)
node3_connect = turn(node3_connect, 180)
- var/list/node_connects = new/list()
-
- node_connects.Add(node1_connect, node2_connect, node3_connect)
+ var/list/node_connects = list(node1_connect, node2_connect, node3_connect)
..(node_connects)
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/components/unary_devices/Freezer.dm b/code/ATMOSPHERICS/components/unary_devices/Freezer.dm
index b91d8a74dbb..59994128b55 100644
--- a/code/ATMOSPHERICS/components/unary_devices/Freezer.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/Freezer.dm
@@ -4,7 +4,7 @@
icon_state = "freezer"
density = 1
var/min_temperature = 0
- anchored = 1.0
+ anchored = 1
use_power = 1
current_heat_capacity = 1000
@@ -69,7 +69,7 @@
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/interact(mob/user)
if(stat & (NOPOWER|BROKEN))
return
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
user.set_machine(src)
var/temp_text = ""
if(air_contents.temperature > (T0C - 20))
@@ -128,7 +128,7 @@
icon_state = "heater"
density = 1
var/max_temperature = 0
- anchored = 1.0
+ anchored = 1
current_heat_capacity = 1000
@@ -194,7 +194,7 @@
return interact(user)
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/interact(mob/user)
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
if(stat & (NOPOWER|BROKEN))
return
diff --git a/code/ATMOSPHERICS/components/unary_devices/cold_sink.dm b/code/ATMOSPHERICS/components/unary_devices/cold_sink.dm
index 7750a7c7b14..65419798bfd 100644
--- a/code/ATMOSPHERICS/components/unary_devices/cold_sink.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/cold_sink.dm
@@ -16,7 +16,7 @@
if(showpipe)
overlays += getpipeimage('icons/obj/atmospherics/components/unary_devices.dmi', "scrub_cap", initialize_directions) //scrub_cap works for now
- if(!nodes[NODE1] || !on || stat & (NOPOWER|BROKEN))
+ if(!NODE1 || !on || stat & (NOPOWER|BROKEN))
icon_state = "cold_off"
return
@@ -27,7 +27,7 @@
..()
if(!on)
return 0
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
var/air_heat_capacity = air_contents.heat_capacity()
var/combined_heat_capacity = current_heat_capacity + air_heat_capacity
diff --git a/code/ATMOSPHERICS/components/unary_devices/cryo.dm b/code/ATMOSPHERICS/components/unary_devices/cryo.dm
index 87eb0e606e8..5edaa823b99 100644
--- a/code/ATMOSPHERICS/components/unary_devices/cryo.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/cryo.dm
@@ -3,7 +3,7 @@
icon = 'icons/obj/cryogenics.dmi'
icon_state = "cell-off"
density = 1
- anchored = 1.0
+ anchored = 1
layer = 4
var/on = 0
@@ -44,10 +44,10 @@
if(beaker)
beaker.loc = get_step(loc, SOUTH) //Beaker is carefully ejected from the wreckage of the cryotube
beaker = null
- ..()
+ return ..()
/obj/machinery/atmospherics/components/unary/cryo_cell/process_atmos()
..()
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
if(air_contents)
temperature_archived = air_contents.temperature
@@ -62,14 +62,14 @@
on = 0
open_machine()
playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
- if(!nodes[NODE1] || !is_operational())
+ if(!NODE1 || !is_operational())
return
if(!on)
updateDialog()
return
- if(airs[AIR1])
+ if(AIR1)
if (occupant)
process_occupant()
expel_gas()
@@ -145,7 +145,7 @@
/obj/machinery/atmospherics/components/unary/cryo_cell/get_ui_data()
// this is the data which will be sent to the ui
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
var/data = list()
data["isOperating"] = on
@@ -289,7 +289,7 @@
update_icon()
/obj/machinery/atmospherics/components/unary/cryo_cell/proc/process_occupant()
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
if(air_contents.total_moles() < 10)
return
if(occupant)
@@ -314,14 +314,14 @@
occupant.heal_organ_damage(heal_brute,heal_fire)
if(beaker && next_trans == 0)
beaker.reagents.trans_to(occupant, 1, 10)
- beaker.reagents.reaction(occupant)
+ beaker.reagents.reaction(occupant, VAPOR)
next_trans++
if(next_trans == 10)
next_trans = 0
/obj/machinery/atmospherics/components/unary/cryo_cell/proc/heat_gas_contents()
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
if(air_contents.total_moles() < 1)
return
@@ -332,7 +332,7 @@
air_contents.temperature = combined_energy/combined_heat_capacity
/obj/machinery/atmospherics/components/unary/cryo_cell/proc/expel_gas()
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
if(air_contents.total_moles() < 1)
return
diff --git a/code/ATMOSPHERICS/components/unary_devices/generator_input.dm b/code/ATMOSPHERICS/components/unary_devices/generator_input.dm
index 20d1474ffd3..15ae3eb88f9 100644
--- a/code/ATMOSPHERICS/components/unary_devices/generator_input.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/generator_input.dm
@@ -9,7 +9,7 @@
var/update_cycle
/obj/machinery/atmospherics/components/unary/generator_input/update_icon()
- if(nodes[NODE1])
+ if(NODE1)
icon_state = "intact"
else
icon_state = "exposed"
@@ -17,4 +17,4 @@
return
/obj/machinery/atmospherics/components/unary/generator_input/proc/return_exchange_air()
- return airs[AIR1]
+ return AIR1
diff --git a/code/ATMOSPHERICS/components/unary_devices/heat_exchanger.dm b/code/ATMOSPHERICS/components/unary_devices/heat_exchanger.dm
index 21746bc4e97..1b400dad2bb 100644
--- a/code/ATMOSPHERICS/components/unary_devices/heat_exchanger.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/heat_exchanger.dm
@@ -11,9 +11,9 @@
var/update_cycle
/obj/machinery/atmospherics/components/unary/heat_exchanger/update_icon()
- if(nodes[NODE1])
+ if(NODE1)
icon_state = "he_intact"
- var/obj/machinery/atmospherics/node = nodes[NODE1]
+ var/obj/machinery/atmospherics/node = NODE1
color = node.color
else
icon_state = "he_exposed"
@@ -43,8 +43,8 @@
update_cycle = SSair.times_fired
partner.update_cycle = SSair.times_fired
- var/datum/gas_mixture/air_contents = airs[AIR1]
- var/datum/gas_mixture/partner_air_contents = partner.airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
+ var/datum/gas_mixture/partner_air_contents = partner.AIR1
var/air_heat_capacity = air_contents.heat_capacity()
var/other_air_heat_capacity = partner_air_contents.heat_capacity()
diff --git a/code/ATMOSPHERICS/components/unary_devices/heat_source.dm b/code/ATMOSPHERICS/components/unary_devices/heat_source.dm
index ceba342a5fa..b08a4a214a7 100644
--- a/code/ATMOSPHERICS/components/unary_devices/heat_source.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/heat_source.dm
@@ -17,7 +17,7 @@
if(showpipe)
overlays += getpipeimage('icons/obj/atmospherics/components/unary_devices.dmi', "scrub_cap", initialize_directions) //scrub_cap works for now
- if(!nodes[NODE1] || !on || stat & (NOPOWER|BROKEN))
+ if(!NODE1 || !on || stat & (NOPOWER|BROKEN))
icon_state = "cold_off"
return
@@ -29,7 +29,7 @@
if(!on)
return 0
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
var/air_heat_capacity = air_contents.heat_capacity()
var/combined_heat_capacity = current_heat_capacity + air_heat_capacity
diff --git a/code/ATMOSPHERICS/components/unary_devices/outlet_injector.dm b/code/ATMOSPHERICS/components/unary_devices/outlet_injector.dm
index 10ecdf726d9..df9af8f6cfc 100644
--- a/code/ATMOSPHERICS/components/unary_devices/outlet_injector.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/outlet_injector.dm
@@ -19,13 +19,13 @@
/obj/machinery/atmospherics/components/unary/outlet_injector/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
+ return ..()
/obj/machinery/atmospherics/components/unary/outlet_injector/on
on = 1
/obj/machinery/atmospherics/components/unary/outlet_injector/update_icon_nopipes()
- if(!nodes[NODE1] || !on || stat & (NOPOWER|BROKEN))
+ if(!NODE1 || !on || stat & (NOPOWER|BROKEN))
icon_state = "inje_off"
return
@@ -45,7 +45,7 @@
if(!on || stat & NOPOWER)
return 0
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
if(air_contents.temperature > 0)
var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
@@ -63,7 +63,7 @@
if(on || injecting)
return 0
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
injecting = 1
@@ -126,7 +126,7 @@
if("set_volume_rate" in signal.data)
var/number = text2num(signal.data["set_volume_rate"])
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
volume_rate = Clamp(number, 0, air_contents.volume)
if("status" in signal.data)
diff --git a/code/ATMOSPHERICS/components/unary_devices/oxygen_generator.dm b/code/ATMOSPHERICS/components/unary_devices/oxygen_generator.dm
index d8c1d69e200..0c0bee0b275 100644
--- a/code/ATMOSPHERICS/components/unary_devices/oxygen_generator.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/oxygen_generator.dm
@@ -18,7 +18,7 @@
if(showpipe)
overlays += getpipeimage('icons/obj/atmospherics/components/unary_devices.dmi', "scrub_cap", initialize_directions) //it works for now
- if(!nodes[NODE1] || !on || stat & BROKEN)
+ if(!NODE1 || !on || stat & BROKEN)
icon_state = "o2gen_off"
return
@@ -27,16 +27,16 @@
/obj/machinery/atmospherics/components/unary/oxygen_generator/New()
..()
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
air_contents.volume = 50
- airs[AIR1] = air_contents
+ AIR1 = air_contents
/obj/machinery/atmospherics/components/unary/oxygen_generator/process_atmos()
..()
if(!on)
return 0
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
var/total_moles = air_contents.total_moles()
diff --git a/code/ATMOSPHERICS/components/unary_devices/portables_connector.dm b/code/ATMOSPHERICS/components/unary_devices/portables_connector.dm
index 9446c396078..d9e649c7a13 100644
--- a/code/ATMOSPHERICS/components/unary_devices/portables_connector.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/portables_connector.dm
@@ -19,7 +19,7 @@
/obj/machinery/atmospherics/components/unary/portables_connector/Destroy()
if(connected_device)
connected_device.disconnect()
- ..()
+ return ..()
/obj/machinery/atmospherics/components/unary/portables_connector/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/wrench))
diff --git a/code/ATMOSPHERICS/components/unary_devices/tank.dm b/code/ATMOSPHERICS/components/unary_devices/tank.dm
index 8f8f6b9e831..44ab5048460 100644
--- a/code/ATMOSPHERICS/components/unary_devices/tank.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/tank.dm
@@ -1,3 +1,4 @@
+#define AIR_CONTENTS (25*ONE_ATMOSPHERE)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
/obj/machinery/atmospherics/components/unary/tank
icon = 'icons/obj/atmospherics/pipes/pressure_tank.dmi'
icon_state = "generic"
@@ -6,15 +7,19 @@
var/volume = 10000 //in liters, 1 meters by 1 meters by 2 meters
density = 1
+/obj/machinery/atmospherics/components/unary/tank/New()
+ ..()
+ var/datum/gas_mixture/air_contents = AIR1
+ air_contents.volume = volume
+ air_contents.temperature = T20C
+
/obj/machinery/atmospherics/components/unary/tank/carbon_dioxide
name = "pressure tank (Carbon Dioxide)"
/obj/machinery/atmospherics/components/unary/tank/carbon_dioxide/New()
..()
- var/datum/gas_mixture/air_contents = airs[AIR1]
- air_contents.volume = volume
- air_contents.temperature = T20C
- air_contents.carbon_dioxide = (25*ONE_ATMOSPHERE)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
+ var/datum/gas_mixture/air_contents = AIR1
+ air_contents.carbon_dioxide = AIR_CONTENTS
/obj/machinery/atmospherics/components/unary/tank/toxins
icon_state = "orange"
@@ -22,10 +27,8 @@
/obj/machinery/atmospherics/components/unary/tank/toxins/New()
..()
- var/datum/gas_mixture/air_contents = airs[AIR1]
- air_contents.volume = volume
- air_contents.temperature = T20C
- air_contents.toxins = (25*ONE_ATMOSPHERE)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
+ var/datum/gas_mixture/air_contents = AIR1
+ air_contents.toxins = AIR_CONTENTS
/obj/machinery/atmospherics/components/unary/tank/oxygen_agent_b
icon_state = "orange_2"
@@ -33,11 +36,9 @@
/obj/machinery/atmospherics/components/unary/tank/oxygen_agent_b/New()
..()
- var/datum/gas_mixture/air_contents = airs[AIR1]
- air_contents.volume = volume
- air_contents.temperature = T0C
+ var/datum/gas_mixture/air_contents = AIR1
var/datum/gas/oxygen_agent_b/trace_gas = new
- trace_gas.moles = (25*ONE_ATMOSPHERE)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
+ trace_gas.moles = AIR_CONTENTS
air_contents.trace_gases += trace_gas
/obj/machinery/atmospherics/components/unary/tank/oxygen
@@ -46,10 +47,8 @@
/obj/machinery/atmospherics/components/unary/tank/oxygen/New()
..()
- var/datum/gas_mixture/air_contents = airs[AIR1]
- air_contents.volume = volume
- air_contents.temperature = T20C
- air_contents.oxygen = (25*ONE_ATMOSPHERE)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
+ var/datum/gas_mixture/air_contents = AIR1
+ air_contents.oxygen = AIR_CONTENTS
/obj/machinery/atmospherics/components/unary/tank/nitrogen
icon_state = "red"
@@ -57,10 +56,8 @@
/obj/machinery/atmospherics/components/unary/tank/nitrogen/New()
..()
- var/datum/gas_mixture/air_contents = airs[AIR1]
- air_contents.volume = volume
- air_contents.temperature = T20C
- air_contents.nitrogen = (25*ONE_ATMOSPHERE)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
+ var/datum/gas_mixture/air_contents = AIR1
+ air_contents.nitrogen = AIR_CONTENTS
/obj/machinery/atmospherics/components/unary/tank/air
icon_state = "grey"
@@ -68,8 +65,6 @@
/obj/machinery/atmospherics/components/unary/tank/air/New()
..()
- var/datum/gas_mixture/air_contents = airs[AIR1]
- air_contents.volume = volume
- air_contents.temperature = T20C
- air_contents.oxygen = (25*ONE_ATMOSPHERE*O2STANDARD)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
- air_contents.nitrogen = (25*ONE_ATMOSPHERE*N2STANDARD)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
\ No newline at end of file
+ var/datum/gas_mixture/air_contents = AIR1
+ air_contents.oxygen = AIR_CONTENTS * 0.2
+ air_contents.nitrogen = AIR_CONTENTS * 0.8
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/components/unary_devices/unary_base.dm b/code/ATMOSPHERICS/components/unary_devices/unary_base.dm
index 96b99f52fd1..2e018e313b7 100644
--- a/code/ATMOSPHERICS/components/unary_devices/unary_base.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/unary_base.dm
@@ -12,32 +12,22 @@
Iconnery
*/
-/obj/machinery/atmospherics/components/unary/hide(var/intact)
- showpipe = !intact
+/obj/machinery/atmospherics/components/unary/hide(intact)
update_icon()
..(intact)
-/*
-Housekeeping and pipe network stuff below
-*/
-
-/obj/machinery/atmospherics/components/unary/atmosinit()
- var/list/node_connects = new/list()
- node_connects.Add(dir)
- ..(node_connects)
-
/obj/machinery/atmospherics/components/unary/default_change_direction_wrench(mob/user, obj/item/weapon/wrench/W)
if(!..())
return
SetInitDirections()
- var/obj/machinery/atmospherics/node = nodes[NODE1]
+ var/obj/machinery/atmospherics/node = NODE1
if(node)
node.disconnect(src)
node = null
- nullifyPipenet(parents[PARENT1])
+ nullifyPipenet(PARENT1)
atmosinit()
- node = nodes[NODE1]
+ node = NODE1
if(node)
node.atmosinit()
node.addMember(src)
diff --git a/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm b/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm
index 7d574f302d6..cc253759f72 100644
--- a/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm
@@ -2,6 +2,9 @@
#define INT_BOUND 2
#define NO_BOUND 3
+#define SIPHONING 0
+#define RELEASING 1
+
/obj/machinery/atmospherics/components/unary/vent_pump
icon_state = "vent_map"
@@ -19,12 +22,12 @@
var/id_tag = null
var/on = 0
- var/pump_direction = 1 //0 = siphoning, 1 = releasing
+ var/pump_direction = RELEASING
var/external_pressure_bound = ONE_ATMOSPHERE
var/internal_pressure_bound = 0
- var/pressure_checks = 1
+ var/pressure_checks = EXT_BOUND
//EXT_BOUND: Do not pass external_pressure_bound
//INT_BOUND: Do not pass internal_pressure_bound
//NO_BOUND: Do not pass either
@@ -40,7 +43,7 @@
icon_state = "vent_out"
/obj/machinery/atmospherics/components/unary/vent_pump/siphon
- pump_direction = 0
+ pump_direction = SIPHONING
/obj/machinery/atmospherics/components/unary/vent_pump/siphon/on
on = 1
@@ -59,7 +62,12 @@
/obj/machinery/atmospherics/components/unary/vent_pump/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
+ radio_connection = null
+ if(initial_loc)
+ initial_loc.air_vent_info -= id_tag
+ initial_loc.air_vent_names -= id_tag
+ initial_loc = null
+ return ..()
/obj/machinery/atmospherics/components/unary/vent_pump/high_volume
name = "large air vent"
@@ -67,7 +75,7 @@
/obj/machinery/atmospherics/components/unary/vent_pump/high_volume/New()
..()
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
air_contents.volume = 1000
/obj/machinery/atmospherics/components/unary/vent_pump/update_icon_nopipes()
@@ -79,20 +87,20 @@
icon_state = "vent_welded"
return
- if(!nodes[NODE1] || !on || stat & (NOPOWER|BROKEN))
+ if(!NODE1 || !on || stat & (NOPOWER|BROKEN))
icon_state = "vent_off"
return
- if(pump_direction)
+ if(pump_direction & RELEASING)
icon_state = "vent_out"
- else
+ else //pump_direction == SIPHONING
icon_state = "vent_in"
/obj/machinery/atmospherics/components/unary/vent_pump/process_atmos()
..()
if(stat & (NOPOWER|BROKEN))
return
- if (!nodes[NODE1])
+ if (!NODE1)
on = 0
//broadcast_status() // from now air alarm/control computer should request update purposely --rastaf0
if(!on)
@@ -101,11 +109,11 @@
if(welded)
return 0
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
var/datum/gas_mixture/environment = loc.return_air()
var/environment_pressure = environment.return_pressure()
- if(pump_direction) //internal -> external
+ if(pump_direction & RELEASING) //internal -> external
var/pressure_delta = 10000
if(pressure_checks&EXT_BOUND)
@@ -201,11 +209,11 @@
if("purge" in signal.data)
pressure_checks &= ~EXT_BOUND
- pump_direction = 0
+ pump_direction = SIPHONING
if("stabalize" in signal.data)
pressure_checks |= EXT_BOUND
- pump_direction = 1
+ pump_direction = RELEASING
if("power" in signal.data)
on = text2num(signal.data["power"])
@@ -310,3 +318,10 @@
/obj/machinery/atmospherics/components/unary/vent_pump/can_crawl_through()
return !welded
+
+#undef INT_BOUND
+#undef EXT_BOUND
+#undef NO_BOUND
+
+#undef SIPHONING
+#undef RELEASING
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm
index 691835ed4cc..ac52a1d1178 100644
--- a/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm
+++ b/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm
@@ -1,3 +1,6 @@
+#define SIPHONING 0
+#define SCRUBBING 1
+
/obj/machinery/atmospherics/components/unary/vent_scrubber
icon_state = "scrub_map"
@@ -22,7 +25,7 @@
var/list/turf/simulated/adjacent_turfs = list()
var/on = 0
- var/scrubbing = 1 //0 = siphoning, 1 = scrubbing
+ var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing
var/scrub_CO2 = 1
var/scrub_Toxins = 0
var/scrub_N2O = 0
@@ -48,10 +51,14 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
+ radio_connection = null
if(initial_loc)
initial_loc.air_scrub_info -= id_tag
initial_loc.air_scrub_names -= id_tag
- ..()
+ initial_loc = null
+ for(var/I in adjacent_turfs)
+ I = null
+ return ..()
/obj/machinery/atmospherics/components/unary/vent_scrubber/auto_use_power()
if(!powered(power_channel))
return 0
@@ -62,14 +69,14 @@
var/amount = idle_power_usage
- if (scrubbing)
+ if(scrubbing & SCRUBBING)
if (scrub_CO2)
amount += idle_power_usage
if (scrub_Toxins)
amount += idle_power_usage
if (scrub_N2O)
amount += idle_power_usage
- else
+ else //scrubbing == SIPHONING
amount = active_power_usage
if (widenet)
@@ -86,13 +93,13 @@
icon_state = "scrub_welded"
return
- if(!nodes[NODE1] || !on || stat & (NOPOWER|BROKEN))
+ if(!NODE1 || !on || stat & (NOPOWER|BROKEN))
icon_state = "scrub_off"
return
- if(scrubbing)
+ if(scrubbing & SCRUBBING)
icon_state = "scrub_on"
- else
+ else //scrubbing == SIPHONING
icon_state = "scrub_purge"
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/set_frequency(new_frequency)
@@ -142,7 +149,7 @@
..()
if(stat & (NOPOWER|BROKEN))
return
- if (!nodes[NODE1])
+ if (!NODE1)
on = 0
//broadcast_status()
if(!on || welded)
@@ -159,9 +166,9 @@
return 0
var/datum/gas_mixture/environment = tile.return_air()
- var/datum/gas_mixture/air_contents = airs[AIR1]
+ var/datum/gas_mixture/air_contents = AIR1
- if(scrubbing)
+ if(scrubbing & SCRUBBING)
if((environment.toxins>0) || (environment.carbon_dioxide>0) || (environment.trace_gases.len>0))
var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles()
@@ -312,3 +319,6 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_crawl_through()
return !welded
+
+#undef SIPHONING
+#undef SCRUBBING
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm
index cf55d774602..b4547824db6 100644
--- a/code/ATMOSPHERICS/datum_pipeline.dm
+++ b/code/ATMOSPHERICS/datum_pipeline.dm
@@ -18,7 +18,7 @@
P.parent = null
for(var/obj/machinery/atmospherics/components/C in other_atmosmch)
C.nullifyPipenet(src)
- ..()
+ return ..()
/datum/pipeline/process()
if(update)
@@ -185,6 +185,7 @@ var/pipenetwarnings = 10
air.temperature += self_temperature_delta
modeled_location.air.temperature += sharer_temperature_delta
+ modeled_location.air_update_turf()
else
@@ -208,8 +209,8 @@ var/pipenetwarnings = 10
GL += P.other_airs
for(var/obj/machinery/atmospherics/components/binary/valve/V in P.other_atmosmch)
if(V.open)
- PL |= V.parents["p1"]
- PL |= V.parents["p2"]
+ PL |= V.PARENT1
+ PL |= V.PARENT2
for(var/obj/machinery/atmospherics/components/unary/portables_connector/C in P.other_atmosmch)
if(C.connected_device)
GL += C.portableConnectorReturnAir()
@@ -266,144 +267,4 @@ var/pipenetwarnings = 10
corresponding = new trace_gas.type()
G.trace_gases += corresponding
- corresponding.moles = trace_gas.moles*G.volume/total_volume
-
-
-/*
-/datum/pipeline/proc/mingle_with_turf(turf/simulated/target, mingle_volume)
- var/datum/gas_mixture/air_sample = air.remove_ratio(mingle_volume/air.volume)
- air_sample.volume = mingle_volume
-
- var/datum/gas_mixture/turf_air = target.return_air()
-
- equalize_gases(list(air_sample, turf_air))
- air.merge(air_sample)
- //turf_air already modified by equalize_gases()
-
- if(istype(target))
- if(target.air)
- if(target.air.check_tile_graphic())
- target.update_visuals(target.air)
- update = 1
-
-/datum/pipeline/proc/reconcile_air()
- //Perfectly equalize all gases members instantly
-
- //Calculate totals from individual components
- var/total_thermal_energy = 0
- var/total_heat_capacity = 0
- var/datum/gas_mixture/air_transient = new()
- var/list/gases = list(air)
- gases.Add(other_airs)
- for(var/datum/gas_mixture/gas in gases)
- air_transient.volume += gas.volume
- total_thermal_energy += gas.thermal_energy()
- total_heat_capacity += gas.heat_capacity()
-
- air_transient.oxygen += gas.oxygen
- air_transient.nitrogen += gas.nitrogen
- air_transient.toxins += gas.toxins
- air_transient.carbon_dioxide += gas.carbon_dioxide
-
- if(gas.trace_gases.len)
- for(var/datum/gas/trace_gas in gas.trace_gases)
- var/datum/gas/corresponding = locate(trace_gas.type) in air_transient.trace_gases
- if(!corresponding)
- corresponding = new trace_gas.type()
- air_transient.trace_gases += corresponding
-
- corresponding.moles += trace_gas.moles
-
- if(air_transient.volume > 0)
-
- if(total_heat_capacity > 0)
- air_transient.temperature = total_thermal_energy/total_heat_capacity
-
- //Allow air mixture to react
- if(air_transient.react())
- update = 1
-
- else
- air_transient.temperature = 0
-
- //Update individual gas_mixtures by volume ratio
- for(var/datum/gas_mixture/gas in gases)
- gas.oxygen = air_transient.oxygen*gas.volume/air_transient.volume
- gas.nitrogen = air_transient.nitrogen*gas.volume/air_transient.volume
- gas.toxins = air_transient.toxins*gas.volume/air_transient.volume
- gas.carbon_dioxide = air_transient.carbon_dioxide*gas.volume/air_transient.volume
-
- gas.temperature = air_transient.temperature
-
- if(air_transient.trace_gases.len)
- for(var/datum/gas/trace_gas in air_transient.trace_gases)
- var/datum/gas/corresponding = locate(trace_gas.type) in gas.trace_gases
- if(!corresponding)
- corresponding = new trace_gas.type()
- gas.trace_gases += corresponding
-
- corresponding.moles = trace_gas.moles*gas.volume/air_transient.volume
- return 1
-
-/proc/equalize_gases(datum/gas_mixture/list/gases)
- //Perfectly equalize all gases members instantly
-
- //Calculate totals from individual components
- var/total_volume = 0
- var/total_thermal_energy = 0
- var/total_heat_capacity = 0
-
- var/total_oxygen = 0
- var/total_nitrogen = 0
- var/total_toxins = 0
- var/total_carbon_dioxide = 0
-
- var/list/total_trace_gases = list()
-
- for(var/datum/gas_mixture/gas in gases)
- total_volume += gas.volume
- total_thermal_energy += gas.thermal_energy()
- total_heat_capacity += gas.heat_capacity()
-
- total_oxygen += gas.oxygen
- total_nitrogen += gas.nitrogen
- total_toxins += gas.toxins
- total_carbon_dioxide += gas.carbon_dioxide
-
- if(gas.trace_gases.len)
- for(var/datum/gas/trace_gas in gas.trace_gases)
- var/datum/gas/corresponding = locate(trace_gas.type) in total_trace_gases
- if(!corresponding)
- corresponding = new trace_gas.type()
- total_trace_gases += corresponding
-
- corresponding.moles += trace_gas.moles
-
- if(total_volume > 0)
-
- //Calculate temperature
- var/temperature = 0
-
- if(total_heat_capacity > 0)
- temperature = total_thermal_energy/total_heat_capacity
-
- //Update individual gas_mixtures by volume ratio
- for(var/datum/gas_mixture/gas in gases)
- gas.oxygen = total_oxygen*gas.volume/total_volume
- gas.nitrogen = total_nitrogen*gas.volume/total_volume
- gas.toxins = total_toxins*gas.volume/total_volume
- gas.carbon_dioxide = total_carbon_dioxide*gas.volume/total_volume
-
- gas.temperature = temperature
-
- if(total_trace_gases.len)
- for(var/datum/gas/trace_gas in total_trace_gases)
- var/datum/gas/corresponding = locate(trace_gas.type) in gas.trace_gases
- if(!corresponding)
- corresponding = new trace_gas.type()
- gas.trace_gases += corresponding
-
- corresponding.moles = trace_gas.moles*gas.volume/total_volume
-
- return 1
-*/
\ No newline at end of file
+ corresponding.moles = trace_gas.moles*G.volume/total_volume
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/pipes/he_pipes.dm b/code/ATMOSPHERICS/pipes/he_pipes.dm
deleted file mode 100644
index 119b371d59b..00000000000
--- a/code/ATMOSPHERICS/pipes/he_pipes.dm
+++ /dev/null
@@ -1,151 +0,0 @@
-////////////
-//HE Pipes
-////////////
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging
- icon = 'icons/obj/atmospherics/pipes/heat.dmi'
- icon_state = "intact"
- level = 2
- var/initialize_directions_he
- var/minimum_temperature_difference = 20
- var/thermal_conductivity = WINDOW_HEAT_TRANSFER_COEFFICIENT
- color = "#404040"
- buckle_lying = 1
- var/icon_temperature = T20C //stop small changes in temperature causing icon refresh
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/New()
- ..()
- color = "#404040"
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/SetInitDirections()
- switch(dir)
- if(SOUTH)
- initialize_directions_he = SOUTH|NORTH
- if(NORTH)
- initialize_directions_he = SOUTH|NORTH
- if(EAST)
- initialize_directions_he = EAST|WEST
- if(WEST)
- initialize_directions_he = WEST|EAST
- if(NORTHEAST)
- initialize_directions_he = NORTH|EAST
- if(NORTHWEST)
- initialize_directions_he = NORTH|WEST
- if(SOUTHEAST)
- initialize_directions_he = SOUTH|EAST
- if(SOUTHWEST)
- initialize_directions_he = SOUTH|WEST
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/atmosinit()
- normalize_dir()
- var/N = 2
- for(var/D in cardinal)
- if(D & initialize_directions_he)
- N--
- for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src, D))
- if(target.initialize_directions_he & get_dir(target,src))
- if(!node1 && N == 1)
- node1 = target
- break
- if(!node2 && N == 0)
- node2 = target
- break
- update_icon()
- ..()
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/process_atmos()
- var/environment_temperature = 0
- var/datum/gas_mixture/pipe_air = return_air()
-
- if(istype(loc, /turf/simulated))
- if(loc:blocks_air)
- environment_temperature = loc:temperature
- else
- var/datum/gas_mixture/environment = loc.return_air()
- environment_temperature = environment.temperature
- else
- environment_temperature = loc:temperature
-
- if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
- parent.temperature_interact(loc, volume, thermal_conductivity)
-
-
- //heatup/cooldown any mobs buckled to ourselves based on our temperature
- if(buckled_mob)
- var/hc = pipe_air.heat_capacity()
- var/avg_temp = (pipe_air.temperature * hc + buckled_mob.bodytemperature * 3500) / (hc + 3500)
- pipe_air.temperature = avg_temp
- buckled_mob.bodytemperature = avg_temp
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/process()
- var/datum/gas_mixture/pipe_air = return_air()
- //Burn any mobs buckled to ourselves based on our temperature
- if(buckled_mob)
- var/heat_limit = 1000
- if(pipe_air.temperature > heat_limit + 1)
- buckled_mob.apply_damage(4 * log(pipe_air.temperature - heat_limit), BURN, "chest")
-
- //Heat causes pipe to glow
- if(pipe_air.temperature && (icon_temperature > 500 || pipe_air.temperature > 500)) //glow starts at 500K
- if(abs(pipe_air.temperature - icon_temperature) > 10)
- icon_temperature = pipe_air.temperature
-
- var/h_r = heat2colour_r(icon_temperature)
- var/h_g = heat2colour_g(icon_temperature)
- var/h_b = heat2colour_b(icon_temperature)
-
- if(icon_temperature < 2000)//scale glow until 2000K
- var/scale = (icon_temperature - 500) / 1500
- h_r = 64 + (h_r - 64) * scale
- h_g = 64 + (h_g - 64) * scale
- h_b = 64 + (h_b - 64) * scale
-
- animate(src, color = rgb(h_r, h_g, h_b), time = 20, easing = SINE_EASING)
-
-////////////////
-//HE Junctions
-////////////////
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction
- icon = 'icons/obj/atmospherics/pipes/junction.dmi'
- icon_state = "intact"
- level = 2
- minimum_temperature_difference = 300
- thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/normalize_dir()
- return
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/SetInitDirections()
- switch(dir)
- if(SOUTH)
- initialize_directions = NORTH
- initialize_directions_he = SOUTH
- if(NORTH)
- initialize_directions = SOUTH
- initialize_directions_he = NORTH
- if(EAST)
- initialize_directions = WEST
- initialize_directions_he = EAST
- if(WEST)
- initialize_directions = EAST
- initialize_directions_he = WEST
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/update_icon()
- if(node1&&node2)
- icon_state = "intact"
- else
- var/have_node1 = node1?1:0
- var/have_node2 = node2?1:0
- icon_state = "exposed[have_node1][have_node2]"
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/atmosinit()
- for(var/obj/machinery/atmospherics/target in get_step(src,initialize_directions))
- if(target.initialize_directions & get_dir(target,src))
- node1 = target
- break
- for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,initialize_directions_he))
- if(target.initialize_directions_he & get_dir(target,src))
- node2 = target
- break
- update_icon()
- ..()
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/pipes/heat_exchange/he_pipes.dm b/code/ATMOSPHERICS/pipes/heat_exchange/he_pipes.dm
new file mode 100644
index 00000000000..8920b51e916
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/heat_exchange/he_pipes.dm
@@ -0,0 +1,79 @@
+/obj/machinery/atmospherics/pipe/heat_exchanging/
+ icon = 'icons/obj/atmospherics/pipes/heat.dmi'
+ level = 2
+ var/initialize_directions_he
+ var/minimum_temperature_difference = 20
+ var/thermal_conductivity = WINDOW_HEAT_TRANSFER_COEFFICIENT
+ color = "#404040"
+ buckle_lying = 1
+ var/icon_temperature = T20C //stop small changes in temperature causing icon refresh
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/New()
+ ..()
+ color = "#404040"
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/can_be_node(obj/machinery/atmospherics/pipe/heat_exchanging/target)
+ if(!istype(target))
+ return 0
+ if(target.initialize_directions_he & get_dir(target,src))
+ return 1
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/hide()
+ return
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/GetInitDirections()
+ return ..() | initialize_directions_he
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/process_atmos()
+ var/environment_temperature = 0
+ var/datum/gas_mixture/pipe_air = return_air()
+
+ var/turf/simulated/T = loc
+ if(istype(T))
+ if(T.blocks_air)
+ environment_temperature = T.temperature
+ else
+ var/datum/gas_mixture/environment = T.return_air()
+ environment_temperature = environment.temperature
+ else
+ environment_temperature = T.temperature
+
+ if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
+ parent.temperature_interact(T, volume, thermal_conductivity)
+
+
+ //heatup/cooldown any mobs buckled to ourselves based on our temperature
+ if(buckled_mob)
+ var/hc = pipe_air.heat_capacity()
+ var/avg_temp = (pipe_air.temperature * hc + buckled_mob.bodytemperature * 3500) / (hc + 3500)
+ pipe_air.temperature = avg_temp
+ buckled_mob.bodytemperature = avg_temp
+
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/process()
+ var/datum/gas_mixture/pipe_air = return_air()
+ if(!pipe_air)
+ return //machines subsystem fires before atmos is initialized so this prevents race condition runtimes
+
+ //Heat causes pipe to glow
+ if(pipe_air.temperature && (icon_temperature > 500 || pipe_air.temperature > 500)) //glow starts at 500K
+ if(abs(pipe_air.temperature - icon_temperature) > 10)
+ icon_temperature = pipe_air.temperature
+
+ var/h_r = heat2colour_r(icon_temperature)
+ var/h_g = heat2colour_g(icon_temperature)
+ var/h_b = heat2colour_b(icon_temperature)
+
+ if(icon_temperature < 2000)//scale glow until 2000K
+ var/scale = (icon_temperature - 500) / 1500
+ h_r = 64 + (h_r - 64) * scale
+ h_g = 64 + (h_g - 64) * scale
+ h_b = 64 + (h_b - 64) * scale
+
+ animate(src, color = rgb(h_r, h_g, h_b), time = 20, easing = SINE_EASING)
+
+ //burn any mobs buckled based on temperature
+ if(buckled_mob)
+ var/heat_limit = 1000
+ if(pipe_air.temperature > heat_limit + 1)
+ buckled_mob.apply_damage(4 * log(pipe_air.temperature - heat_limit), BURN, "chest")
diff --git a/code/ATMOSPHERICS/pipes/heat_exchange/junction.dm b/code/ATMOSPHERICS/pipes/heat_exchange/junction.dm
new file mode 100644
index 00000000000..0cba512ec63
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/heat_exchange/junction.dm
@@ -0,0 +1,50 @@
+/obj/machinery/atmospherics/pipe/heat_exchanging/junction
+ icon = 'icons/obj/atmospherics/pipes/junction.dmi'
+ icon_state = "intact"
+
+ name = "junction"
+ desc = "A one meter junction that connects regular and heat-exchanging pipe"
+
+ minimum_temperature_difference = 300
+ thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
+
+ dir = SOUTH
+ initialize_directions = NORTH
+ initialize_directions_he = SOUTH
+
+ device_type = BINARY
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/junction/SetInitDirections()
+ switch(dir)
+ if(SOUTH)
+ initialize_directions = NORTH
+ initialize_directions_he = SOUTH
+ if(NORTH)
+ initialize_directions = SOUTH
+ initialize_directions_he = NORTH
+ if(EAST)
+ initialize_directions = WEST
+ initialize_directions_he = EAST
+ if(WEST)
+ initialize_directions = EAST
+ initialize_directions_he = WEST
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/junction/atmosinit()
+ var/node2_connect = dir
+ var/node1_connect = turn(dir, 180)
+ var/list/node_connects = list(node1_connect, node2_connect)
+
+ ..(node_connects)
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/junction/can_be_node(obj/machinery/atmospherics/target, iteration)
+ var/init_dir
+ switch(iteration)
+ if(1)
+ init_dir = target.initialize_directions
+ if(2)
+ var/obj/machinery/atmospherics/pipe/heat_exchanging/H = target
+ if(!istype(H))
+ return 0
+ init_dir = H.initialize_directions_he
+ if(init_dir & get_dir(target,src))
+ return 1
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/pipes/heat_exchange/manifold.dm b/code/ATMOSPHERICS/pipes/heat_exchange/manifold.dm
new file mode 100644
index 00000000000..b9e7780cbac
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/heat_exchange/manifold.dm
@@ -0,0 +1,60 @@
+//3-way manifold
+/obj/machinery/atmospherics/pipe/heat_exchanging/manifold
+ icon_state = "manifold"
+
+ name = "pipe manifold"
+ desc = "A manifold composed of regular pipes"
+
+ dir = SOUTH
+ initialize_directions_he = EAST|NORTH|WEST
+
+ device_type = TRINARY
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/manifold/SetInitDirections()
+ switch(dir)
+ if(NORTH)
+ initialize_directions_he = EAST|SOUTH|WEST
+ if(SOUTH)
+ initialize_directions_he = WEST|NORTH|EAST
+ if(EAST)
+ initialize_directions_he = SOUTH|WEST|NORTH
+ if(WEST)
+ initialize_directions_he = NORTH|EAST|SOUTH
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/manifold/update_icon()
+ var/invis = invisibility ? "-f" : ""
+
+ icon_state = "manifold_center[invis]"
+
+ overlays.Cut()
+
+ //Add non-broken pieces
+ for(DEVICE_TYPE_LOOP)
+ if(NODE_I)
+ overlays += getpipeimage('icons/obj/atmospherics/pipes/heat.dmi', "manifold_intact[invis]", get_dir(src, NODE_I))
+
+//4-way manifold
+/obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w
+ icon_state = "manifold4w"
+
+ name = "4-way pipe manifold"
+ desc = "A manifold composed of heat-exchanging pipes"
+
+ initialize_directions_he = NORTH|SOUTH|EAST|WEST
+
+ device_type = QUATERNARY
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w/SetInitDirections()
+ initialize_directions_he = initial(initialize_directions_he)
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w/update_icon()
+ var/invis = invisibility ? "-f" : ""
+
+ icon_state = "manifold4w_center[invis]"
+
+ overlays.Cut()
+
+ //Add non-broken pieces
+ for(DEVICE_TYPE_LOOP)
+ if(NODE_I)
+ overlays += getpipeimage('icons/obj/atmospherics/pipes/heat.dmi', "manifold_intact[invis]", get_dir(src, NODE_I))
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/pipes/heat_exchange/simple.dm b/code/ATMOSPHERICS/pipes/heat_exchange/simple.dm
new file mode 100644
index 00000000000..040e3cf8ae6
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/heat_exchange/simple.dm
@@ -0,0 +1,33 @@
+/obj/machinery/atmospherics/pipe/heat_exchanging/simple
+ icon_state = "intact"
+
+ name = "pipe"
+ desc = "A one meter section of heat-exchanging pipe"
+
+ dir = SOUTH
+ initialize_directions_he = SOUTH|NORTH
+
+ device_type = BINARY
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/simple/SetInitDirections()
+ if(dir in diagonals)
+ initialize_directions_he = dir
+ switch(dir)
+ if(NORTH,SOUTH)
+ initialize_directions_he = SOUTH|NORTH
+ if(EAST,WEST)
+ initialize_directions_he = WEST|EAST
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/simple/proc/normalize_dir()
+ if(dir==SOUTH)
+ dir = NORTH
+ else if(dir==WEST)
+ dir = EAST
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/simple/atmosinit()
+ normalize_dir()
+ ..()
+
+/obj/machinery/atmospherics/pipe/heat_exchanging/simple/update_icon()
+ normalize_dir()
+ ..()
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/pipes/manifold.dm b/code/ATMOSPHERICS/pipes/manifold.dm
index 8f6ac175080..bae84ae22ce 100644
--- a/code/ATMOSPHERICS/pipes/manifold.dm
+++ b/code/ATMOSPHERICS/pipes/manifold.dm
@@ -1,8 +1,6 @@
-
/*
3-Way Manifold
*/
-
/obj/machinery/atmospherics/pipe/manifold
icon = 'icons/obj/atmospherics/pipes/manifold.dmi'
icon_state = "manifold"
@@ -10,22 +8,10 @@
name = "pipe manifold"
desc = "A manifold composed of regular pipes"
- volume = 105
-
dir = SOUTH
initialize_directions = EAST|NORTH|WEST
- var/obj/machinery/atmospherics/node1
- var/obj/machinery/atmospherics/node2
- var/obj/machinery/atmospherics/node3
-
- level = 1
- layer = 2.4 //under wires with their 2.44
-
-/obj/machinery/atmospherics/pipe/manifold/New()
- color = pipe_color
-
- ..()
+ device_type = TRINARY
/obj/machinery/atmospherics/pipe/manifold/SetInitDirections()
switch(dir)
@@ -38,59 +24,6 @@
if(WEST)
initialize_directions = NORTH|EAST|SOUTH
-/obj/machinery/atmospherics/pipe/manifold/atmosinit()
- for(var/D in cardinal)
- if(D == dir)
- continue
- for(var/obj/machinery/atmospherics/target in get_step(src, D))
- if(target.initialize_directions & get_dir(target,src))
- if(turn(dir, 90) == D)
- node1 = target
- if(turn(dir, 270) == D)
- node2 = target
- if(turn(dir, 180) == D)
- node3 = target
- break
- var/turf/T = src.loc // hide if turf is not intact
- hide(T.intact)
- update_icon()
- ..()
-
-/obj/machinery/atmospherics/pipe/manifold/Destroy()
- if(node1)
- var/obj/machinery/atmospherics/A = node1
- node1.disconnect(src)
- node1 = null
- A.build_network()
- if(node2)
- var/obj/machinery/atmospherics/A = node2
- node2.disconnect(src)
- node2 = null
- A.build_network()
- if(node3)
- var/obj/machinery/atmospherics/A = node3
- node3.disconnect(src)
- node3 = null
- A.build_network()
- releaseAirToTurf()
- ..()
-
-/obj/machinery/atmospherics/pipe/manifold/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node1 = null
- if(reference == node2)
- if(istype(node2, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node2 = null
- if(reference == node3)
- if(istype(node3, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node3 = null
- update_icon()
- ..()
-
/obj/machinery/atmospherics/pipe/manifold/update_icon()
var/invis = invisibility ? "-f" : ""
@@ -99,32 +32,9 @@
overlays.Cut()
//Add non-broken pieces
- if(node1)
- overlays += getpipeimage('icons/obj/atmospherics/pipes/manifold.dmi', "manifold_full[invis]", get_dir(src,node1))
-
- if(node2)
- overlays += getpipeimage('icons/obj/atmospherics/pipes/manifold.dmi', "manifold_full[invis]", get_dir(src,node2))
-
- if(node3)
- overlays += getpipeimage('icons/obj/atmospherics/pipes/manifold.dmi', "manifold_full[invis]", get_dir(src,node3))
-
-/obj/machinery/atmospherics/pipe/manifold/hide(i)
- if(level == 1 && istype(loc, /turf/simulated))
- invisibility = i ? 101 : 0
- update_icon()
-
-/obj/machinery/atmospherics/pipe/manifold/pipeline_expansion()
- return list(node1, node2, node3)
-
-/obj/machinery/atmospherics/pipe/manifold/update_node_icon()
- ..()
- if(node1)
- node1.update_icon()
- if(node2)
- node2.update_icon()
- if(node3)
- node3.update_icon()
-
+ for(DEVICE_TYPE_LOOP)
+ if(NODE_I)
+ overlays += getpipeimage('icons/obj/atmospherics/pipes/manifold.dmi', "manifold_full[invis]", get_dir(src, NODE_I))
//Colored pipes, use these for mapping
/obj/machinery/atmospherics/pipe/manifold/general
diff --git a/code/ATMOSPHERICS/pipes/manifold4w.dm b/code/ATMOSPHERICS/pipes/manifold4w.dm
index 4db873eed76..7b5514adc0e 100644
--- a/code/ATMOSPHERICS/pipes/manifold4w.dm
+++ b/code/ATMOSPHERICS/pipes/manifold4w.dm
@@ -1,4 +1,3 @@
-
/*
4-way manifold
*/
@@ -9,101 +8,14 @@
name = "4-way pipe manifold"
desc = "A manifold composed of regular pipes"
- volume = 140
-
initialize_directions = NORTH|SOUTH|EAST|WEST
- var/obj/machinery/atmospherics/node1 // North
- var/obj/machinery/atmospherics/node2 // South
- var/obj/machinery/atmospherics/node3 // East
- var/obj/machinery/atmospherics/node4 // West
-
- level = 1
- layer = 2.4 //under wires with their 2.44
-
-/obj/machinery/atmospherics/pipe/manifold4w/New()
- color = pipe_color
- ..()
+ device_type = QUATERNARY
/obj/machinery/atmospherics/pipe/manifold4w/SetInitDirections()
- return
-
-/obj/machinery/atmospherics/pipe/manifold4w/atmosinit()
- for(var/D in cardinal)
- for(var/obj/machinery/atmospherics/target in get_step(src, D))
- if(target.initialize_directions & get_dir(target,src))
- if(D == NORTH)
- node1 = target
- else if(D == SOUTH)
- node2 = target
- else if(D == EAST)
- node3 = target
- else if(D == WEST)
- node4 = target
- break
-
- var/turf/T = src.loc // hide if turf is not intact
- hide(T.intact)
- update_icon()
- ..()
-
-/obj/machinery/atmospherics/pipe/manifold4w/hide(i)
- if(level == 1 && istype(loc, /turf/simulated))
- invisibility = i ? 101 : 0
- update_icon()
-
-/obj/machinery/atmospherics/pipe/manifold4w/pipeline_expansion()
- return list(node1, node2, node3, node4)
-
-/obj/machinery/atmospherics/pipe/manifold4w/Destroy()
- if(node1)
- var/obj/machinery/atmospherics/A = node1
- node1.disconnect(src)
- node1 = null
- A.build_network()
- if(node2)
- var/obj/machinery/atmospherics/A = node2
- node2.disconnect(src)
- node2 = null
- A.build_network()
- if(node3)
- var/obj/machinery/atmospherics/A = node3
- node3.disconnect(src)
- node3 = null
- A.build_network()
- if(node4)
- var/obj/machinery/atmospherics/A = node4
- node4.disconnect(src)
- node4 = null
- A.build_network()
- releaseAirToTurf()
- ..()
-
-/obj/machinery/atmospherics/pipe/manifold4w/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node1 = null
- if(reference == node2)
- if(istype(node2, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node2 = null
- if(reference == node3)
- if(istype(node3, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node3 = null
- if(reference == node4)
- if(istype(node4, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node4 = null
- update_icon()
- ..()
+ initialize_directions = initial(initialize_directions)
/obj/machinery/atmospherics/pipe/manifold4w/update_icon()
- if(!node1 && !node2 && !node3 && !node4) //Remove us if we ain't connected to anything.
- qdel(src)
- return
-
var/invis = invisibility ? "-f" : ""
icon_state = "manifold4w_center[invis]"
@@ -111,28 +23,9 @@
overlays.Cut()
//Add non-broken pieces
- if(node1)
- overlays += getpipeimage('icons/obj/atmospherics/pipes/manifold.dmi', "manifold_full[invis]", NORTH)
-
- if(node2)
- overlays += getpipeimage('icons/obj/atmospherics/pipes/manifold.dmi', "manifold_full[invis]", SOUTH)
-
- if(node3)
- overlays += getpipeimage('icons/obj/atmospherics/pipes/manifold.dmi', "manifold_full[invis]", EAST)
-
- if(node4)
- overlays += getpipeimage('icons/obj/atmospherics/pipes/manifold.dmi', "manifold_full[invis]", WEST)
-
-/obj/machinery/atmospherics/pipe/manifold4w/update_node_icon()
- ..()
- if(node1)
- node1.update_icon()
- if(node2)
- node2.update_icon()
- if(node3)
- node3.update_icon()
- if(node4)
- node4.update_icon()
+ for(DEVICE_TYPE_LOOP)
+ if(NODE_I)
+ overlays += getpipeimage('icons/obj/atmospherics/pipes/manifold.dmi', "manifold_full[invis]", get_dir(src, NODE_I))
//Colored pipes, use these for mapping
/obj/machinery/atmospherics/pipe/manifold4w/general
diff --git a/code/ATMOSPHERICS/pipes/pipes.dm b/code/ATMOSPHERICS/pipes/pipes.dm
index f0ca8f8e244..df05d4d18bc 100644
--- a/code/ATMOSPHERICS/pipes/pipes.dm
+++ b/code/ATMOSPHERICS/pipes/pipes.dm
@@ -1,7 +1,10 @@
/obj/machinery/atmospherics/pipe
var/datum/gas_mixture/air_temporary //used when reconstructing a pipeline that broke
var/volume = 0
+
+ level = 1
layer = 2.4 //under wires with their 2.44
+
use_power = 0
can_unwrench = 1
var/datum/pipeline/parent = null
@@ -11,8 +14,34 @@
buckle_requires_restraints = 1
buckle_lying = -1
-/obj/machinery/atmospherics/proc/pipeline_expansion()
- return null
+/obj/machinery/atmospherics/pipe/New()
+ color = pipe_color
+ volume = 35 * device_type
+ ..()
+
+/obj/machinery/atmospherics/pipe/nullifyNode(I)
+ var/obj/machinery/atmospherics/oldN = NODE_I
+ ..()
+ if(oldN)
+ oldN.build_network()
+
+/obj/machinery/atmospherics/pipe/update_icon() //overridden by manifolds
+ if(NODE1&&NODE2)
+ icon_state = "intact[invisibility ? "-f" : "" ]"
+ else
+ var/have_node1 = NODE1?1:0
+ var/have_node2 = NODE2?1:0
+ icon_state = "exposed[have_node1][have_node2][invisibility ? "-f" : "" ]"
+
+/obj/machinery/atmospherics/pipe/atmosinit()
+ var/turf/T = loc // hide if turf is not intact
+ hide(T.intact)
+ ..()
+
+/obj/machinery/atmospherics/pipe/hide(i)
+ if(level == 1 && istype(loc, /turf/simulated))
+ invisibility = i ? 101 : 0
+ update_icon()
/obj/machinery/atmospherics/pipe/proc/check_pressure(pressure)
//Return 1 if parent should continue checking other pipes
@@ -50,14 +79,24 @@
parent = P
/obj/machinery/atmospherics/pipe/Destroy()
+ releaseAirToTurf()
+ qdel(air_temporary)
+ air_temporary = null
+
var/turf/T = loc
for(var/obj/machinery/meter/meter in T)
if(meter.target == src)
var/obj/item/pipe_meter/PM = new (T)
meter.transfer_fingerprints_to(PM)
qdel(meter)
- ..()
+ . = ..()
+
+ if(parent && !parent.gc_destroyed)
+ qdel(parent)
+ parent = null
/obj/machinery/atmospherics/pipe/proc/update_node_icon()
- //Used for pipe painting. Overriden in the children.
- return
+ for(DEVICE_TYPE_LOOP)
+ if(NODE_I)
+ var/obj/machinery/atmospherics/N = NODE_I
+ N.update_icon()
diff --git a/code/ATMOSPHERICS/pipes/simple.dm b/code/ATMOSPHERICS/pipes/simple.dm
index b4685c44a1d..02337d84ec3 100644
--- a/code/ATMOSPHERICS/pipes/simple.dm
+++ b/code/ATMOSPHERICS/pipes/simple.dm
@@ -1,4 +1,3 @@
-
/*
Simple Pipe
The regular pipe you see everywhere, including bent ones.
@@ -11,113 +10,33 @@ The regular pipe you see everywhere, including bent ones.
name = "pipe"
desc = "A one meter section of regular pipe"
- volume = 70
-
dir = SOUTH
initialize_directions = SOUTH|NORTH
- var/obj/machinery/atmospherics/node1
- var/obj/machinery/atmospherics/node2
-
- level = 1
-
-/obj/machinery/atmospherics/pipe/simple/New()
- color = pipe_color
-
- ..()
-
+ device_type = BINARY
/obj/machinery/atmospherics/pipe/simple/SetInitDirections()
+ if(dir in diagonals)
+ initialize_directions = dir
switch(dir)
- if(NORTH)
+ if(NORTH,SOUTH)
initialize_directions = SOUTH|NORTH
- if(SOUTH)
- initialize_directions = SOUTH|NORTH
- if(EAST)
+ if(EAST,WEST)
initialize_directions = EAST|WEST
- if(WEST)
- initialize_directions = EAST|WEST
- if(NORTHEAST)
- initialize_directions = NORTH|EAST
- if(NORTHWEST)
- initialize_directions = NORTH|WEST
- if(SOUTHEAST)
- initialize_directions = SOUTH|EAST
- if(SOUTHWEST)
- initialize_directions = SOUTH|WEST
/obj/machinery/atmospherics/pipe/simple/atmosinit()
normalize_dir()
- var/N = 2
- for(var/D in cardinal)
- if(D & initialize_directions)
- N--
- for(var/obj/machinery/atmospherics/target in get_step(src, D))
- if(target.initialize_directions & get_dir(target,src))
- if(!node1 && N == 1)
- node1 = target
- break
- if(!node2 && N == 0)
- node2 = target
- break
- var/turf/T = loc // hide if turf is not intact
- hide(T.intact)
- update_icon()
..()
-/obj/machinery/atmospherics/pipe/simple/Destroy()
- if(node1)
- var/obj/machinery/atmospherics/A = node1
- node1.disconnect(src)
- node1 = null
- A.build_network()
- if(node2)
- var/obj/machinery/atmospherics/A = node2
- node2.disconnect(src)
- node2 = null
- A.build_network()
- releaseAirToTurf()
- ..()
-
-/obj/machinery/atmospherics/pipe/simple/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node1 = null
- if(reference == node2)
- if(istype(node2, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node2 = null
- update_icon()
-
/obj/machinery/atmospherics/pipe/simple/proc/normalize_dir()
- if(dir==2)
- dir = 1
- else if(dir==8)
- dir = 4
+ if(dir==SOUTH)
+ dir = NORTH
+ else if(dir==WEST)
+ dir = EAST
/obj/machinery/atmospherics/pipe/simple/update_icon()
- if(node1&&node2)
- icon_state = "intact[invisibility ? "-f" : "" ]"
- else
- var/have_node1 = node1?1:0
- var/have_node2 = node2?1:0
- icon_state = "exposed[have_node1][have_node2][invisibility ? "-f" : "" ]"
-
-/obj/machinery/atmospherics/pipe/simple/hide(i)
- if(level == 1 && istype(loc, /turf/simulated))
- invisibility = i ? 101 : 0
- update_icon()
-
-/obj/machinery/atmospherics/pipe/simple/pipeline_expansion()
- return list(node1, node2)
-
-/obj/machinery/atmospherics/pipe/simple/update_node_icon()
+ normalize_dir()
..()
- if(node1)
- node1.update_icon()
- if(node2)
- node2.update_icon()
//Colored pipes, use these for mapping
/obj/machinery/atmospherics/pipe/simple/general
diff --git a/code/LINDA/LINDA_turf_tile.dm b/code/LINDA/LINDA_turf_tile.dm
index f3929467d2a..50e2645eced 100644
--- a/code/LINDA/LINDA_turf_tile.dm
+++ b/code/LINDA/LINDA_turf_tile.dm
@@ -8,7 +8,7 @@
var/atmos_supeconductivity = 0
/turf/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
- del(giver)
+ qdel(giver)
return 0
/turf/return_air()
@@ -55,18 +55,20 @@
/turf/simulated/New()
..()
-
+ levelupdate()
+ if(smooth)
+ smooth_icon(src)
+ visibilityChanged()
if(!blocks_air)
air = new
-
air.oxygen = oxygen
air.carbon_dioxide = carbon_dioxide
air.nitrogen = nitrogen
air.toxins = toxins
-
air.temperature = temperature
/turf/simulated/Del()
+ visibilityChanged()
if(active_hotspot)
active_hotspot.Kill()
..()
@@ -290,7 +292,7 @@
/atom/movable/var/pressure_resistance = 5
/atom/movable/proc/experience_pressure_difference(pressure_difference, direction)
- if(!anchored)
+ if(!anchored && !pulledby)
if(pressure_difference > pressure_resistance)
spawn step(src, direction)
return 1
diff --git a/code/__DATASTRUCTURES/linked_lists.dm b/code/__DATASTRUCTURES/linked_lists.dm
new file mode 100644
index 00000000000..eccc3c422a8
--- /dev/null
+++ b/code/__DATASTRUCTURES/linked_lists.dm
@@ -0,0 +1,191 @@
+
+//Ok so it's technically a double linked list, bite me.
+
+/datum/linked_list
+ var/datum/linked_node/head
+ var/datum/linked_node/tail
+ var/node_amt = 0
+
+
+/datum/linked_node
+ var/value = null
+ var/datum/linked_list/linked_list = null
+ var/datum/linked_node/next_node = null
+ var/datum/linked_node/previous_node = null
+
+
+/datum/linked_list/proc/IsEmpty()
+ . = (node_amt <= 0)
+
+
+//Add a linked_node (or value, creating a linked_node) at position
+//the added node BECOMES the position-th element,
+//eg: add("Test",5), the 5th node is now "Test", the previous 5th moves up to become the 6th
+/datum/linked_list/proc/Add(node, position)
+ var/datum/linked_node/adding
+ if(istype(node, /datum/linked_node))
+ adding = node
+ else
+ adding = new()
+ adding.value = node
+
+ if(!adding.linked_list || (adding.linked_list && (adding.linked_list != src)))
+ node_amt++
+
+ adding.linked_list = src
+
+ if(position && position < node_amt)
+ //Replacing head
+ if(position == 1)
+ if(head)
+ head.previous_node = adding
+ adding.next_node = head
+ head = adding
+
+ //Replacing any middle node
+ else
+ var/location = 0
+ var/datum/linked_node/at
+ while((location != position) && (location <= node_amt))
+ if(at)
+ if(at.next_node)
+ at = at.next_node
+ else
+ break
+ else
+ at = head
+ location++
+
+ //Push at up and assume it's place as the position-th element
+ if(at && at.previous_node)
+ at.previous_node.next_node = adding
+ adding.previous_node = at.previous_node
+ at.previous_node = adding
+ adding.next_node = at
+ return
+
+ //Replacing tail
+ if(tail)
+ tail.next_node = adding
+ adding.previous_node = tail
+ if(!tail.previous_node)
+ head = tail
+ tail = adding
+
+
+
+//Remove a linked_node or the linked_node of a value
+//If you specify a value the FIRST ONE is removed
+/datum/linked_list/proc/Remove(node)
+ var/datum/linked_node/removing
+ if(istype(node,/datum/linked_node))
+ removing = node
+ else
+ //optimise removing head and tail, no point looping for them, especially the tail
+ if(removing == head)
+ removing = head
+ else if(removing == tail)
+ removing = tail
+ else
+ var/location = 1
+ var/current_value = null
+ var/datum/linked_node/at = null
+ while((current_value != node) && (location <= node_amt))
+ if(at)
+ if(at.next_node)
+ at = at.next_node
+ else
+ at = head
+ location++
+ if(at)
+ current_value = at.value
+ if(current_value == node)
+ removing = at
+ break
+
+ //Adjust pointers of where removing -was- in the chain.
+ if(removing)
+ if(removing.previous_node)
+ if(removing == tail)
+ tail = removing.previous_node
+ if(removing.next_node)
+ if(removing == head)
+ head = removing.next_node
+ removing.next_node.previous_node = removing.previous_node
+ removing.previous_node.next_node = removing.next_node
+ else
+ removing.previous_node.next_node = null
+ else
+ if(removing.next_node)
+ if(removing == head)
+ head = removing.next_node
+ removing.next_node.previous_node = null
+
+ //if this is still true at this point, there's no more nodes to replace them with
+ if(removing == head)
+ head = null
+ if(removing == tail)
+ tail = null
+
+ removing.next_node = null
+ removing.previous_node = null
+ if(removing.linked_list == src)
+ node_amt--
+ removing.linked_list = null
+
+ return removing
+ return 0
+
+
+//Removes and deletes a node or value
+/datum/linked_list/proc/RemoveDelete(node)
+ var/datum/linked_node/dead = Remove(node)
+ if(dead)
+ qdel(dead)
+ return 1
+ return 0
+
+
+//Empty the linked_list, deleting all nodes
+/datum/linked_list/proc/Empty()
+ var/datum/linked_node/n = head
+ while(n)
+ var/next = n.next_node
+ Remove(n)
+ qdel(n)
+ n = next
+ node_amt = 0
+
+
+//Some debugging tools
+/datum/linked_list/proc/CheckNodeLinks()
+ var/datum/linked_node/n = head
+ while(n)
+ . = "|[n.value]|"
+ if(n.previous_node)
+ . = "[n.previous_node.value]<-" + .
+ if(n.next_node)
+ . += "->[n.next_node.value]"
+ n = n.next_node
+ . += " "
+
+
+/datum/linked_list/proc/DrawNodeLinks()
+ . = "|<-"
+ var/datum/linked_node/n = head
+ while(n)
+ if(n.previous_node)
+ . += "<-"
+ . += "[n.value]"
+ if(n.next_node)
+ . += "->"
+ n = n.next_node
+ . += "->|"
+
+
+/datum/linked_list/proc/ToList()
+ . = list()
+ var/datum/linked_node/n = head
+ while(n)
+ . += n
+ n = n.next_node
\ No newline at end of file
diff --git a/code/__DATASTRUCTURES/priority_queue.dm b/code/__DATASTRUCTURES/priority_queue.dm
new file mode 100644
index 00000000000..2983924e0a1
--- /dev/null
+++ b/code/__DATASTRUCTURES/priority_queue.dm
@@ -0,0 +1,65 @@
+
+//////////////////////
+//PriorityQueue object
+//////////////////////
+
+//an ordered list, using the cmp proc to weight the list elements
+/PriorityQueue
+ var/list/L //the actual queue
+ var/cmp //the weight function used to order the queue
+
+/PriorityQueue/New(compare)
+ L = new()
+ cmp = compare
+
+/PriorityQueue/proc/IsEmpty()
+ return !L.len
+
+//add an element in the list,
+//immediatly ordering it to its position using Insertion sort
+/PriorityQueue/proc/Enqueue(atom/A)
+ var/i
+ L.Add(A)
+ i = L.len -1
+ while(i > 0 && call(cmp)(L[i],A) >= 0) //place the element at it's right position using the compare proc
+ L.Swap(i,i+1) //last inserted element being first in case of ties (optimization)
+ i--
+
+//removes and returns the first element in the queue
+/PriorityQueue/proc/Dequeue()
+ if(!L.len)
+ return 0
+ . = L[1]
+ Remove(.)
+ return .
+
+//removes an element
+/PriorityQueue/proc/Remove(atom/A)
+ return L.Remove(A)
+
+//returns a copy of the elements list
+/PriorityQueue/proc/List()
+ var/list/ret = L.Copy()
+ return ret
+
+//return the position of an element or 0 if not found
+/PriorityQueue/proc/Seek(atom/A)
+ return L.Find(A)
+
+//return the element at the i_th position
+/PriorityQueue/proc/Get(i)
+ if(i > L.len || i < 1)
+ return 0
+ return L[i]
+
+//replace the passed element at it's right position using the cmp proc
+/PriorityQueue/proc/ReSort(atom/A)
+ var/i = Seek(A)
+ if(i == 0)
+ return
+ while(i < L.len && call(cmp)(L[i],L[i+1]) > 0)
+ L.Swap(i,i+1)
+ i++
+ while(i > 1 && call(cmp)(L[i],L[i-1]) <= 0) //last inserted element being first in case of ties (optimization)
+ L.Swap(i,i-1)
+ i--
\ No newline at end of file
diff --git a/code/__DATASTRUCTURES/stacks.dm b/code/__DATASTRUCTURES/stacks.dm
new file mode 100644
index 00000000000..b310a3b9401
--- /dev/null
+++ b/code/__DATASTRUCTURES/stacks.dm
@@ -0,0 +1,56 @@
+/datum/stack
+ var/list/stack = list()
+ var/max_elements = 0
+
+/datum/stack/New(list/elements,max)
+ ..()
+ if(elements)
+ stack = elements.Copy()
+ if(max)
+ max_elements = max
+
+/datum/stack/proc/Pop()
+ if(is_empty())
+ return null
+ . = stack[stack.len]
+ stack.Cut(stack.len,0)
+
+/datum/stack/proc/Push(element)
+ if(max_elements && (stack.len+1 > max_elements))
+ return null
+ stack += element
+
+/datum/stack/proc/Top()
+ if(is_empty())
+ return null
+ . = stack[stack.len]
+
+/datum/stack/proc/is_empty()
+ . = stack.len ? 0 : 1
+
+//Rotate entire stack left with the leftmost looping around to the right
+/datum/stack/proc/RotateLeft()
+ if(is_empty())
+ return 0
+ . = stack[1]
+ stack.Cut(1,2)
+ Push(.)
+
+//Rotate entire stack to the right with the rightmost looping around to the left
+/datum/stack/proc/RotateRight()
+ if(is_empty())
+ return 0
+ . = stack[stack.len]
+ stack.Cut(stack.len,0)
+ stack.Insert(1,.)
+
+
+/datum/stack/proc/Copy()
+ var/datum/stack/S=new()
+ S.stack = stack.Copy()
+ S.max_elements = max_elements
+ return S
+
+
+/datum/stack/proc/Clear()
+ stack.Cut()
diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm
index 1745c74f2a2..c09cb0de0f6 100644
--- a/code/__DEFINES/atmospherics.dm
+++ b/code/__DEFINES/atmospherics.dm
@@ -106,9 +106,42 @@
#define PRESSURE_DAMAGE_COEFFICIENT 4 //The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE
#define MAX_HIGH_PRESSURE_DAMAGE 4 //This used to be 20... I got this much random rage for some retarded decision by polymorph?! Polymorph now lies in a pool of blood with a katana jammed in his spleen. ~Errorage --PS: The katana did less than 20 damage to him :(
#define LOW_PRESSURE_DAMAGE 2 //The amounb of damage someone takes when in a low pressure area (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
-
-#define COLD_SLOWDOWN_FACTOR 20 //Humans are slowed by the difference between bodytemp and BODYTEMP_COLD_DAMAGE_LIMIT divided by this
+
+#define COLD_SLOWDOWN_FACTOR 20 //Humans are slowed by the difference between bodytemp and BODYTEMP_COLD_DAMAGE_LIMIT divided by this
// Atmos pipe limits
#define MAX_OUTPUT_PRESSURE 4500 // (kPa) What pressure pumps and powered equipment max out at.
-#define MAX_TRANSFER_RATE 200 // (L/s) Maximum speed powered equipment can work at.
\ No newline at end of file
+#define MAX_TRANSFER_RATE 200 // (L/s) Maximum speed powered equipment can work at.
+
+//Atmos machinery pipenet stuff
+
+// used for device_type vars; used by DEVICE_TYPE_LOOP
+#define UNARY 1
+#define BINARY 2
+#define TRINARY 3
+#define QUATERNARY 4
+
+// this is the standard for loop used by all sorts of atmos machinery procs
+#define DEVICE_TYPE_LOOP var/I = 1; I <= device_type; I++
+
+// defines for the various machinery lists
+// NODE_I, AIR_I, PARENT_I are used within DEVICE_TYPE_LOOP
+
+// nodes list - all atmos machinery
+#define NODE1 nodes[1]
+#define NODE2 nodes[2]
+#define NODE3 nodes[3]
+#define NODE4 nodes[4]
+#define NODE_I nodes[I]
+
+// airs list - components only
+#define AIR1 airs[1]
+#define AIR2 airs[2]
+#define AIR3 airs[3]
+#define AIR_I airs[I]
+
+// parents list - components only
+#define PARENT1 parents[1]
+#define PARENT2 parents[2]
+#define PARENT3 parents[3]
+#define PARENT_I parents[I]
\ No newline at end of file
diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index 0da4f75e1bf..33d02d6e06e 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -77,4 +77,5 @@
#define ALIEN 4
#define ROBOT 8
#define SLIME 16
-#define DRONE 32
\ No newline at end of file
+#define DRONE 32
+#define SWARMER 64
\ No newline at end of file
diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm
index 20f32f85a37..681defddba2 100644
--- a/code/__DEFINES/genetics.dm
+++ b/code/__DEFINES/genetics.dm
@@ -8,6 +8,7 @@
#define EPILEPSY "Epilepsy"
#define MUTATE "Unstable DNA"
#define COUGH "Cough"
+#define DWARFISM "Dwarfism"
#define CLOWNMUT "Clumsiness"
#define TOURETTES "Tourettes Syndrome"
#define DEAFMUT "Deafness"
@@ -63,7 +64,7 @@
#define DNA_FACIAL_HAIR_STYLE_BLOCK 6
#define DNA_HAIR_STYLE_BLOCK 7
-#define DNA_STRUC_ENZYMES_BLOCKS 23
+#define DNA_STRUC_ENZYMES_BLOCKS 24
#define DNA_UNIQUE_ENZYMES_LEN 32
//Transformation proc stuff
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 94da0533b1a..53b9724d1ac 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -23,12 +23,13 @@
#define FRIDAY_13TH "Friday the 13th"
//Human Overlays Indexes/////////
-#define SPECIES_LAYER 26 // mutantrace colors... these are on a seperate layer in order to prvent
+#define SPECIES_LAYER 27 // mutantrace colors... these are on a seperate layer in order to prvent
+#define MUTATIONS_LAYER 26 //mutations. Hulk, Tk headglows, etc
#define BODY_BEHIND_LAYER 25
#define BODY_LAYER 24 //underwear, undershirts, socks, eyes, lips(makeup)
#define BODY_ADJ_LAYER 23
-#define MUTATIONS_LAYER 22 //Tk headglows etc.
-#define AUGMENTS_LAYER 21
+#define AUGMENTS_LAYER 22
+#define FRONT_MUTATIONS_LAYER 21 //mutations that should appear above body and augments layer (e.g. laser eyes)
#define DAMAGE_LAYER 20 //damage indicators (cuts and burns)
#define UNIFORM_LAYER 19
#define ID_LAYER 18
@@ -49,7 +50,7 @@
#define R_HAND_LAYER 3 //Having the two hands seperate seems rather silly, merge them together? It'll allow for code to be reused on mobs with arbitarily many hands
#define BODY_FRONT_LAYER 2
#define FIRE_LAYER 1 //If you're on fire
-#define TOTAL_LAYERS 26 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
+#define TOTAL_LAYERS 27 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
//Human Overlay Index Shortcuts for alternate_worn_layer, layers
//Because I *KNOW* somebody will think layer+1 means "above"
@@ -244,3 +245,31 @@
#define FACING_EACHOTHER 2
#define FACING_INIT_FACING_TARGET_TARGET_FACING_PERPENDICULAR 3 //Do I win the most informative but also most stupid define award?
+
+//Cache of bloody footprint images
+//Key:
+//"entered-[blood_state]-[dir_of_image]"
+//or: "exited-[blood_state]-[dir_of_image]"
+var/list/bloody_footprints_cache = list()
+
+//Bloody shoes/footprints
+#define MAX_SHOE_BLOODINESS 100
+#define BLOODY_FOOTPRINT_BASE_ALPHA 150
+#define BLOOD_GAIN_PER_STEP 100
+#define BLOOD_LOSS_PER_STEP 5
+#define BLOOD_FADEOUT_TIME 2
+
+//Bloody shoe blood states
+#define BLOOD_STATE_HUMAN "blood"
+#define BLOOD_STATE_XENO "xeno"
+#define BLOOD_STATE_OIL "oil"
+#define BLOOD_STATE_NOT_BLOODY "no blood whatsoever"
+//Turf wet states
+#define TURF_DRY 0
+#define TURF_WET_WATER 1
+#define TURF_WET_LUBE 2
+
+//Object/Item sharpness
+#define IS_BLUNT 0
+#define IS_SHARP 1
+#define IS_SHARP_ACCURATE 2
\ No newline at end of file
diff --git a/code/__DEFINES/pipe_construction.dm b/code/__DEFINES/pipe_construction.dm
new file mode 100644
index 00000000000..f19c19824ab
--- /dev/null
+++ b/code/__DEFINES/pipe_construction.dm
@@ -0,0 +1,41 @@
+/*
+PIPE CONSTRUCTION DEFINES
+Update these any time a path is changed
+Construction breaks otherwise
+*/
+
+//Pipes
+#define PIPE_SIMPLE /obj/machinery/atmospherics/pipe/simple
+#define PIPE_MANIFOLD /obj/machinery/atmospherics/pipe/manifold
+#define PIPE_4WAYMANIFOLD /obj/machinery/atmospherics/pipe/manifold4w
+#define PIPE_HE /obj/machinery/atmospherics/pipe/heat_exchanging/simple
+#define PIPE_HE_MANIFOLD /obj/machinery/atmospherics/pipe/heat_exchanging/manifold
+#define PIPE_HE_4WAYMANIFOLD /obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w
+#define PIPE_JUNCTION /obj/machinery/atmospherics/pipe/heat_exchanging/junction
+//Unary
+#define PIPE_CONNECTOR /obj/machinery/atmospherics/components/unary/portables_connector
+#define PIPE_UVENT /obj/machinery/atmospherics/components/unary/vent_pump
+#define PIPE_SCRUBBER /obj/machinery/atmospherics/components/unary/vent_scrubber
+#define PIPE_HEAT_EXCHANGE /obj/machinery/atmospherics/components/unary/heat_exchanger
+//Binary
+#define PIPE_PUMP /obj/machinery/atmospherics/components/binary/pump
+#define PIPE_PASSIVE_GATE /obj/machinery/atmospherics/components/binary/passive_gate
+#define PIPE_VOLUME_PUMP /obj/machinery/atmospherics/components/binary/volume_pump
+#define PIPE_MVALVE /obj/machinery/atmospherics/components/binary/valve
+#define PIPE_DVALVE /obj/machinery/atmospherics/components/binary/valve/digital
+//Trinary
+#define PIPE_GAS_FILTER /obj/machinery/atmospherics/components/trinary/filter
+#define PIPE_GAS_MIXER /obj/machinery/atmospherics/components/trinary/mixer
+
+//Disposal piping numbers - do NOT hardcode these, use the defines
+#define DISP_PIPE_STRAIGHT 0
+#define DISP_PIPE_BENT 1
+#define DISP_JUNCTION 2
+#define DISP_JUNCTION_FLIP 3
+#define DISP_YJUNCTION 4
+#define DISP_END_TRUNK 5
+#define DISP_END_BIN 6
+#define DISP_END_OUTLET 7
+#define DISP_END_CHUTE 8
+#define DISP_SORTJUNCTION 9
+#define DISP_SORTJUNCTION_FLIP 10
\ No newline at end of file
diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm
index bb05efc975a..65084617ba1 100644
--- a/code/__DEFINES/preferences.dm
+++ b/code/__DEFINES/preferences.dm
@@ -10,6 +10,7 @@
#define SOUND_INSTRUMENTS 128
#define SOUND_SHIP_AMBIENCE 256
#define SOUND_PRAYERS 512
+#define ANNOUNCE_LOGIN 1024
#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE|SOUND_PRAYERS)
@@ -43,4 +44,4 @@
#define BE_GANG 4096
#define BE_SHADOWLING 8192
#define BE_ABDUCTOR 16384
-#define BE_REVENANT 32768
+#define BE_REVENANT 32768
diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm
index feb949b3241..f228349b70d 100644
--- a/code/__DEFINES/qdel.dm
+++ b/code/__DEFINES/qdel.dm
@@ -7,4 +7,5 @@
#define QDEL_HINT_HARDDEL 3 //qdel should assume this object won't gc, and queue a hard delete using a hard reference.
#define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste.
#define QDEL_HINT_PUTINPOOL 5 //qdel will put this object in the atom pool.
-
+#define QDEL_HINT_FINDREFERENCE 6 //functionally identical to QDEL_HINT_QUEUE if TESTING is not enabled in _compiler_options.dm.
+ //if TESTING is enabled, qdel will call this object's find_references() verb.
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index 21626590306..1d7c5cfdd24 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -380,3 +380,56 @@
return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y)
+/proc/pollCandidates(var/Question, var/jobbanType, var/datum/game_mode/gametypeCheck, var/be_special_flag = 0, var/poll_time = 300)
+ var/list/mob/dead/observer/candidates = list()
+ var/time_passed = world.time
+ if (!Question)
+ Question = "Would you like to be a special role?"
+
+ for(var/mob/dead/observer/G in player_list)
+ if(!G.key || !G.client)
+ continue
+ if(be_special_flag)
+ if(!(G.client.prefs.be_special & be_special_flag))
+ continue
+ if (gametypeCheck)
+ if(!gametypeCheck.age_check(G.client))
+ continue
+ if (jobbanType)
+ if(jobban_isbanned(G, jobbanType) || jobban_isbanned(G, "Syndicate"))
+ continue
+ spawn(0)
+ G << 'sound/misc/notice2.ogg' //Alerting them to their consideration
+ switch(alert(G,Question,"Please answer in [poll_time/10] seconds!","Yes","No"))
+ if("Yes")
+ G << "Choice registered: Yes."
+ if((world.time-time_passed)>poll_time)//If more than 30 game seconds passed.
+ G << "Sorry, you were too late for the consideration!"
+ G << 'sound/machines/buzz-sigh.ogg'
+ return
+ candidates += G
+ if("No")
+ G << "Choice registered: No."
+ return
+ else
+ return
+ sleep(poll_time)
+
+ //Check all our candidates, to make sure they didn't log off during the 30 second wait period.
+ for(var/mob/dead/observer/G in candidates)
+ if(!G.key || !G.client)
+ candidates.Remove(G)
+
+ return candidates
+
+/proc/makeBody(mob/dead/observer/G_found) // Uses stripped down and bastardized code from respawn character
+ if(!G_found || !G_found.key) return
+
+ //First we spawn a dude.
+ var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned.
+
+ G_found.client.prefs.copy_to(new_character)
+ new_character.dna.update_dna_identity()
+ new_character.key = G_found.key
+
+ return new_character
diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm
index 0de55b127be..09c6c4e1973 100644
--- a/code/__HELPERS/icon_smoothing.dm
+++ b/code/__HELPERS/icon_smoothing.dm
@@ -1,10 +1,26 @@
-/atom/var/smooth = 0
+//Redefinitions of the diagonal directions so they can be stored in one var without conflicts
+#define NORTH_EAST 16
+#define NORTH_WEST 32
+#define SOUTH_EAST 64
+#define SOUTH_WEST 128
+
+#define SMOOTH_FALSE 0 //not smooth
+#define SMOOTH_TRUE 1 //smooths with exact specified types or just itself
+#define SMOOTH_MORE 2 //smooths with all subtypes of specified types or just itself
+
+/atom/var/smooth = SMOOTH_FALSE
/atom/var/top_left_corner
/atom/var/top_right_corner
/atom/var/bottom_left_corner
/atom/var/bottom_right_corner
/atom/var/can_be_unanchored = 0
-/atom/var/list/canSmoothWith=list() // TYPE PATHS I CAN SMOOTH WITH~~~~~
+/atom/var/list/canSmoothWith = null // TYPE PATHS I CAN SMOOTH WITH~~~~~ If this is null and atom is smooth, it smooths only with itself
+
+/atom/proc/clear_smooth_overlays()
+ overlays -= top_left_corner
+ overlays -= top_right_corner
+ overlays -= bottom_right_corner
+ overlays -= bottom_left_corner
//generic (by snowflake) tile smoothing code; smooth your icons with this!
/*
@@ -16,13 +32,10 @@
Each atom has its own icon file with all the possible corner states. See 'smooth_wall.dmi' for a template.
*/
-//Redefinitions of the diagonal directions so they can be stored in one var without conflicts
-#define NORTH_EAST 16
-#define NORTH_WEST 32
-#define SOUTH_EAST 64
-#define SOUTH_WEST 128
-
/proc/calculate_adjacencies(atom/A)
+ if(!A.loc)
+ return 0
+
var/adjacencies = 0
if(A.can_be_unanchored)
@@ -45,11 +58,13 @@
return adjacencies
/proc/smooth_icon(atom/A)
+ if(qdeleted(A))
+ return
spawn(0) //don't remove this, otherwise smoothing breaks
if(A && A.smooth)
var/adjacencies = calculate_adjacencies(A)
- clear_overlays(A)
+ A.clear_smooth_overlays()
A.top_left_corner = make_nw_corner(adjacencies)
A.top_right_corner = make_ne_corner(adjacencies)
@@ -61,7 +76,6 @@
A.overlays += A.bottom_right_corner
A.overlays += A.bottom_left_corner
-
/proc/make_nw_corner(adjacencies)
var/sdir = "i"
if((adjacencies & NORTH) && (adjacencies & WEST))
@@ -74,8 +88,6 @@
sdir = "n"
else if(adjacencies & WEST)
sdir = "w"
- else
- sdir = "i"
return "1-[sdir]"
/proc/make_ne_corner(adjacencies)
@@ -90,8 +102,6 @@
sdir = "n"
else if(adjacencies & EAST)
sdir = "e"
- else
- sdir = "i"
return "2-[sdir]"
/proc/make_sw_corner(adjacencies)
@@ -106,8 +116,6 @@
sdir = "s"
else if(adjacencies & WEST)
sdir = "w"
- else
- sdir = "i"
return "3-[sdir]"
/proc/make_se_corner(adjacencies)
@@ -123,8 +131,6 @@
else
if(adjacencies & EAST)
sdir = "e"
- else
- sdir = "i"
return "4-[sdir]"
/proc/smooth_icon_neighbors(atom/A)
@@ -149,14 +155,21 @@
var/turf/target_turf = locate(source.x + x_offset, source.y + y_offset, source.z)
if(source.canSmoothWith)
var/atom/A
- for(var/a_type in source.canSmoothWith)
- if(ispath(a_type, /turf))
- if(a_type == target_turf.type)
+ if(source.smooth == SMOOTH_MORE)
+ for(var/a_type in source.canSmoothWith)
+ if( istype(target_turf, a_type) )
return target_turf
- else
A = locate(a_type) in target_turf
- if(A && A.type == a_type)
+ if(A)
return A
+ return null
+
+ for(var/a_type in source.canSmoothWith)
+ if(a_type == target_turf.type)
+ return target_turf
+ A = locate(a_type) in target_turf
+ if(A && A.type == a_type)
+ return A
return null
else
if(isturf(source))
@@ -164,12 +177,6 @@
var/atom/A = locate(source.type) in target_turf
return A && A.type == source.type ? A : null
-/proc/clear_overlays(atom/A)
- A.overlays -= A.top_left_corner
- A.overlays -= A.top_right_corner
- A.overlays -= A.bottom_right_corner
- A.overlays -= A.bottom_left_corner
-
/proc/transform_dir(direction)
switch(direction)
if(NORTH,SOUTH,EAST,WEST)
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index ef86ac33bfc..649f671d82c 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -217,7 +217,7 @@ world
// Multiply all alpha values by this float
-/icon/proc/ChangeOpacity(opacity = 1.0)
+/icon/proc/ChangeOpacity(opacity = 1)
MapColors(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,opacity, 0,0,0,0)
// Convert to grayscale
diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm
index 2ec7b4c407f..66ae50cf852 100644
--- a/code/__HELPERS/lists.dm
+++ b/code/__HELPERS/lists.dm
@@ -342,4 +342,10 @@
for(var/datum/D in L)
if(D.vars.Find(varname))
if(D.vars[varname] == value)
- return D
\ No newline at end of file
+ return D
+
+//remove all nulls from a list
+/proc/removeNullsFromList(list/L)
+ while(L.Remove(null))
+ continue
+ return L
\ No newline at end of file
diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm
index 264f8cc73f1..27f8526c2e1 100644
--- a/code/__HELPERS/text.dm
+++ b/code/__HELPERS/text.dm
@@ -76,7 +76,7 @@
// Used to get a properly sanitized input, of max_length
/proc/stripped_input(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN)
var/name = input(user, message, title, default) as text|null
- return html_encode(trim(name, max_length)) //trim is "inside" because html_encode can expand single symbols into multiple symbols (such as turning < into <)
+ return trim(html_encode(name), max_length) //trim is "outside" because html_encode can expand single symbols into multiple symbols (such as turning < into <)
// Used to get a properly sanitized multiline input, of max_length
/proc/stripped_multiline_input(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN)
@@ -411,4 +411,4 @@ var/list/binary = list("0","1")
t = replacetext(t, "\[list\]", "
")
t = replacetext(t, "\[/list\]", "
")
- return t
\ No newline at end of file
+ return t
diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm
index fe9e8a29e25..216a65b5be3 100644
--- a/code/__HELPERS/type2type.dm
+++ b/code/__HELPERS/type2type.dm
@@ -193,21 +193,21 @@
//Turns a direction into text
/proc/dir2text(direction)
switch(direction)
- if(1.0)
+ if(1)
return "north"
- if(2.0)
+ if(2)
return "south"
- if(4.0)
+ if(4)
return "east"
- if(8.0)
+ if(8)
return "west"
- if(5.0)
+ if(5)
return "northeast"
- if(6.0)
+ if(6)
return "southeast"
- if(9.0)
+ if(9)
return "northwest"
- if(10.0)
+ if(10)
return "southwest"
else
return
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 429994eaf19..74202a2f82a 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1108,90 +1108,6 @@ var/global/list/common_tools = list(
return 1
return 0
-/proc/is_hot(obj/item/W)
- if(istype(W, /obj/item/weapon/weldingtool))
- var/obj/item/weapon/weldingtool/O = W
- if(O.isOn())
- return 3800
- else
- return 0
- if(istype(W, /obj/item/weapon/lighter))
- var/obj/item/weapon/lighter/O = W
- if(O.lit)
- return 1500
- else
- return 0
- if(istype(W, /obj/item/weapon/match))
- var/obj/item/weapon/match/O = W
- if(O.lit == 1)
- return 1000
- else
- return 0
- if(istype(W, /obj/item/clothing/mask/cigarette))
- var/obj/item/clothing/mask/cigarette/O = W
- if(O.lit)
- return 1000
- else
- return 0
- if(istype(W, /obj/item/candle))
- var/obj/item/candle/O = W
- if(O.lit)
- return 1000
- else
- return 0
- if(istype(W, /obj/item/device/flashlight/flare))
- var/obj/item/device/flashlight/flare/O = W
- if(O.on)
- return 1000
- else
- return 0
- if(istype(W, /obj/item/weapon/gun/energy/plasmacutter))
- return 3800
- if(istype(W, /obj/item/weapon/melee/energy))
- var/obj/item/weapon/melee/energy/O = W
- if(O.active)
- return 3500
- else
- return 0
- if(istype(W, /obj/item/device/assembly/igniter))
- return 1000
- else
- return 0
-
-//Is this even used for anything besides balloons? Yes I took out the W:lit stuff because : really shouldnt be used.
-/proc/is_sharp(obj/item/W) // For the record, WHAT THE HELL IS THIS METHOD OF DOING IT?
- var/list/sharp_things_1 = list(\
- /obj/item/weapon/circular_saw,\
- /obj/item/weapon/shovel,\
- /obj/item/weapon/shard,\
- /obj/item/weapon/broken_bottle,\
- /obj/item/weapon/twohanded/fireaxe,\
- /obj/item/weapon/hatchet,\
- /obj/item/weapon/throwing_star,\
- /obj/item/clothing/glasses/sunglasses/garb,\
- /obj/item/clothing/glasses/sunglasses/gar,\
- /obj/item/clothing/glasses/hud/security/sunglasses/gars,\
- /obj/item/clothing/glasses/meson/gar,\
- /obj/item/weapon/twohanded/spear)
-
- //Because is_sharp is used for food or something.
- var/list/sharp_things_2 = list(\
- /obj/item/weapon/kitchen/knife,\
- /obj/item/weapon/scalpel)
-
- if(is_type_in_list(W,sharp_things_1))
- return 1
-
- if(is_type_in_list(W,sharp_things_2))
- return 2 //cutting food
-
- if(istype(W, /obj/item/weapon/melee/energy))
- var/obj/item/weapon/melee/energy/E = W
- if(E.active)
- return 1
- else
- return 0
-
/proc/is_pointed(obj/item/W)
if(istype(W, /obj/item/weapon/pen))
return 1
@@ -1207,7 +1123,7 @@ var/global/list/common_tools = list(
//For objects that should embed, but make no sense being is_sharp or is_pointed()
//e.g: rods
/proc/can_embed(obj/item/W)
- if(is_sharp(W))
+ if(W.is_sharp())
return 1
if(is_pointed(W))
return 1
@@ -1227,17 +1143,29 @@ var/list/WALLITEMS = list(
/obj/machinery/power/apc, /obj/machinery/alarm, /obj/item/device/radio/intercom,
/obj/structure/extinguisher_cabinet, /obj/structure/reagent_dispensers/peppertank,
/obj/machinery/status_display, /obj/machinery/requests_console, /obj/machinery/light_switch, /obj/structure/sign,
- /obj/machinery/newscaster, /obj/machinery/firealarm, /obj/structure/noticeboard, /obj/machinery/door_control,
+ /obj/machinery/newscaster, /obj/machinery/firealarm, /obj/structure/noticeboard, /obj/machinery/button,
/obj/machinery/computer/security/telescreen, /obj/machinery/embedded_controller/radio/simple_vent_controller,
/obj/item/weapon/storage/secure/safe, /obj/machinery/door_timer, /obj/machinery/flasher, /obj/machinery/keycard_auth,
/obj/structure/mirror, /obj/structure/fireaxecabinet, /obj/machinery/computer/security/telescreen/entertainment
)
-/proc/gotwallitem(loc, dir)
+
+var/list/WALLITEMS_EXTERNAL = list(
+ /obj/machinery/camera, /obj/machinery/camera_assembly,
+ /obj/machinery/light_construct, /obj/machinery/light)
+
+var/list/WALLITEMS_INVERSE = list(
+ /obj/machinery/light_construct, /obj/machinery/light)
+
+
+/proc/gotwallitem(loc, dir, var/check_external = 0)
var/locdir = get_step(loc, dir)
for(var/obj/O in loc)
- if(is_type_in_list(O, WALLITEMS))
+ if(is_type_in_list(O, WALLITEMS) && check_external != 2)
//Direction works sometimes
- if(O.dir == dir)
+ if(is_type_in_list(O, WALLITEMS_INVERSE))
+ if(O.dir == turn(dir, 180))
+ return 1
+ else if(O.dir == dir)
return 1
//Some stuff doesn't use dir properly, so we need to check pixel instead
@@ -1245,9 +1173,16 @@ var/list/WALLITEMS = list(
if(get_turf_pixel(O) == locdir)
return 1
+ if(is_type_in_list(O, WALLITEMS_EXTERNAL) && check_external)
+ if(is_type_in_list(O, WALLITEMS_INVERSE))
+ if(O.dir == turn(dir, 180))
+ return 1
+ else if(O.dir == dir)
+ return 1
+
//Some stuff is placed directly on the wallturf (signs)
for(var/obj/O in locdir)
- if(is_type_in_list(O, WALLITEMS))
+ if(is_type_in_list(O, WALLITEMS) && check_external != 2)
if(O.pixel_x == 0 && O.pixel_y == 0)
return 1
return 0
@@ -1396,21 +1331,32 @@ B --><-- A
*/
-/atom/movable/var/atom/orbiting = null
//This is just so you can stop an orbit.
//orbit() can run without it (swap orbiting for A)
//but then you can never stop it and that's just silly.
+/atom/movable/var/atom/orbiting = null
+//we raise this each time orbit is called to prevent mutiple calls in a short time frame from breaking things
+/atom/movable/var/orbitid = 0
-/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = 1, angle_increment = 15)
+/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = 1, angle_increment = 15, lockinorbit = 0)
if(!istype(A))
return
+ orbitid++
+ var/myid = orbitid
+ if (orbiting)
+ stop_orbit()
+ //sadly this is the only way to ensure the original orbit proc stops and resets the atom's transform.
+ sleep(1)
+ if (orbiting || !istype(A) || orbitid != myid) //post sleep re-check
+ return
orbiting = A
+ var/lastloc = loc
var/angle = 0
var/matrix/initial_transform = matrix(transform)
spawn
- while(orbiting)
- loc = orbiting.loc
-
+ while(orbiting && orbiting.loc && orbitid == myid && (!lockinorbit || loc == lastloc))
+ loc = get_turf(orbiting.loc)
+ lastloc = loc
angle += angle_increment
var/matrix/shift = matrix(initial_transform)
@@ -1429,3 +1375,40 @@ B --><-- A
if(orbiting)
loc = get_turf(orbiting)
orbiting = null
+
+
+//Center's an image.
+//Requires:
+//The Image
+//The x dimension of the icon file used in the image
+//The y dimension of the icon file used in the image
+// eg: center_image(I, 32,32)
+// eg2: center_image(I, 96,96)
+
+/proc/center_image(var/image/I, x_dimension = 0, y_dimension = 0)
+ if(!I)
+ return
+
+ if(!x_dimension || !y_dimension)
+ return
+
+ //Get out of here, punk ass kids calling procs needlessly
+ if((x_dimension == world.icon_size) && (y_dimension == world.icon_size))
+ return I
+
+ //Offset the image so that it's bottom left corner is shifted this many pixels
+ //This makes it infinitely easier to draw larger inhands/images larger than world.iconsize
+ //but still use them in game
+ var/x_offset = -((x_dimension/world.icon_size)-1)*(world.icon_size*0.5)
+ var/y_offset = -((y_dimension/world.icon_size)-1)*(world.icon_size*0.5)
+
+ //Correct values under world.icon_size
+ if(x_dimension < world.icon_size)
+ x_offset *= -1
+ if(y_dimension < world.icon_size)
+ y_offset *= -1
+
+ I.pixel_x = x_offset
+ I.pixel_y = y_offset
+
+ return I
diff --git a/code/_compile_options.dm b/code/_compile_options.dm
index 320b756fdee..a27192f7dc4 100644
--- a/code/_compile_options.dm
+++ b/code/_compile_options.dm
@@ -1,7 +1,5 @@
#define DEBUG //Enables byond profiling and full runtime logs - note, this may also be defined in your .dme file
-//#define dellogging //Enables logging of forced del() calls (used for debugging)
-//#define TESTING //Enables in-depth debug messages to runtime log (used for debugging)
- //By using the testing("message") proc you can create debug-feedback for people with this
+//#define TESTING //Enables in-depth debug messages to runtime log (used for debugging) //By using the testing("message") proc you can create debug-feedback for people with this
//uncommented, but not visible in the release version)
#define PRELOAD_RSC 1 /*set to:
@@ -46,15 +44,6 @@
#define AI_VOX 1 // Comment out if you don't want VOX to be enabled and have players download the voice sounds.
//Additional code for the above flags.
-#ifdef dellogging
-#warn compiling del logging. This will have additional overheads. //will warn you if compiling with dellogging
-var/list/del_counter = list()
-/proc/log_del(datum/X)
- if(istype(X)){del_counter[X.type]++;}
- del(X)
-#define del(X) log_del(X) //overrides all del() calls with log_del()
-#endif
-
#ifdef TESTING
#warn compiling in TESTING mode. testing() debug messages will be visible.
#endif
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index fcb84606da3..0df52bd675d 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -13,4 +13,6 @@ var/global/list/chemical_reactions_list //list of all /datum/chemical_reactio
var/global/list/chemical_reagents_list //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff
var/global/list/surgeries_list = list() //list of all surgeries by name, associated with their path.
var/global/list/table_recipes = list() //list of all table craft recipes
-var/global/list/apcs_list = list() //list of all Area Power Controller machines, seperate from machines for powernet speeeeeeed.
\ No newline at end of file
+var/global/list/rcd_list = list() //list of Rapid Construction Devices.
+var/global/list/apcs_list = list() //list of all Area Power Controller machines, seperate from machines for powernet speeeeeeed.
+var/global/list/tracked_implants = list() //list of all current implants that are tracked to work out what sort of trek everyone is on. Sadly not on lavaworld not implemented...
\ No newline at end of file
diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm
index ccd6ccaf7f2..b3b0d91fbd1 100644
--- a/code/_onclick/drag_drop.dm
+++ b/code/_onclick/drag_drop.dm
@@ -5,8 +5,10 @@
recieving object instead, so that's the default action. This allows you to drag
almost anything into a trash can.
*/
-/atom/MouseDrop(atom/over)
+/atom/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
if(!usr || !over) return
+ if(over == src)
+ return usr.client.Click(src, src_location, src_control, params)
if(!Adjacent(usr) || !over.Adjacent(usr)) return // should stop you from dragging through windows
over.MouseDrop_T(src,usr)
diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm
index 3f005c58c0f..c1442fe2e9c 100644
--- a/code/_onclick/hud/action.dm
+++ b/code/_onclick/hud/action.dm
@@ -30,6 +30,7 @@
/datum/action/Destroy()
if(owner)
Remove(owner)
+ return ..()
/datum/action/proc/Grant(mob/living/T)
if(owner)
@@ -45,7 +46,8 @@
if(button)
if(T.client)
T.client.screen -= button
- del(button)
+ qdel(button)
+ button = null
T.actions.Remove(src)
T.update_action_buttons()
owner = null
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index fb209d087e7..d947bfa6553 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -197,6 +197,8 @@ var/datum/global_hud/global_hud = new()
blob_hud()
else if(isdrone(mymob))
drone_hud(ui_style)
+ else if(isswarmer(mymob))
+ swarmer_hud()
//Version denotes which style should be displayed. blank or 0 means "next version"
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index bc045a9923d..9681dd9b556 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -9,13 +9,13 @@
/obj/screen
name = ""
icon = 'icons/mob/screen_gen.dmi'
- layer = 20.0
+ layer = 20
unacidable = 1
var/obj/master = null //A reference to the object in the slot. Grabs or items, generally.
/obj/screen/Destroy()
master = null
- ..()
+ return ..()
/obj/screen/text
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index e0bdd54cae3..aa33440fa74 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -39,6 +39,16 @@
visible_message("[attack_message]",
"[attack_message]")
+ if((butcher_results) && (stat == DEAD))
+ var/sharpness = I.is_sharp()
+ if(sharpness)
+ user.changeNext_move(CLICK_CD_MELEE)
+ user << "You begin to butcher [src]..."
+ playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1)
+ if(do_mob(user, src, 80/sharpness))
+ harvest(user)
+ return
+
/mob/living/simple_animal/attacked_by(var/obj/item/I, var/mob/living/user)
if(!I.force)
user.visible_message("[user] gently taps [src] with [I].",\
diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm
index 33a8ad6e056..ff3ebace2ce 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -67,7 +67,7 @@ var/const/tk_maxrange = 15
icon_state = "2"
flags = NOBLUDGEON | ABSTRACT
//item_state = null
- w_class = 10.0
+ w_class = 10
layer = 20
var/last_throw = 0
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index c8670e39a3d..cb111d7c063 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -163,6 +163,11 @@
var/reactionary_explosions = 0 //If we use reactionary explosions, explosions that react to walls and doors
+ var/autoconvert_notes = 0 //if all connecting player's notes should attempt to be converted to the database
+
+ var/announce_admin_logout = 0
+ var/announce_admin_login = 0
+
/datum/configuration/New()
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
for(var/T in L)
@@ -178,7 +183,7 @@
probabilities[M.config_tag] = M.probability
if(M.votable)
votable_modes += M.config_tag
- del(M)
+ qdel(M)
votable_modes += "secret"
/datum/configuration/proc/load(filename, type = "config") //the type can also be game_options, in which case it uses a different switch. not making it separate to not copypaste code - Urist
@@ -343,6 +348,12 @@
if (world.log != newlog)
world.log << "Now logging runtimes to data/logs/runtimes/runtime-[time2text(world.realtime, "YYYY-MM-DD")].log"
world.log = newlog
+ if("autoconvert_notes")
+ config.autoconvert_notes = 1
+ if("announce_admin_logout")
+ config.announce_admin_logout = 1
+ if("announce_admin_login")
+ config.announce_admin_login = 1
else
diary << "Unknown setting in configuration: '[name]'"
@@ -567,7 +578,7 @@
var/datum/game_mode/M = new T()
if(M.config_tag && M.config_tag == mode_name)
return M
- del(M)
+ qdel(M)
return new /datum/game_mode/extended()
/datum/configuration/proc/get_runnable_modes()
@@ -576,10 +587,10 @@
var/datum/game_mode/M = new T()
//world << "DEBUG: [T], tag=[M.config_tag], prob=[probabilities[M.config_tag]]"
if(!(M.config_tag in modes))
- del(M)
+ qdel(M)
continue
if(probabilities[M.config_tag]<=0)
- del(M)
+ qdel(M)
continue
if(M.can_start())
runnable_modes[M] = probabilities[M.config_tag]
diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm
index a4639a42327..31bdbd542a8 100644
--- a/code/controllers/master_controller.dm
+++ b/code/controllers/master_controller.dm
@@ -103,7 +103,7 @@ calculate the longest number of ticks the MC can wait between each cycle without
var/oldwait = SS.wait
var/GlobalCostDelta = (SSCostPerSecond-(SS.cost/(SS.wait/10)))-1
var/NewWait = MC_AVERAGE(oldwait,(SS.cost-SS.dwait_buffer+GlobalCostDelta)*SS.dwait_delta)
- SS.wait = Clamp(round(NewWait,world.tick_lag),SS.dwait_lower,SS.dwait_upper)
+ SS.wait = Clamp(NewWait,SS.dwait_lower,SS.dwait_upper)
if (oldwait != SS.wait)
calculateGCD()
SS.next_fire += SS.wait
@@ -147,4 +147,4 @@ calculate the longest number of ticks the MC can wait between each cycle without
msg += "\t [varname] = [varval]\n"
world.log << msg
- subsystems = master_controller.subsystems
\ No newline at end of file
+ subsystems = master_controller.subsystems
diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm
index c3d63b689a4..6c45cc35ae7 100644
--- a/code/controllers/subsystem/air.dm
+++ b/code/controllers/subsystem/air.dm
@@ -95,13 +95,11 @@ var/datum/subsystem/air/SSair
/datum/subsystem/air/proc/process_pipenets()
- var/i=1
for(var/thing in networks)
if(thing)
thing:process()
- ++i
continue
- networks.Cut(i, i+1)
+ networks.Remove(thing)
/datum/subsystem/air/proc/process_atmos_machinery()
diff --git a/code/controllers/subsystem/bots.dm b/code/controllers/subsystem/bots.dm
index 3a4d79d1cf3..6f71bb62d9b 100644
--- a/code/controllers/subsystem/bots.dm
+++ b/code/controllers/subsystem/bots.dm
@@ -14,11 +14,9 @@ var/datum/subsystem/bots/SSbot
/datum/subsystem/bots/fire()
var/seconds = wait * 0.1
- var/i=1
for(var/thing in processing)
if(thing && !thing:gc_destroyed)
spawn(-1)
thing:bot_process(seconds)
- ++i
continue
- processing.Cut(i, i+1)
\ No newline at end of file
+ processing.Remove(thing)
\ No newline at end of file
diff --git a/code/controllers/subsystem/diseases.dm b/code/controllers/subsystem/diseases.dm
index d28785d947f..76343a81bec 100644
--- a/code/controllers/subsystem/diseases.dm
+++ b/code/controllers/subsystem/diseases.dm
@@ -13,10 +13,8 @@ var/datum/subsystem/diseases/SSdisease
..("P:[processing.len]")
/datum/subsystem/diseases/fire()
- var/i=1
for(var/thing in processing)
if(thing)
thing:process()
- ++i
continue
- processing.Cut(i,i+1)
+ processing.Remove(thing)
diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm
index e2dfe59a2eb..a0ec2bab7c5 100644
--- a/code/controllers/subsystem/events.dm
+++ b/code/controllers/subsystem/events.dm
@@ -36,13 +36,11 @@ var/datum/subsystem/events/SSevent
/datum/subsystem/events/fire()
checkEvent()
- var/i=1
for(var/thing in running)
if(thing)
thing:process()
- ++i
continue
- running.Cut(i,i+1)
+ running.Remove(thing)
//checks if we should select a random event yet, and reschedules if necessary
@@ -66,6 +64,8 @@ var/datum/subsystem/events/SSevent
for(var/datum/round_event_control/E in control)
if(E.occurrences >= E.max_occurrences) continue
if(E.earliest_start >= world.time) continue
+ if(E.gamemode_blacklist.len && (ticker.mode.config_tag in E.gamemode_blacklist)) continue
+ if(E.gamemode_whitelist.len && !(ticker.mode.config_tag in E.gamemode_whitelist)) continue
if(E.holidayID)
if(!holidays || !holidays[E.holidayID]) continue
if(E.weight < 0) //for round-start events etc.
@@ -83,6 +83,8 @@ var/datum/subsystem/events/SSevent
for(var/datum/round_event_control/E in control)
if(E.occurrences >= E.max_occurrences) continue
if(E.earliest_start >= world.time) continue
+ if(E.gamemode_blacklist.len && (ticker.mode.config_tag in E.gamemode_blacklist)) continue
+ if(E.gamemode_whitelist.len && !(ticker.mode.config_tag in E.gamemode_whitelist)) continue
if(E.holidayID)
if(!holidays || !holidays[E.holidayID]) continue
sum_of_weights -= E.weight
@@ -96,7 +98,6 @@ var/datum/subsystem/events/SSevent
log_game("Random Event triggering: [E.name] ([E.typepath])")
return
-
/datum/round_event/proc/findEventArea() //Here's a nice proc to use to find an area for your event to land in!
var/list/safe_areas = list(
/area/turret_protected/ai,
diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm
index 4e617f76af9..3f93766c026 100644
--- a/code/controllers/subsystem/garbage.dm
+++ b/code/controllers/subsystem/garbage.dm
@@ -25,6 +25,7 @@ var/datum/subsystem/garbage_collector/SSgarbage
var/list/didntgc = list() // list of all types that have failed to GC associated with the number of times that's happened.
// the types are stored as strings
+ var/list/noqdelhint = list()// list of all types that do not return a QDEL_HINT
/datum/subsystem/garbage_collector/New()
NEW_SS_GLOBAL(SSgarbage)
@@ -61,7 +62,7 @@ var/datum/subsystem/garbage_collector/SSgarbage
if(GCd_at_time > time_to_kill)
break // Everything else is newer, skip them
- var/atom/A
+ var/datum/A
if (!istext(refID))
del(A)
else
@@ -76,7 +77,6 @@ var/datum/subsystem/garbage_collector/SSgarbage
else
++gcedlasttick
++totalgcs
-
queue.Cut(1, 2)
@@ -101,7 +101,6 @@ var/datum/subsystem/garbage_collector/SSgarbage
if (!A)
return
if (!istype(A))
- //warning("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
del(A)
else if (isnull(A.gc_destroyed))
// Let our friend know they're about to get fucked up.
@@ -121,7 +120,15 @@ var/datum/subsystem/garbage_collector/SSgarbage
del(A)
if (QDEL_HINT_PUTINPOOL) //qdel will put this object in the pool.
PlaceInPool(A,0)
+ if (QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion.
+ SSgarbage.Queue(A)
+ #ifdef TESTING
+ A.find_references()
+ #endif
else
+ if(!("[A.type]" in SSgarbage.noqdelhint))
+ SSgarbage.noqdelhint += "[A.type]"
+ testing("WARNING: [A.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.")
SSgarbage.Queue(A)
// Returns 1 if the object has been queued for deletion.
@@ -134,9 +141,8 @@ var/datum/subsystem/garbage_collector/SSgarbage
// Default implementation of clean-up code.
// This should be overridden to remove all references pointing to the object being destroyed.
-// Return true if the the GC controller should allow the object to continue existing. (Useful if pooling objects.)
+// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE.
/datum/proc/Destroy()
- //del(src)
tag = null
return QDEL_HINT_QUEUE
@@ -144,40 +150,44 @@ var/datum/subsystem/garbage_collector/SSgarbage
#ifdef TESTING
/client/var/running_find_references
+/datum/var/running_find_references
-/atom/verb/find_references()
+/datum/verb/find_references()
set category = "Debug"
set name = "Find References"
set background = 1
set src in world
- if(!usr || !usr.client)
- return
+ running_find_references = type
+ if(usr && usr.client)
+ if(usr.client.running_find_references)
+ testing("CANCELLED search for references to a [usr.client.running_find_references].")
+ usr.client.running_find_references = null
+ running_find_references = null
+ //restart the garbage collector
+ SSgarbage.can_fire = 1
+ SSgarbage.next_fire = world.time + world.tick_lag
+ return
- if(usr.client.running_find_references)
- testing("CANCELLED search for references to a [usr.client.running_find_references].")
- usr.client.running_find_references = null
- return
+ if(alert("Running this will create a lot of lag until it finishes. You can cancel it by running it again. Would you like to begin the search?", "Find References", "Yes", "No") == "No")
+ running_find_references = null
+ return
- if(alert("Running this will create a lot of lag until it finishes. You can cancel it by running it again. Would you like to begin the search?", "Find References", "Yes", "No") == "No")
- return
+ //this keeps the garbage collector from failing to collect objects being searched for in here
+ SSgarbage.can_fire = 0
- // Remove this object from the list of things to be auto-deleted.
- if(garbage)
- garbage.destroyed -= "\ref[src]"
+ if(usr && usr.client)
+ usr.client.running_find_references = type
- usr.client.running_find_references = type
testing("Beginning search for references to a [type].")
var/list/things = list()
for(var/client/thing)
- things += thing
+ things |= thing
for(var/datum/thing)
- things += thing
- for(var/atom/thing)
- things += thing
+ things |= thing
testing("Collected list of things in search for references to a [type]. ([things.len] Thing\s)")
for(var/datum/thing in things)
- if(!usr.client.running_find_references) return
+ if(usr && usr.client && !usr.client.running_find_references) return
for(var/varname in thing.vars)
var/variable = thing.vars[varname]
if(variable == src)
@@ -186,15 +196,31 @@ var/datum/subsystem/garbage_collector/SSgarbage
if(src in variable)
testing("Found [src.type] \ref[src] in [thing.type]'s [varname] list var.")
testing("Completed search for references to a [type].")
- usr.client.running_find_references = null
+ if(usr && usr.client)
+ usr.client.running_find_references = null
+ running_find_references = null
+
+ //restart the garbage collector
+ SSgarbage.can_fire = 1
+ SSgarbage.next_fire = world.time + world.tick_lag
/client/verb/purge_all_destroyed_objects()
set category = "Debug"
- if(garbage)
- while(garbage.destroyed.len)
- var/datum/o = locate(garbage.destroyed[1])
+ if(SSgarbage)
+ while(SSgarbage.queue.len)
+ var/datum/o = locate(SSgarbage.queue[1])
if(istype(o) && o.gc_destroyed)
del(o)
- garbage.dels++
- garbage.destroyed.Cut(1, 2)
-#endif
+ SSgarbage.totaldels++
+ SSgarbage.queue.Cut(1, 2)
+
+/datum/verb/qdel_then_find_references()
+ set category = "Debug"
+ set name = "qdel() then Find References"
+ set background = 1
+ set src in world
+
+ qdel(src)
+ if(!running_find_references)
+ find_references()
+#endif
\ No newline at end of file
diff --git a/code/controllers/subsystem/jobs.dm b/code/controllers/subsystem/jobs.dm
index e3d1114edbf..743d799374f 100644
--- a/code/controllers/subsystem/jobs.dm
+++ b/code/controllers/subsystem/jobs.dm
@@ -17,7 +17,8 @@ var/datum/subsystem/job/SSjob
if (zlevel)
return ..()
SetupOccupations()
- LoadJobs("config/jobs.txt")
+ if(config.load_jobs_from_txt)
+ LoadJobs()
..()
@@ -391,40 +392,13 @@ var/datum/subsystem/job/SSjob
break
-/datum/subsystem/job/proc/LoadJobs(jobsfile) //ran during round setup, reads info from jobs.txt -- Urist
- if(!config.load_jobs_from_txt)
- return 0
-
- var/list/jobEntries = file2list(jobsfile)
-
- for(var/job in jobEntries)
- if(!job)
- continue
-
- job = trim(job)
- if (!length(job))
- continue
-
- var/pos = findtext(job, "=")
- var/name = null
- var/value = null
-
- if(pos)
- name = copytext(job, 1, pos)
- value = copytext(job, pos + 1)
- else
- continue
-
- if(name && value)
- var/datum/job/J = GetJob(name)
- if(!J) continue
- J.total_positions = text2num(value)
- J.spawn_positions = text2num(value)
- if(name == "AI" || name == "Cyborg")//I dont like this here but it will do for now
- J.total_positions = 0
-
- return 1
-
+/datum/subsystem/job/proc/LoadJobs()
+ var/jobstext = return_file_text("config/jobs.txt")
+ for(var/datum/job/J in occupations)
+ var/regex = "[J.title]=(-1|\\d+),(-1|\\d+)"
+ var/datum/regex/results = regex_find(jobstext, regex)
+ J.total_positions = results.str(2)
+ J.spawn_positions = results.str(3)
/datum/subsystem/job/proc/HandleFeedbackGathering()
for(var/datum/job/job in occupations)
diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm
index 053241cd2e7..38389bf704f 100644
--- a/code/controllers/subsystem/lighting.dm
+++ b/code/controllers/subsystem/lighting.dm
@@ -71,13 +71,11 @@ var/datum/subsystem/lighting/SSlighting
if(z_level)
//we need to loop through to clear only shifted turfs from the list. or we will cause errors
- var/i=1
for(var/thing in changed_turfs)
var/turf/T = thing
if(T.z in z_start to z_finish)
- ++i
continue
- changed_turfs.Cut(i, i+1)
+ changed_turfs.Remove(thing)
else
changed_turfs.Cut()
diff --git a/code/controllers/subsystem/nanoUI.dm b/code/controllers/subsystem/nanoUI.dm
index feb60fce007..5ec4344fee7 100644
--- a/code/controllers/subsystem/nanoUI.dm
+++ b/code/controllers/subsystem/nanoUI.dm
@@ -38,12 +38,10 @@ var/datum/subsystem/nano/SSnano
/datum/subsystem/nano/fire()
- var/i=1
for(var/thing in SSnano.processing_uis)
if(thing)
var/datum/nanoui/ui = thing
if(ui.src_object && ui.user)
ui.process()
- ++i
continue
- processing_uis.Cut(i, i+1)
+ processing_uis.Remove(thing)
diff --git a/code/controllers/subsystem/objects.dm b/code/controllers/subsystem/objects.dm
index 35236b38fb6..24e206139b7 100644
--- a/code/controllers/subsystem/objects.dm
+++ b/code/controllers/subsystem/objects.dm
@@ -15,6 +15,7 @@ var/datum/subsystem/objects/SSobj
NEW_SS_GLOBAL(SSobj)
/datum/subsystem/objects/Initialize(timeofday, zlevel)
+ setupGenetics()
for(var/atom/movable/AM in world)
if (zlevel && AM.z != zlevel)
continue
@@ -31,16 +32,14 @@ var/datum/subsystem/objects/SSobj
/datum/subsystem/objects/fire()
- var/i=1
for(var/thing in SSobj.processing)
if(thing)
thing:process(wait)
- ++i
continue
- SSobj.processing.Cut(i, i+1)
+ SSobj.processing.Remove(thing)
for(var/obj/burningobj in SSobj.burning)
if(burningobj && (burningobj.burn_state == 1))
if(burningobj.burn_world_time < world.time)
burningobj.burn()
else
- SSobj.burning -= burningobj
\ No newline at end of file
+ SSobj.burning.Remove(burningobj)
\ No newline at end of file
diff --git a/code/controllers/subsystem/radio.dm b/code/controllers/subsystem/radio.dm
index 25f172bf9da..110f48d8f42 100644
--- a/code/controllers/subsystem/radio.dm
+++ b/code/controllers/subsystem/radio.dm
@@ -29,7 +29,7 @@ var/datum/subsystem/radio/radio_controller
frequency.remove_listener(device)
if(frequency.devices.len == 0)
- del(frequency)
+ qdel(frequency)
frequencies -= f_text
return 1
diff --git a/code/controllers/subsystem/shuttles.dm b/code/controllers/subsystem/shuttles.dm
index d578f1c501c..a539d401827 100644
--- a/code/controllers/subsystem/shuttles.dm
+++ b/code/controllers/subsystem/shuttles.dm
@@ -24,10 +24,13 @@ var/datum/subsystem/shuttle/SSshuttle
var/points_per_decisecond = 0.005 //points gained every decisecond
var/points_per_slip = 2 //points gained per slip returned
var/points_per_crate = 5 //points gained per crate returned
- var/points_per_intel = 100 //points gained per intel returned
+ var/points_per_intel = 250 //points gained per intel returned
var/points_per_plasma = 5 //points gained per plasma returned
+ var/points_per_design = 25 //points gained per max reliability research design returned (only for initilally unreliable designs)
var/centcom_message = "" //Remarks from Centcom on how well you checked the last order.
- var/list/discoveredPlants = list() //Unique typepaths for unusual things we've already sent CentComm, associated with their potencies
+ var/list/discoveredPlants = list() //Typepaths for unusual plants we've already sent CentComm, associated with their potencies
+ var/list/techLevels = list()
+ var/list/researchDesigns = list()
var/list/shoppinglist = list()
var/list/requestlist = list()
var/list/supply_packs = list()
@@ -61,15 +64,12 @@ var/datum/subsystem/shuttle/SSshuttle
/datum/subsystem/shuttle/fire()
points += points_per_decisecond * wait
-
- var/i=1
for(var/thing in mobile)
if(thing)
var/obj/docking_port/mobile/P = thing
P.check()
- ++i
continue
- mobile.Cut(i, i+1)
+ mobile.Remove(thing)
/datum/subsystem/shuttle/proc/getShuttle(id)
for(var/obj/docking_port/mobile/M in mobile)
@@ -109,7 +109,7 @@ var/datum/subsystem/shuttle/SSshuttle
user << "The emergency shuttle has been disabled by Centcom."
return
- call_reason = html_encode(trim(call_reason))
+ call_reason = trim(html_encode(call_reason))
if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH)
user << "You must provide a reason."
@@ -118,9 +118,9 @@ var/datum/subsystem/shuttle/SSshuttle
var/area/signal_origin = get_area(user)
var/emergency_reason = "\nNature of emergency:\n\n[call_reason]"
if(seclevel2num(get_security_level()) == SEC_LEVEL_RED) // There is a serious threat we gotta move no time to give them five minutes.
- emergency.request(null, 0.5, signal_origin, emergency_reason, 1)
+ emergency.request(null, 0.5, signal_origin, html_decode(emergency_reason), 1)
else
- emergency.request(null, 1, signal_origin, emergency_reason, 0)
+ emergency.request(null, 1, signal_origin, html_decode(emergency_reason), 0)
log_game("[key_name(user)] has called the shuttle.")
message_admins("[key_name_admin(user)] has called the shuttle.")
@@ -128,21 +128,23 @@ var/datum/subsystem/shuttle/SSshuttle
return
/datum/subsystem/shuttle/proc/cancelEvac(mob/user)
+ if(canRecall())
+ emergency.cancel(get_area(user))
+ log_game("[key_name(user)] has recalled the shuttle.")
+ message_admins("[key_name_admin(user)] has recalled the shuttle.")
+ return 1
+
+/datum/subsystem/shuttle/proc/canRecall()
if(emergency.mode != SHUTTLE_CALL)
return
-
if(ticker.mode.name == "meteor")
return
-
- if((seclevel2num(get_security_level()) == SEC_LEVEL_RED))
+ if(seclevel2num(get_security_level()) == SEC_LEVEL_RED)
if(emergency.timeLeft(1) < emergencyCallTime * 0.25)
return
- else if(emergency.timeLeft(1) < emergencyCallTime * 0.5)
- return
-
- emergency.cancel(get_area(user))
- log_game("[key_name(user)] has recalled the shuttle.")
- message_admins("[key_name_admin(user)] has recalled the shuttle.")
+ else
+ if(emergency.timeLeft(1) < emergencyCallTime * 0.5)
+ return
return 1
/datum/subsystem/shuttle/proc/autoEvac()
@@ -199,19 +201,6 @@ var/datum/subsystem/shuttle/SSshuttle
return 2
return 0 //dock successful
-
-/*
-/proc/push_mob_back(var/mob/living/L, var/dir)
- if(iscarbon(L) && isturf(L.loc))
- if(prob(88))
- var/turf/T = get_step(L, dir)
- if(T)
- for(var/obj/O in T) // For doors and such (kinda ugly but we can't have people opening doors)
- if(!O.CanPass(L, L.loc, 1))
- return
- L.Move(get_step(L, dir), dir)
-*/
-
/datum/supply_order
var/ordernum
var/datum/supply_packs/object = null
@@ -284,6 +273,12 @@ var/datum/subsystem/shuttle/SSshuttle
A:amount = object.amount
slip.info += "
[A.name]
" //add the item to the manifest (even if it was misplaced)
+ if(istype(Crate, /obj/structure/closet/critter)) // critter crates do not actually spawn mobs yet and have no contains var, but the manifest still needs to list them
+ var/obj/structure/closet/critter/CritCrate = Crate
+ if(CritCrate.content_mob)
+ var/mob/crittername = CritCrate.content_mob
+ slip.info += "
[initial(crittername.name)]
"
+
if((errors & MANIFEST_ERROR_ITEM))
//secure and large crates cannot lose items
if(findtext("[object.containertype]", "/secure/") || findtext("[object.containertype]","/largecrate/"))
@@ -306,7 +301,7 @@ var/datum/subsystem/shuttle/SSshuttle
var/obj/structure/largecrate/LC = Crate
LC.manifest = slip
LC.update_icon()
-
+
return Crate
/datum/subsystem/shuttle/proc/generateSupplyOrder(packId, _orderedby, _orderedbyRank, _comment)
@@ -327,11 +322,3 @@ var/datum/subsystem/shuttle/SSshuttle
return O
-/*
-/datum/subsystem/shuttle/proc/getShuttleFromArea(area/A)
- if(!A)
- return
- for(var/obj/docking_port/mobile/M in SSshuttle.mobile)
- if(M.areaInstance == A)
- return M
-*/
diff --git a/code/controllers/subsystem/shuttles/emergency.dm b/code/controllers/subsystem/shuttles/emergency.dm
index d3e9ad64a44..652cff69e34 100644
--- a/code/controllers/subsystem/shuttles/emergency.dm
+++ b/code/controllers/subsystem/shuttles/emergency.dm
@@ -106,7 +106,8 @@
if(time_left <= 0 && !SSshuttle.emergencyNoEscape)
//move each escape pod to its corresponding transit dock
for(var/obj/docking_port/mobile/pod/M in SSshuttle.mobile)
- M.enterTransit()
+ if(M.z == ZLEVEL_STATION) //Will not launch from the mine/planet
+ M.enterTransit()
//now move the actual emergency shuttle to its transit dock
enterTransit()
mode = SHUTTLE_ESCAPE
@@ -131,16 +132,13 @@
width = 3
height = 4
- New()
- if(id == "pod")
- WARNING("[type] id has not been changed from the default. Use the id convention \"pod1\" \"pod2\" etc.")
- ..()
+/obj/docking_port/mobile/pod/New()
+ if(id == "pod")
+ WARNING("[type] id has not been changed from the default. Use the id convention \"pod1\" \"pod2\" etc.")
+ ..()
- request()
- return
-
- cancel()
- return
+/obj/docking_port/mobile/pod/cancel()
+ return
/*
findTransitDock()
@@ -148,3 +146,27 @@
if(.) return .
return ..()
*/
+
+/obj/machinery/computer/shuttle/pod
+ name = "pod control computer"
+ admin_controlled = 1
+ shuttleId = "pod"
+ possible_destinations = "pod_asteroid"
+ icon = 'icons/obj/terminals.dmi'
+ icon_state = "dorm_available"
+ density = 0
+
+/obj/machinery/computer/shuttle/pod/update_icon()
+ return
+
+/obj/machinery/computer/shuttle/pod/emag_act(mob/user as mob)
+ user << " Access requirements overridden. The pod may now be launched manually at any time."
+ admin_controlled = 0
+ icon_state = "dorm_emag"
+
+/obj/docking_port/stationary/random/initialize()
+ ..()
+ var/target_area = /area/mine/unexplored
+ var/turfs = get_area_turfs(target_area)
+ var/T=pick(turfs)
+ src.loc = T
diff --git a/code/controllers/subsystem/shuttles/supply.dm b/code/controllers/subsystem/shuttles/supply.dm
index 8d0ca50207f..71873c539da 100644
--- a/code/controllers/subsystem/shuttles/supply.dm
+++ b/code/controllers/subsystem/shuttles/supply.dm
@@ -143,6 +143,32 @@
if(istype(thing, /obj/item/documents/syndicate))
++intel_count
+ // Sell tech levels
+ if(istype(thing, /obj/item/weapon/disk/tech_disk))
+ var/obj/item/weapon/disk/tech_disk/disk = thing
+ if(!disk.stored) continue
+ var/datum/tech/tech = disk.stored
+
+ var/cost = tech.getCost(SSshuttle.techLevels[tech.id])
+ if(cost)
+ SSshuttle.techLevels[tech.id] = tech.level
+ SSshuttle.points += cost
+ msg += "+[cost]: [tech.name] - new data. "
+
+ // Sell max reliablity designs
+ if(istype(thing, /obj/item/weapon/disk/design_disk))
+ var/obj/item/weapon/disk/design_disk/disk = thing
+ if(!disk.blueprint) continue
+ var/datum/design/design = disk.blueprint
+ if(design.id in SSshuttle.researchDesigns) continue
+
+ if(initial(design.reliability) < 100 && design.reliability >= 100)
+ // Maxed out reliability designs only.
+ SSshuttle.points += SSshuttle.points_per_design
+ SSshuttle.researchDesigns += design.id
+ msg += "+[SSshuttle.points_per_design]: Reliable [design.name] design. "
+
+ // Sell exotic plants
if(istype(thing, /obj/item/seeds))
var/obj/item/seeds/S = thing
if(S.rarity == 0) // Mundane species
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 98fecb0227c..46f76fb41cd 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -59,7 +59,6 @@ var/datum/subsystem/ticker/ticker
return ..()
if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase()
if(!syndicate_code_response) syndicate_code_response = generate_code_phrase()
- setupGenetics()
setupFactions()
..()
@@ -137,7 +136,7 @@ var/datum/subsystem/ticker/ticker
mode = config.pick_mode(master_mode)
if(!mode.can_start())
world << "Unable to start [mode.name]. Not enough players, [mode.required_players] players and [mode.required_enemies] eligible antagonists needed. Reverting to pre-game lobby."
- del(mode)
+ qdel(mode)
SSjob.ResetOccupations()
return 0
@@ -148,7 +147,7 @@ var/datum/subsystem/ticker/ticker
if(!Debug2)
if(!can_continue)
- del(mode)
+ qdel(mode)
world << "Error setting up [master_mode]. Reverting to pre-game lobby."
SSjob.ResetOccupations()
return 0
@@ -289,8 +288,8 @@ var/datum/subsystem/ticker/ticker
flick("station_intact",cinematic)
world << sound('sound/ambience/signal.ogg')
sleep(100)
- if(cinematic) del(cinematic)
- if(temp_buckle) del(temp_buckle)
+ if(cinematic) qdel(cinematic)
+ if(temp_buckle) qdel(temp_buckle)
return //Faster exit, since nothing happened
else //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
@@ -370,7 +369,7 @@ var/datum/subsystem/ticker/ticker
//Round statistics report
var/datum/station_state/end_state = new /datum/station_state()
end_state.count()
- var/station_integrity = min(round( 100.0 * start_state.score(end_state), 0.1), 100.0)
+ var/station_integrity = min(round( 100 * start_state.score(end_state), 0.1), 100)
world << " [TAB]Shift Duration: [round(world.time / 36000)]:[add_zero("[world.time / 600 % 60]", 2)]:[world.time / 100 % 6][world.time / 100 % 10]"
world << " [TAB]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[station_integrity]%"]"
diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm
index 1d9fb09f63b..67c5abe8b5c 100644
--- a/code/controllers/subsystem/timer.dm
+++ b/code/controllers/subsystem/timer.dm
@@ -43,6 +43,7 @@ var/datum/subsystem/timer/SStimer
/datum/timedevent/Destroy()
SStimer.processing -= src
+ return ..()
/proc/addtimer(thingToCall, procToCall, wait, argList = list())
if (!SStimer) //can't run timers before the mc has been created
diff --git a/code/controllers/subsystem/voting.dm b/code/controllers/subsystem/voting.dm
index 5d11eccd14a..1fce5abd014 100644
--- a/code/controllers/subsystem/voting.dm
+++ b/code/controllers/subsystem/voting.dm
@@ -116,7 +116,16 @@ var/datum/subsystem/vote/SSvote
else
master_mode = .
if(restart)
- world.Reboot("Restart vote successful.", "end_error", "restart vote")
+ var/active_admins = 0
+ for(var/client/C in admins)
+ if(!C.is_afk() && check_rights_for(C, R_SERVER))
+ active_admins = 1
+ break
+ if(!active_admins)
+ world.Reboot("Restart vote successful.", "end_error", "restart vote")
+ else
+ world << "Notice:Restart vote will not restart the server automatically because there are active admins on."
+ message_admins("A restart vote has passed, but there are active admins on with +server, so it has been canceled. If you wish, you may restart the server.")
return .
diff --git a/code/controllers/subsystems.dm b/code/controllers/subsystems.dm
index 88e3451a4d2..5c3c9a50f72 100644
--- a/code/controllers/subsystems.dm
+++ b/code/controllers/subsystems.dm
@@ -47,7 +47,7 @@
/datum/subsystem/proc/stat_entry(msg)
var/dwait = ""
if (dynamic_wait)
- dwait = "DWait:[wait]ds "
+ dwait = "DWait:[round(wait,0.1)]ds "
stat(name, "[round(cost,0.001)]ds\t[dwait][msg]")
@@ -59,4 +59,4 @@
//usually called via datum/subsystem/New() when replacing a subsystem (i.e. due to a recurring crash)
//should attempt to salvage what it can from the old instance of subsystem
-/datum/subsystem/proc/Recover()
\ No newline at end of file
+/datum/subsystem/proc/Recover()
diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm
index 0ce16230efc..74cd402bca3 100644
--- a/code/datums/ai_laws.dm
+++ b/code/datums/ai_laws.dm
@@ -134,7 +134,7 @@
src.ion += law
/datum/ai_laws/proc/clear_inherent_laws()
- del(src.inherent)
+ qdel(src.inherent)
src.inherent = list()
/datum/ai_laws/proc/add_supplied_law(number, law)
diff --git a/code/datums/computerfiles.dm b/code/datums/computerfiles.dm
deleted file mode 100644
index 37ba1ec51e0..00000000000
--- a/code/datums/computerfiles.dm
+++ /dev/null
@@ -1,7 +0,0 @@
-/datum
- computer
- var/name
- folder
- var/list/datum/computer/contents = list()
-
- file
\ No newline at end of file
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index d5ba85e6c91..095b53dd585 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -225,7 +225,7 @@ var/record_id_num = 1001
var/datum/data/record/M = new()
M.fields["id"] = id
M.fields["name"] = H.real_name
- M.fields["blood_type"] = H.blood_type
+ M.fields["blood_type"] = H.dna.blood_type
M.fields["b_dna"] = H.dna.unique_enzymes
M.fields["mi_dis"] = "None"
M.fields["mi_dis_d"] = "No minor disabilities have been declared."
@@ -255,7 +255,7 @@ var/record_id_num = 1001
L.fields["rank"] = H.mind.assigned_role
L.fields["age"] = H.age
L.fields["sex"] = H.gender
- L.fields["blood_type"] = H.blood_type
+ L.fields["blood_type"] = H.dna.blood_type
L.fields["b_dna"] = H.dna.unique_enzymes
L.fields["enzymes"] = H.dna.struc_enzymes
L.fields["identity"] = H.dna.uni_identity
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index 45f8ddab2f6..cd4363d9dff 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -252,6 +252,7 @@
body += ""
body += ""
body += ""
+ body += ""
if(iscarbon(D))
body += ""
body += ""
@@ -592,6 +593,29 @@ body
if(usr.client)
usr.client.cmd_assume_direct_control(M)
+ else if(href_list["offer_control"])
+ if(!check_rights(0)) return
+
+ var/mob/M = locate(href_list["offer_control"])
+ if(!istype(M))
+ usr << "This can only be used on instances of type /mob"
+ return
+ M << "Control of your mob has been offered to dead players."
+ log_admin("[key_name(usr)] has offered control of ([key_name(M)]) to ghosts.")
+ message_admins("[key_name_admin(usr)] has offered control of ([key_name_admin(M)]) to ghosts")
+ var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [M.real_name]?", "pAI", null, FALSE, 100)
+ var/mob/dead/observer/theghost = null
+
+ if(candidates.len)
+ theghost = pick(candidates)
+ M << "Your mob has been taken over by a ghost!"
+ message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)])")
+ M.ghostize()
+ M.key = theghost.key
+ else
+ M << "There were no ghosts willing to take control."
+ message_admins("No ghosts were willing to take control of [key_name_admin(M)])")
+
else if(href_list["delall"])
if(!check_rights(R_DEBUG|R_SERVER)) return
@@ -813,8 +837,7 @@ body
if(result)
var/newtype = species_list[result]
- hardset_dna(H, null, null, null, null, newtype)
- H.regenerate_icons()
+ H.set_species(newtype)
else if(href_list["purrbation"])
if(!check_rights(R_SPAWN)) return
@@ -828,7 +851,7 @@ body
usr << "Mob doesn't exist anymore"
return
- if(H.dna && H.dna.species.id == "human")
+ if(H.dna.species.id == "human")
if(H.dna.features["tail_human"] == "None" || H.dna.features["ears"] == "None")
usr << "Put [H] on purrbation."
H << "You suddenly feel valid."
diff --git a/code/datums/diseases/_disease.dm b/code/datums/diseases/_disease.dm
index 954446639f3..6b098310e6d 100644
--- a/code/datums/diseases/_disease.dm
+++ b/code/datums/diseases/_disease.dm
@@ -138,7 +138,7 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease
for(var/datum/disease/D in affected_mob.viruses)
if(D != src)
if(IsSame(D))
- del(D)
+ qdel(D)
if(holder == affected_mob)
if(affected_mob.stat != DEAD)
@@ -156,7 +156,7 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease
if(!(type in affected_mob.resistances))
affected_mob.resistances += type
remove_virus()
- del(src)
+ qdel(src)
/datum/disease/New()
diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm
index 8d5b977c3d7..94e808667ae 100644
--- a/code/datums/diseases/advance/advance.dm
+++ b/code/datums/diseases/advance/advance.dm
@@ -107,7 +107,7 @@ var/list/advance_cures = list(
if(resistance && !(id in affected_mob.resistances))
affected_mob.resistances[id] = id
remove_virus()
- del(src) //delete the datum to stop it processing
+ qdel(src) //delete the datum to stop it processing
// Returns the advance disease with a different reference memory.
/datum/disease/advance/Copy(process = 0)
diff --git a/code/datums/diseases/advance/symptoms/confusion.dm b/code/datums/diseases/advance/symptoms/confusion.dm
index 8f48fdab86a..198faec9fe4 100644
--- a/code/datums/diseases/advance/symptoms/confusion.dm
+++ b/code/datums/diseases/advance/symptoms/confusion.dm
@@ -35,6 +35,6 @@ Bonus
M << "[pick("You feel confused.", "You forgot what you were thinking about.")]"
else
M << "You are unable to think straight!"
- M.confused = min(100, M.confused + 2)
+ M.confused = min(100, M.confused + 8)
return
diff --git a/code/datums/diseases/advance/symptoms/genetics.dm b/code/datums/diseases/advance/symptoms/genetics.dm
index cb730215ee9..8389c46b07f 100644
--- a/code/datums/diseases/advance/symptoms/genetics.dm
+++ b/code/datums/diseases/advance/symptoms/genetics.dm
@@ -31,7 +31,8 @@ Bonus
..()
if(prob(SYMPTOM_ACTIVATION_PROB * 5)) // 15% chance
var/mob/living/carbon/M = A.affected_mob
- if(!check_dna_integrity(M)) return
+ if(!M.has_dna())
+ return
switch(A.stage)
if(4, 5)
M << "[pick("Your skin feels itchy.", "You feel light headed.")]"
@@ -44,7 +45,7 @@ Bonus
possible_mutations = (bad_mutations | not_good_mutations) - mutations_list[RACEMUT]
var/mob/living/carbon/M = A.affected_mob
if(M)
- if(!check_dna_integrity(M))
+ if(!M.has_dna())
return
archived_dna = M.dna.struc_enzymes
@@ -52,37 +53,7 @@ Bonus
/datum/symptom/genetic_mutation/End(datum/disease/advance/A)
var/mob/living/carbon/M = A.affected_mob
if(M && archived_dna)
- if(!check_dna_integrity(M))
+ if(!M.has_dna())
return
- hardset_dna(M, se = archived_dna)
- domutcheck(M)
-/*
-//////////////////////////////////////
-
-DNA Aide
-
- Very very very very noticable.
- Lowers resistance tremendously.
- Decreases stage speed tremendously.
- Decreases transmittablity tremendously.
- Fatal Level.
-
-Bonus
- Cleans the DNA of a person and then randomly gives them a power..
-
-//////////////////////////////////////
-*/
-
-/datum/symptom/genetic_mutation/powers
-
- name = "Deoxyribonucleic Acid Aide"
- stealth = -7
- resistance = -7
- stage_speed = -7
- transmittable = -7
- level = 6
- severity = 0
-
-/datum/symptom/genetic_mutation/powers/Start(datum/disease/advance/A)
- ..()
- possible_mutations = good_mutations
\ No newline at end of file
+ M.dna.struc_enzymes = archived_dna
+ M.domutcheck()
diff --git a/code/datums/diseases/dna_spread.dm b/code/datums/diseases/dna_spread.dm
index eb38e8689af..1ee18603a61 100644
--- a/code/datums/diseases/dna_spread.dm
+++ b/code/datums/diseases/dna_spread.dm
@@ -43,7 +43,7 @@
affected_mob.adjustToxLoss(2)
affected_mob.updatehealth()
if(4)
- if(!src.transformed && !src.carrier)
+ if(!transformed && !carrier)
//Save original dna for when the disease is cured.
original_dna = new affected_mob.dna.type
affected_mob.dna.copy_dna(original_dna)
@@ -51,24 +51,22 @@
affected_mob << "You don't feel like yourself.."
var/datum/dna/transform_dna = strain_data["dna"]
- transform_dna.transfer_identity(affected_mob)
+ transform_dna.transfer_identity(affected_mob, transfer_SE = 1)
affected_mob.real_name = affected_mob.dna.real_name
+ affected_mob.updateappearance(mutcolor_update=1)
+ affected_mob.domutcheck()
- updateappearance(affected_mob)
- domutcheck(affected_mob)
-
- src.transformed = 1
- src.carrier = 1 //Just chill out at stage 4
+ transformed = 1
+ carrier = 1 //Just chill out at stage 4
return
/datum/disease/dnaspread/Del()
if (original_dna && transformed && affected_mob)
- original_dna.transfer_identity(affected_mob)
+ original_dna.transfer_identity(affected_mob, transfer_SE = 1)
affected_mob.real_name = affected_mob.dna.real_name
-
- updateappearance(affected_mob)
- domutcheck(affected_mob)
+ affected_mob.updateappearance(mutcolor_update=1)
+ affected_mob.domutcheck()
affected_mob << "You feel more like yourself."
..()
\ No newline at end of file
diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm
index 1b83792a13c..b5913c3e71a 100644
--- a/code/datums/diseases/transformation.dm
+++ b/code/datums/diseases/transformation.dm
@@ -201,9 +201,8 @@
if(3)
if(ishuman(affected_mob))
var/mob/living/carbon/human/human = affected_mob
- if(human.dna && human.dna.species.id != "slime")
- hardset_dna(human, null, null, null, null, /datum/species/slime)
- human.regenerate_icons()
+ if(human.dna.species.id != "slime")
+ human.set_species(/datum/species/slime)
/datum/disease/transformation/corgi
name = "The Barkening"
diff --git a/code/datums/gas_mixture.dm b/code/datums/gas_mixture.dm
index 277773ea3d5..ff91a69b1d6 100644
--- a/code/datums/gas_mixture.dm
+++ b/code/datums/gas_mixture.dm
@@ -321,7 +321,7 @@ What are the archived variables for?
trace_gases += corresponding
corresponding.moles += trace_gas.moles
-// del(giver)
+// qdel(giver)
return 1
/datum/gas_mixture/remove(amount)
diff --git a/code/datums/martial.dm b/code/datums/martial.dm
index 96d8726d596..2929c4b0a2e 100644
--- a/code/datums/martial.dm
+++ b/code/datums/martial.dm
@@ -27,34 +27,22 @@
/datum/martial_art/proc/basic_hit(mob/living/carbon/human/A,mob/living/carbon/human/D)
A.do_attack_animation(D)
- var/damage = rand(0,9)
+ var/damage = rand(0,9) + A.dna.species.punchmod
- var/atk_verb = "punch"
+ var/atk_verb = A.dna.species.attack_verb
if(D.lying)
atk_verb = "kick"
- else if(A.dna)
- atk_verb = A.dna.species.attack_verb
-
- if(A.dna)
- damage += A.dna.species.punchmod
if(!damage)
- if(A.dna)
- playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
- else
- playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
- D.visible_message("[A] has attempted to [atk_verb] [D]!")
- add_logs(A, D, "attempted to [atk_verb]")
- return 0
+ playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
+ D.visible_message("[A] has attempted to [atk_verb] [D]!")
+ add_logs(A, D, "attempted to [atk_verb]")
+ return 0
var/obj/item/organ/limb/affecting = D.get_organ(ran_zone(A.zone_sel.selecting))
var/armor_block = D.run_armor_check(affecting, "melee")
- if(A.dna)
- playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1)
- else
- playsound(D.loc, 'sound/weapons/punch1.ogg', 25, 1, -1)
-
+ playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1)
D.visible_message("[A] has [atk_verb]ed [D]!", \
"[A] has [atk_verb]ed [D]!")
@@ -104,24 +92,18 @@
var/atk_verb = pick("left hook","right hook","straight punch")
- var/damage = rand(5,8)
- if(A.dna)
- damage += A.dna.species.punchmod
+ var/damage = rand(5,8) + A.dna.species.punchmod
if(!damage)
- if(A.dna)
- playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
- else
- playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
- D.visible_message("[A] has attempted to hit [D] with a [atk_verb]!")
- add_logs(A, D, "attempted to hit", atk_verb)
- return 0
+ playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
+ D.visible_message("[A] has attempted to hit [D] with a [atk_verb]!")
+ add_logs(A, D, "attempted to hit", atk_verb)
+ return 0
var/obj/item/organ/limb/affecting = D.get_organ(ran_zone(A.zone_sel.selecting))
var/armor_block = D.run_armor_check(affecting, "melee")
- playsound(D.loc, 'sound/weapons/punch1.ogg', 25, 1, -1)
-
+ playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1)
D.visible_message("[A] has hit [D] with a [atk_verb]!", \
"[A] has hit [D] with a [atk_verb]!")
diff --git a/code/datums/material_container.dm b/code/datums/material_container.dm
index 6a7708ef46a..d7c5c307bc5 100644
--- a/code/datums/material_container.dm
+++ b/code/datums/material_container.dm
@@ -39,15 +39,19 @@
if(mat_list[MAT_BANANIUM])
materials[MAT_BANANIUM] = new /datum/material/bananium()
+/datum/material_container/Destroy()
+ owner = null
+ return ..()
+
//For inserting an amount of material
/datum/material_container/proc/insert_amount(amt, material_type = null)
if(amt > 0 && has_space(amt))
var/total_amount_saved = total_amount
if(material_type)
- for(var/datum/material/M in materials)
- if(M.material_type == material_type)
- M.amount += amt
- total_amount += amt
+ var/datum/material/M = materials[material_type]
+ if(M)
+ M.amount += amt
+ total_amount += amt
else
for(var/datum/material/M in materials)
M.amount += amt
@@ -56,9 +60,15 @@
return 0
/datum/material_container/proc/insert_stack(obj/item/stack/S, amt = 0)
- if(!amt)
+ if(amt <= 0)
+ return 0
+ if(amt > S.amount)
amt = S.amount
+
var/material_amt = get_item_material_amount(S)
+ if(!material_amt)
+ return 0
+
amt = min(amt, round(((max_amount - total_amount) / material_amt)))
if(!amt)
return 0
@@ -67,17 +77,18 @@
S.use(amt)
return amt
-/datum/material_container/proc/insert_item(obj/item/I)
+/datum/material_container/proc/insert_item(obj/item/I, multiplier = 1)
if(!I)
return 0
if(istype(I,/obj/item/stack))
- return insert_stack(I)
+ var/obj/item/stack/S = I
+ return insert_stack(I, S.amount)
var/material_amount = get_item_material_amount(I)
if(!material_amount || !has_space(material_amount))
return 0
- insert_materials(I)
+ insert_materials(I, multiplier)
return material_amount
/datum/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only
@@ -89,21 +100,21 @@
//For consuming material
//mats is a list of types of material to use and the corresponding amounts, example: list(MAT_METAL=100, MAT_GLASS=200)
-/datum/material_container/proc/use_amount(list/mats)
+/datum/material_container/proc/use_amount(list/mats, multiplier=1)
if(!mats || !mats.len)
return 0
var/datum/material/M
for(var/MAT in materials)
M = materials[MAT]
- if(M.amount < mats[MAT])
+ if(M.amount < (mats[MAT] * multiplier))
return 0
var/total_amount_save = total_amount
for(var/MAT in materials)
M = materials[MAT]
- M.amount -= mats[MAT]
- total_amount -= mats[MAT]
+ M.amount -= mats[MAT] * multiplier
+ total_amount -= mats[MAT] * multiplier
return total_amount_save - total_amount
@@ -120,7 +131,9 @@
//For spawning mineral sheets; internal use only
/datum/material_container/proc/retrieve(sheet_amt, datum/material/M)
- if(sheet_amt > 0 && M.amount >= (sheet_amt * MINERAL_MATERIAL_AMOUNT))
+ if(sheet_amt > 0)
+ if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT))
+ sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT)
var/count = 0
while(sheet_amt > MAX_STACK_SIZE)
@@ -155,6 +168,17 @@
/datum/material_container/proc/has_space(amt = 0)
return (total_amount + amt) <= max_amount
+/datum/material_container/proc/has_materials(list/mats, multiplier=1)
+ if(!mats || !mats.len)
+ return 0
+
+ var/datum/material/M
+ for(var/MAT in mats)
+ M = materials[MAT]
+ if(M.amount < (mats[MAT] * multiplier))
+ return 0
+ return 1
+
/datum/material_container/proc/amount2sheet(amt)
if(amt >= MINERAL_MATERIAL_AMOUNT)
return round(amt / MINERAL_MATERIAL_AMOUNT)
@@ -169,9 +193,6 @@
var/datum/material/M = materials[material_type]
return M ? M.amount : 0
-/datum/material_container/proc/can_insert(obj/item/I)
- return get_item_material_amount(I)
-
//returns the amount of material relevant to this container;
//if this container does not support glass, any glass in 'I' will not be taken into account
/datum/material_container/proc/get_item_material_amount(obj/item/I)
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index b2172da6dca..f84c04f531a 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -193,7 +193,7 @@
else if(istype(I, /obj/item/device/radio))
var/obj/item/device/radio/R = I
- R.traitor_frequency = 0.0
+ R.traitor_frequency = 0
/datum/mind/proc/remove_all_antag() //For the Lazy amongst us.
remove_changeling()
@@ -256,9 +256,9 @@
text += " Flash: give"
var/list/L = current.get_contents()
- var/obj/item/device/flash/flash = locate() in L
+ var/obj/item/device/assembly/flash/flash = locate() in L
if (flash)
- if(!flash.broken)
+ if(!flash.crit_fail)
text += "|take."
else
text += "|take|repair."
@@ -376,7 +376,7 @@
text += "YES|no"
if (objectives.len==0)
text += " Objectives are empty! Randomize!"
- if( changeling && changeling.absorbed_dna.len && (current.real_name != changeling.absorbed_dna[1]) )
+ if(changeling && changeling.stored_profiles.len && (current.real_name != changeling.first_prof.name) )
text += " Transform to initial appearance."
else
text += "yes|NO"
@@ -807,18 +807,19 @@
if("takeflash")
var/list/L = current.get_contents()
- var/obj/item/device/flash/flash = locate() in L
+ var/obj/item/device/assembly/flash/flash = locate() in L
if (!flash)
usr << "Deleting flash failed!"
qdel(flash)
if("repairflash")
var/list/L = current.get_contents()
- var/obj/item/device/flash/flash = locate() in L
+ var/obj/item/device/assembly/flash/flash = locate() in L
if (!flash)
usr << "Repairing flash failed!"
else
- flash.broken = 0
+ flash.crit_fail = 0
+ flash.update_icon()
@@ -971,14 +972,14 @@
usr << "The objectives for changeling [key] have been generated. You can edit them and anounce manually."
if("initialdna")
- if( !changeling || !changeling.absorbed_dna.len || !istype(current, /mob/living/carbon))
+ if( !changeling || !changeling.stored_profiles.len || !istype(current, /mob/living/carbon))
usr << "Resetting DNA failed!"
else
var/mob/living/carbon/C = current
- C.dna = changeling.absorbed_dna[1]
- C.real_name = C.dna.real_name
- updateappearance(C)
- domutcheck(C)
+ changeling.first_prof.dna.transfer_identity(C, transfer_SE=1)
+ C.real_name = changeling.first_prof.name
+ C.updateappearance(mutcolor_update=1)
+ C.domutcheck()
else if (href_list["nuclear"])
switch(href_list["nuclear"])
@@ -1372,7 +1373,7 @@
ticker.mode.greet_revolutionary(src,0)
var/list/L = current.get_contents()
- var/obj/item/device/flash/flash = locate() in L
+ var/obj/item/device/assembly/flash/flash = locate() in L
qdel(flash)
take_uplink()
var/fail = 0
@@ -1408,7 +1409,7 @@
var/mob/living/carbon/human/H = current
- hardset_dna(H,null,null,null,null,/datum/species/abductor,null)
+ H.set_species(/datum/species/abductor)
var/datum/species/abductor/S = H.dna.species
switch(role)
diff --git a/code/datums/modules.dm b/code/datums/modules.dm
index e52a644d157..af693456543 100644
--- a/code/datums/modules.dm
+++ b/code/datums/modules.dm
@@ -24,7 +24,7 @@ var/list/modules = list( // global associative list
var/mneed = mods.inmodlist(type) // find if this type has modules defined
if(!mneed) // not found in module list?
- del(src) // delete self, thus ending proc
+ qdel(src) // delete self, thus ending proc
var/needed = mods.getbitmask(type) // get a bitmask for the number of modules in this object
status = needed
diff --git a/code/datums/mutations.dm b/code/datums/mutations.dm
index b517e417d93..6129bdce06e 100644
--- a/code/datums/mutations.dm
+++ b/code/datums/mutations.dm
@@ -16,6 +16,9 @@
var/text_gain_indication = ""
var/text_lose_indication = ""
var/list/visual_indicators = list()
+ var/layer_used = MUTATIONS_LAYER //which mutation layer to use
+ var/list/species_allowed = list() //to restrict mutation to only certain species
+ var/health_req //minimum health required to acquire the mutation
/datum/mutation/human/proc/force_give(mob/living/carbon/human/owner)
set_block(owner)
@@ -33,7 +36,7 @@
return before + injection + after
/datum/mutation/human/proc/set_block(mob/living/carbon/owner, on = 1)
- if(owner && istype(owner) && owner.dna)
+ if(owner && owner.has_dna())
owner.dna.struc_enzymes = set_se(owner.dna.struc_enzymes, on)
/datum/mutation/human/proc/check_block_string(se_string)
@@ -49,23 +52,26 @@
. = on_losing(owner)
/datum/mutation/human/proc/on_acquiring(mob/living/carbon/human/owner)
- if(!owner || (src in owner.dna.mutations))
+ if(!owner || !istype(owner) || (src in owner.dna.mutations))
+ return 1
+ if(species_allowed.len && !species_allowed.Find(owner.dna.species.id))
+ return 1
+ if(health_req && owner.health < health_req)
return 1
owner.dna.mutations.Add(src)
- gain_indication(owner)
- owner << text_gain_indication
+ if(text_gain_indication)
+ owner << text_gain_indication
+ if(visual_indicators.len)
+ var/list/mut_overlay = list(get_visual_indicator(owner))
+ if(owner.overlays_standing[layer_used])
+ mut_overlay = owner.overlays_standing[layer_used]
+ mut_overlay |= get_visual_indicator(owner)
+ owner.remove_overlay(layer_used)
+ owner.overlays_standing[layer_used] = mut_overlay
+ owner.apply_overlay(layer_used)
-/datum/mutation/human/proc/gain_indication(mob/living/carbon/human/owner)
- owner.overlays.Add(visual_indicators)
-/*
- var/list/result_overlays = list()
- var/list/limbs = owner_get_limbs(NON_MECHANICAL|NON_AMPUTATED) //I dunno how its done by RR but i assume something like this, proc that returns the list of limbs based on what types of limbs to return in argument
- for(var/obj/limb/L in limbs)
- result_overlays[L.identificator] = visual_indicators[L.identificator] //visual_indicators is where overlays icons are stored, they are all created on new of each mutation, i assume you will change it to linked list for easyness, but for now its just a list
- return owner.redraw_overlays(result_overlays, MUTATION_LAYER) //Currently mutations draw the overlays themselves but i assume if dismemberment will be overriding lots of shit like maybe clothes or something else mutations will just pass the shit to redraw proc
-*/
-/datum/mutation/human/proc/lose_indication(mob/living/carbon/human/owner)
- owner.overlays.Remove(visual_indicators)
+/datum/mutation/human/proc/get_visual_indicator(mob/living/carbon/human/owner)
+ return
/datum/mutation/human/proc/on_attack_hand(mob/living/carbon/human/owner, atom/target)
return
@@ -80,9 +86,17 @@
return
/datum/mutation/human/proc/on_losing(mob/living/carbon/human/owner)
- if(owner && (owner.dna.mutations.Remove(src)))
- lose_indication(owner)
- owner << text_lose_indication
+ if(owner && istype(owner) && (owner.dna.mutations.Remove(src)))
+ if(text_lose_indication)
+ owner << text_lose_indication
+ if(visual_indicators.len)
+ var/list/mut_overlay = list()
+ if(owner.overlays_standing[layer_used])
+ mut_overlay = owner.overlays_standing[layer_used]
+ owner.remove_overlay(layer_used)
+ mut_overlay.Remove(get_visual_indicator(owner))
+ owner.overlays_standing[layer_used] = mut_overlay
+ owner.apply_overlay(layer_used)
return 0
return 1
@@ -100,6 +114,8 @@
get_chance = 15
lowest_value = 256 * 12
text_gain_indication = "Your muscles hurt!"
+ species_allowed = list("human") //no skeleton/lizard hulk
+ health_req = 25
/datum/mutation/human/hulk/New()
..()
@@ -107,16 +123,17 @@
visual_indicators |= image("icon"='icons/effects/genetics.dmi', "icon_state"="hulk_m_s", "layer"=-MUTATIONS_LAYER)
/datum/mutation/human/hulk/on_acquiring(mob/living/carbon/human/owner)
- if(..()) return
+ if(..())
+ return
var/status = CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH
owner.status_flags &= ~status
/datum/mutation/human/hulk/on_attack_hand(mob/living/carbon/human/owner, atom/target)
return target.attack_hulk(owner)
-/datum/mutation/human/hulk/gain_indication(mob/living/carbon/human/owner)
+/datum/mutation/human/hulk/get_visual_indicator(mob/living/carbon/human/owner)
var/g = (owner.gender == FEMALE) ? 1 : 2
- owner.overlays += visual_indicators[g]
+ return visual_indicators[g]
/datum/mutation/human/hulk/on_life(mob/living/carbon/human/owner)
if(owner.health < 25)
@@ -147,6 +164,9 @@
..()
visual_indicators |= image("icon"='icons/effects/genetics.dmi', "icon_state"="telekinesishead_s", "layer"=-MUTATIONS_LAYER)
+/datum/mutation/human/telekinesis/get_visual_indicator(mob/living/carbon/human/owner)
+ return visual_indicators[1]
+
/datum/mutation/human/telekinesis/on_ranged_attack(mob/living/carbon/human/owner, atom/target)
target.attack_tk(owner)
@@ -162,6 +182,9 @@
..()
visual_indicators |= image("icon"='icons/effects/genetics.dmi', "icon_state"="fire_s", "layer"=-MUTATIONS_LAYER)
+/datum/mutation/human/cold_resistance/get_visual_indicator(mob/living/carbon/human/owner)
+ return visual_indicators[1]
+
/datum/mutation/human/cold_resistance/on_life(mob/living/carbon/human/owner)
if(owner.getFireLoss())
if(prob(1))
@@ -176,7 +199,8 @@
text_gain_indication = "The walls suddenly disappear!"
/datum/mutation/human/x_ray/on_acquiring(mob/living/carbon/human/owner)
- if(..()) return
+ if(..())
+ return
on_life(owner)
/datum/mutation/human/x_ray/on_life(mob/living/carbon/human/owner)
@@ -214,10 +238,12 @@
text_gain_indication = "You get a headache."
/datum/mutation/human/epilepsy/on_life(mob/living/carbon/human/owner)
- if ((prob(1) && owner.paralysis < 1))
+ if((prob(1) && owner.paralysis < 1))
owner.visible_message("[owner] starts having a seizure!", "You have a seizure!")
owner.Paralyse(10)
owner.Jitter(1000)
+ spawn(90)
+ owner.jitteriness = 10
/datum/mutation/human/bad_dna
@@ -251,6 +277,23 @@
owner.drop_item()
owner.emote("cough")
+/datum/mutation/human/dwarfism
+
+ name = "Dwarfism"
+ quality = MINOR_NEGATIVE
+ text_gain_indication = "Everything around you seems to grow.."
+ text_lose_indication = "Everything around you seems to shrink.."
+
+/datum/mutation/human/dwarfism/on_acquiring(mob/living/carbon/human/owner)
+ if(..()) return
+ owner.resize = 0.8
+ owner.visible_message("[owner] suddenly shrinks!")
+
+/datum/mutation/human/dwarfism/on_losing(mob/living/carbon/human/owner)
+ if(..()) return
+ owner.resize = 1.25
+ owner.visible_message("[owner] suddenly grows!")
+
/datum/mutation/human/clumsy
name = "Clumsiness"
@@ -333,19 +376,13 @@
quality = NEGATIVE
/datum/mutation/human/race/on_acquiring(mob/living/carbon/human/owner)
- if(..()) return
- . = owner.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
-
-/datum/mutation/human/race/gain_indication(mob/living/carbon/human/owner)
- return
-
-/datum/mutation/human/race/lose_indication(mob/living/carbon/monkey/owner)
- return
-
-/datum/mutation/human/race/on_losing(mob/living/carbon/monkey/owner)
if(..())
return
- . = owner.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
+ . = owner.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
+
+/datum/mutation/human/race/on_losing(mob/living/carbon/monkey/owner)
+ if(owner && istype(owner) && (owner.dna.mutations.Remove(src)))
+ . = owner.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
/datum/mutation/human/stealth
@@ -364,7 +401,8 @@
if(T.lighting_lumcount <= 2)
owner.alpha -= 25
else
- owner.alpha = round(255 * 0.80)
+ if(!owner.dna.check_mutation(CHAMELEON))
+ owner.alpha = round(255 * 0.80)
/datum/mutation/human/stealth/on_losing(mob/living/carbon/human/owner)
if(..())
@@ -582,15 +620,42 @@
message = replacetext(message," muh valids "," getting my kicks ")
return trim(message)
-
/datum/mutation/human/laser_eyes
-
name = "Laser Eyes"
quality = POSITIVE
dna_block = NON_SCANNABLE
text_gain_indication = "You feel pressure building up behind your eyes."
+ layer_used = FRONT_MUTATIONS_LAYER
+
+/datum/mutation/human/laser_eyes/New()
+ ..()
+ visual_indicators |= image("icon"='icons/effects/genetics.dmi', "icon_state"="lasereyes_s", "layer"=-FRONT_MUTATIONS_LAYER)
+
+/datum/mutation/human/laser_eyes/get_visual_indicator(mob/living/carbon/human/owner)
+ return visual_indicators[1]
/datum/mutation/human/laser_eyes/on_ranged_attack(mob/living/carbon/human/owner, atom/target)
if(owner.a_intent == "harm")
owner.LaserEyes(target)
+
+/mob/living/carbon/proc/update_mutations_overlay()
+ return
+
+/mob/living/carbon/human/update_mutations_overlay()
+ for(var/datum/mutation/human/CM in dna.mutations)
+ if(CM.species_allowed.len && !CM.species_allowed.Find(dna.species.id))
+ CM.force_lose(src) //shouldn't have that mutation at all
+ continue
+ if(CM.visual_indicators.len)
+ var/list/mut_overlay = list()
+ if(overlays_standing[CM.layer_used])
+ mut_overlay = overlays_standing[CM.layer_used]
+ var/image/V = CM.get_visual_indicator(src)
+ if(!mut_overlay.Find(V)) //either we lack the visual indicator or we have the wrong one
+ remove_overlay(CM.layer_used)
+ for(var/image/I in CM.visual_indicators)
+ mut_overlay.Remove(I)
+ mut_overlay |= V
+ overlays_standing[CM.layer_used] = mut_overlay
+ apply_overlay(CM.layer_used)
diff --git a/code/datums/outfit.dm b/code/datums/outfit.dm
new file mode 100644
index 00000000000..80da62ee49e
--- /dev/null
+++ b/code/datums/outfit.dm
@@ -0,0 +1,75 @@
+/datum/outfit
+ var/name = "Naked"
+
+ var/uniform = null
+ var/suit = null
+ var/back = null
+ var/belt = null
+ var/gloves = null
+ var/shoes = null
+ var/head = null
+ var/mask = null
+ var/ears = null
+ var/glasses = null
+ var/id = null
+ var/l_pocket = null
+ var/r_pocket = null
+ var/suit_store = null
+ var/r_hand = null
+ var/l_hand = null
+ var/list/backpack_contents = list() // In the list(path=count,otherpath=count) format
+
+/datum/outfit/proc/pre_equip(mob/living/carbon/human/H)
+ //to be overriden for customization depending on client prefs,species etc
+ return
+
+/datum/outfit/proc/post_equip(mob/living/carbon/human/H)
+ //to be overriden for toggling internals, id binding, access etc
+ return
+
+/datum/outfit/proc/equip(mob/living/carbon/human/H)
+ pre_equip(H)
+
+ //Start with uniform,suit,backpack for additional slots
+ if(uniform)
+ H.equip_to_slot_or_del(new uniform(H),slot_w_uniform)
+ if(suit)
+ H.equip_to_slot_or_del(new suit(H),slot_wear_suit)
+ if(back)
+ H.equip_to_slot_or_del(new back(H),slot_back)
+ if(belt)
+ H.equip_to_slot_or_del(new belt(H),slot_belt)
+ if(gloves)
+ H.equip_to_slot_or_del(new gloves(H),slot_gloves)
+ if(shoes)
+ H.equip_to_slot_or_del(new shoes(H),slot_shoes)
+ if(head)
+ H.equip_to_slot_or_del(new head(H),slot_head)
+ if(mask)
+ H.equip_to_slot_or_del(new mask(H),slot_wear_mask)
+ if(ears)
+ H.equip_to_slot_or_del(new ears(H),slot_ears)
+ if(glasses)
+ H.equip_to_slot_or_del(new glasses(H),slot_glasses)
+ if(id)
+ H.equip_to_slot_or_del(new id(H),slot_wear_id)
+ if(l_pocket)
+ H.equip_to_slot_or_del(new l_pocket(H),slot_l_store)
+ if(r_pocket)
+ H.equip_to_slot_or_del(new r_pocket(H),slot_r_store)
+ if(suit_store)
+ H.equip_to_slot_or_del(new suit_store(H),slot_s_store)
+
+ if(l_hand)
+ H.put_in_l_hand(new l_hand(H))
+ if(r_hand)
+ H.put_in_r_hand(new r_hand(H))
+
+ for(var/path in backpack_contents)
+ var/number = backpack_contents[path]
+ for(var/i=0,iThere must be a nearby source of blood!"
+
+/obj/effect/proc_holder/spell/bloodcrawl/perform(obj/effect/decal/cleanable/target, recharge = 1, mob/living/user = usr)
+ if(istype(user))
+ if(phased)
+ if(user.phasein(target))
+ phased = 0
+ else
+ if(user.phaseout(target))
+ phased = 1
+ start_recharge()
+ return
+ revert_cast()
+ user << "You are unable to blood crawl!"
diff --git a/code/datums/spells/conjure.dm b/code/datums/spells/conjure.dm
index c21e37113b7..042243045a6 100644
--- a/code/datums/spells/conjure.dm
+++ b/code/datums/spells/conjure.dm
@@ -46,11 +46,11 @@
return
-/obj/effect/proc_holder/spell/aoe_turf/conjure/summonEdSwarm //test purposes
+/obj/effect/proc_holder/spell/aoe_turf/conjure/summonEdSwarm //test purposes - Also a lot of fun
name = "Dispense Wizard Justice"
desc = "This spell dispenses wizard justice."
summon_type = list(/obj/machinery/bot/ed209)
summon_amt = 10
range = 3
- newVars = list("emagged" = 2,"name" = "Wizard's Justicebot")
\ No newline at end of file
+ newVars = list("emagged" = 2, "remote_disabled" = 1,"shoot_sound" = 'sound/weapons/laser.ogg',"projectile" = /obj/item/projectile/beam, "declare_arrests" = 0,"name" = "Wizard's Justicebot")
\ No newline at end of file
diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm
index 6f5247e8e92..664bf001425 100644
--- a/code/datums/spells/ethereal_jaunt.dm
+++ b/code/datums/spells/ethereal_jaunt.dm
@@ -88,7 +88,7 @@
// Eject contents if deleted somehow
for(var/atom/movable/AM in src)
AM.loc = get_turf(src)
- ..()
+ return ..()
/obj/effect/dummy/spell_jaunt/relaymove(var/mob/user, direction)
if (!src.canmove || reappearing || !direction) return
diff --git a/code/datums/spells/genetic.dm b/code/datums/spells/genetic.dm
index e77e3e69ccf..969372b1203 100644
--- a/code/datums/spells/genetic.dm
+++ b/code/datums/spells/genetic.dm
@@ -18,6 +18,8 @@
/obj/effect/proc_holder/spell/targeted/genetic/cast(list/targets)
playMagSound()
for(var/mob/living/carbon/target in targets)
+ if(!target.dna)
+ continue
for(var/A in mutations)
target.dna.add_mutation(A)
target.disabilities |= disabilities
diff --git a/code/datums/spells/knock.dm b/code/datums/spells/knock.dm
index 45fd66af320..6b772162c7b 100644
--- a/code/datums/spells/knock.dm
+++ b/code/datums/spells/knock.dm
@@ -20,5 +20,9 @@
if(istype(door,/obj/machinery/door/airlock))
door:locked = 0
door.open()
+ for(var/obj/structure/closet/C in T.contents)
+ spawn(1)
+ C.locked = 0
+ C.open()
return
\ No newline at end of file
diff --git a/code/datums/spells/lichdom.dm b/code/datums/spells/lichdom.dm
index a6ace565803..f199a06048f 100644
--- a/code/datums/spells/lichdom.dm
+++ b/code/datums/spells/lichdom.dm
@@ -38,7 +38,7 @@
charge_counter = charge_max
return
- if(!marked_item.loc) //Wait nevermind
+ if(!marked_item || qdeleted(marked_item)) //Wait nevermind
user << "Your phylactery is gone!"
return
@@ -55,7 +55,7 @@
lich.real_name = user.mind.name
user.mind.transfer_to(lich)
- hardset_dna(lich,null,null,lich.real_name,null,/datum/species/skeleton)
+ lich.hardset_dna(null,null,lich.real_name,null,/datum/species/skeleton)
lich << "Your bones clatter and shutter as they're pulled back into this world!"
charge_max += 600
var/mob/old_body = current_body
@@ -98,7 +98,7 @@
marked_item.desc = "A terrible aura surrounds this item, its very existence is offensive to life itself..."
marked_item.color = "#003300"
user << "With a hideous feeling of emptiness you watch in horrified fascination as skin sloughs off bone! Blood boils, nerves disintegrate, eyes boil in their sockets! As your organs crumble to dust in your fleshless chest you come to terms with your choice. You're a lich!"
- hardset_dna(user, null, null, null, null, /datum/species/skeleton)
+ user.set_species(/datum/species/skeleton)
current_body = user.mind.current
if(ishuman(user))
var/mob/living/carbon/human/H = user
diff --git a/code/datums/spells/trigger.dm b/code/datums/spells/trigger.dm
index 684f51159a6..3988f3bae16 100644
--- a/code/datums/spells/trigger.dm
+++ b/code/datums/spells/trigger.dm
@@ -17,7 +17,7 @@
qdel(spell)
linked_spells = null
starting_spells = null
- ..()
+ return ..()
/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets)
playMagSound()
diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm
index 20323fc1f8a..75d971cced4 100644
--- a/code/datums/spells/wizard.dm
+++ b/code/datums/spells/wizard.dm
@@ -41,7 +41,6 @@
clothes_req = 1
invocation = "BIRUZ BENNAR"
invocation_type = "shout"
- message = "You feel strong! You feel a pressure building behind your eyes!"
range = -1
include_user = 1
centcom_cancast = 0
@@ -157,6 +156,20 @@
cast_sound = "sound/magic/ForceWall.ogg"
+/obj/effect/proc_holder/spell/aoe_turf/conjure/timestop
+ name = "Stop Time"
+ desc = "This spell stops time for everyone except for you, allowing you to move freely while your enemies and even projectiles are frozen."
+ charge_max = 300
+ clothes_req = 1
+ invocation = "TOKI WO TOMARE"
+ invocation_type = "shout"
+ range = 0
+ cooldown_min = 90
+ summon_amt = 1
+ action_icon_state = "time"
+
+ summon_type = list(/obj/effect/timestop/wizard)
+
/obj/effect/proc_holder/spell/aoe_turf/conjure/carp
name = "Summon Carp"
desc = "This spell conjures a simple carp."
@@ -234,7 +247,7 @@
sound="sound/magic/Blind.ogg"
/obj/effect/proc_holder/spell/targeted/genetic/blind
- disabilities = 1
+ disabilities = BLIND
duration = 300
sound="sound/magic/Blind.ogg"
@@ -319,4 +332,4 @@
var/mob/living/M = AM
M.Weaken(2)
M << "You're thrown back by a mystical force!"
- spawn(0) AM.throw_at(throwtarget, ((Clamp((maxthrow - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time.
\ No newline at end of file
+ spawn(0) 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/datums/supplypacks.dm b/code/datums/supplypacks.dm
index 5d0e6fb95a0..af79e3c170a 100644
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -233,6 +233,17 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
cost = 10
containername = "disabler crate"
+/datum/supply_packs/security/forensics
+ name = "Forensics Crate"
+ contains = list(/obj/item/device/detective_scanner,
+ /obj/item/weapon/storage/box/evidence,
+ /obj/item/device/camera,
+ /obj/item/device/taperecorder,
+ /obj/item/toy/crayon/white,
+ /obj/item/clothing/head/det_hat)
+ cost = 20
+ containername ="forensics crate"
+
///// Armory stuff
/datum/supply_packs/security/armory
@@ -317,6 +328,23 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
containername = "incendiary weapons crate"
access = access_heads
+/datum/supply_packs/security/armory/wt550
+ name = "WT-550 Auto Rifle Crate"
+ contains = list(/obj/item/weapon/gun/projectile/automatic/wt550,
+ /obj/item/weapon/gun/projectile/automatic/wt550)
+ cost = 40
+ containername = "auto rifle crate"
+
+/datum/supply_packs/security/armory/wt550ammo
+ name = "WT-550 Rifle Ammo Crate"
+ contains = list(/obj/item/ammo_box/magazine/wt550m9,
+ /obj/item/ammo_box/magazine/wt550m9,
+ /obj/item/ammo_box/magazine/wt550m9,
+ /obj/item/ammo_box/magazine/wt550m9,
+ /obj/item/ammo_box/magazine/wt550m9)
+ cost = 40
+ containername = "auto rifle ammo crate"
+
/////// Implants & etc
/datum/supply_packs/security/armory/loyalty
@@ -470,7 +498,7 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/obj/item/solar_assembly,
/obj/item/solar_assembly, // 21 Solar Assemblies. 1 Extra for the controller
/obj/item/weapon/circuitboard/solar_control,
- /obj/item/weapon/tracker_electronics,
+ /obj/item/weapon/electronics/tracker,
/obj/item/weapon/paper/solar)
cost = 20
containername = "solar pack crate"
@@ -748,6 +776,8 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/obj/item/weapon/reagent_containers/food/condiment/rice,
/obj/item/weapon/reagent_containers/food/condiment/milk,
/obj/item/weapon/reagent_containers/food/condiment/soymilk,
+ /obj/item/weapon/reagent_containers/food/condiment/saltshaker,
+ /obj/item/weapon/reagent_containers/food/condiment/peppermill,
/obj/item/weapon/storage/fancy/egg_box,
/obj/item/weapon/reagent_containers/food/condiment/enzyme,
/obj/item/weapon/reagent_containers/food/condiment/sugar,
@@ -1053,11 +1083,11 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/datum/supply_packs/misc/posters
name = "Corporate Posters Crate"
- contains = list(/obj/item/weapon/contraband/poster/legit,
- /obj/item/weapon/contraband/poster/legit,
- /obj/item/weapon/contraband/poster/legit,
- /obj/item/weapon/contraband/poster/legit,
- /obj/item/weapon/contraband/poster/legit)
+ contains = list(/obj/item/weapon/poster/legit,
+ /obj/item/weapon/poster/legit,
+ /obj/item/weapon/poster/legit,
+ /obj/item/weapon/poster/legit,
+ /obj/item/weapon/poster/legit)
cost = 8
containername = "Corporate Posters Crate"
@@ -1211,7 +1241,7 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/datum/supply_packs/misc/randomised/contraband
num_contained = 5
- contains = list(/obj/item/weapon/contraband/poster,
+ contains = list(/obj/item/weapon/poster/contraband,
/obj/item/weapon/storage/fancy/cigarettes/dromedaryco,
/obj/item/weapon/storage/fancy/cigarettes/cigpack_shadyjims)
name = "Contraband Crate"
@@ -1219,6 +1249,26 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
containername = "crate" //let's keep it subtle, eh?
contraband = 1
+/datum/supply_packs/misc/randomised/toys
+ name = "Toy Crate"
+ num_contained = 5
+ contains = list(/obj/item/toy/spinningtoy,
+ /obj/item/toy/sword,
+ /obj/item/toy/foamblade,
+ /obj/item/toy/AI,
+ /obj/item/toy/owl,
+ /obj/item/toy/griffin,
+ /obj/item/toy/nuke,
+ /obj/item/toy/minimeteor,
+ /obj/item/toy/carpplushie,
+ /obj/item/weapon/coin/antagtoken,
+ /obj/item/stack/tile/fakespace,
+ /obj/item/weapon/gun/projectile/shotgun/toy/crossbow,
+ /obj/item/toy/redbutton)
+
+ cost = 50 // or play the arcade machines ya lazy bum
+ containername ="toy crate"
+
/datum/supply_packs/misc/autodrobe
name = "Autodrobe Supply Crate"
contains = list(/obj/item/weapon/vending_refill/autodrobe,
@@ -1280,3 +1330,4 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
cost = 40
containername = "foam force pistols crate"
contraband = 1
+
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index ebd3e3f3f4d..a663a616313 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -100,7 +100,7 @@ var/list/uplink_items = list()
category = "Conspicuous and Dangerous Weapons"
/datum/uplink_item/dangerous/pistol
- name = "Syndicate Pistol"
+ name = "FK-69 Pistol"
desc = "A small, easily concealable handgun that uses 10mm auto rounds in 8-round magazines and is compatible with suppressors."
item = /obj/item/weapon/gun/projectile/automatic/pistol
cost = 9
@@ -146,8 +146,8 @@ var/list/uplink_items = list()
/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 fires bolts tipped with a paralyzing toxin collected from a rare organism. \
- The bow generates bolts using an internal power source but must be manually charged between shots."
+ 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 amount of bolts, but must be manually recharged with each shot."
item = /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow
cost = 12
excludefrom = list(/datum/game_mode/nuclear,/datum/game_mode/gang)
@@ -157,13 +157,14 @@ var/list/uplink_items = list()
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/weapon/flamethrower/full/tank
- cost = 11
+ cost = 4
gamemodes = list(/datum/game_mode/nuclear,/datum/game_mode/gang)
surplus = 40
/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."
+ 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. One can combine two \
+ energy swords to create a double energy sword, which must be wielded in two hands but is more robust and deflects all energy projectiles."
item = /obj/item/weapon/melee/energy/sword/saber
cost = 8
@@ -175,7 +176,7 @@ var/list/uplink_items = list()
/datum/uplink_item/dangerous/syndicate_minibomb
name = "Syndicate Minibomb"
- desc = "The Minibomb is a grenade with a five-second fuse."
+ 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/weapon/grenade/syndieminibomb
cost = 6
@@ -243,6 +244,13 @@ var/list/uplink_items = list()
if(istype(T))
T.TC_cost = cost
+/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/weapon/storage/box/syndie_kit/guardian
+ excludefrom = list(/datum/game_mode/nuclear,/datum/game_mode/gang)
+ cost = 12
+
// AMMUNITION
/datum/uplink_item/ammo
@@ -303,10 +311,10 @@ var/list/uplink_items = list()
cost = 2
gamemodes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/ammo/bulltoxin
- name = "Drum Magazine - 12g Bioterror"
- desc = "An alternative 8-round toxic magazine for use in the Bulldog shotgun. Contains debilitating toxins to make your target die an excruciatingly rapid death."
- item = /obj/item/ammo_box/magazine/m12g/bioterror
+/datum/uplink_item/ammo/bioterror
+ name = "Box of Bioterror Syringes"
+ desc = "A box full of preloaded syringes, containing various chemicals that seize up the victim's motor and broca systems, making it impossible for them to move or speak for some time."
+ item = /obj/item/weapon/storage/box/syndie_kit/bioterror
cost = 6
gamemodes = list(/datum/game_mode/nuclear)
@@ -332,12 +340,11 @@ var/list/uplink_items = list()
gamemodes = list(/datum/game_mode/nuclear)
surplus = 0
-/datum/uplink_item/ammo/toydarts
+/datum/uplink_item/ammo/toydarts //This used to only be for nuke ops, but had the cost lowered and made available to traitors because >a box of foam darts is more expensive than four carbine magazines
name = "Box of Riot Darts"
desc = "A box of 40 Donksoft foam riot darts, for reloading any compatible foam dart gun. Don't forget to share!"
item = /obj/item/ammo_box/foambox/riot
- cost = 10
- gamemodes = list(/datum/game_mode/nuclear)
+ cost = 2
surplus = 0
// STEALTHY WEAPONS
@@ -348,23 +355,29 @@ var/list/uplink_items = list()
/datum/uplink_item/stealthy_weapons/throwingstars
name = "Box of Throwing Stars"
- desc = "A box of throwing stars with a high chance of embedding themselves in people's limbs."
+ desc = "A box of shurikens from ancient Earth martial arts. They are highly effective throwing weapons, and will embed into limbs when possible."
item = /obj/item/weapon/storage/box/throwing_stars
cost = 6
excludefrom = list(/datum/game_mode/nuclear)
+/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/weapon/pen/edagger
+ cost = 2
+
/datum/uplink_item/stealthy_weapons/foampistol
- name = "Toy Gun (with Stun Darts)"
- desc = "An innocent-looking toy pistol designed to fire foam darts. Comes loaded with riot-grade darts, to incapacitate a target."
+ 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/weapon/gun/projectile/automatic/toy/pistol/riot
- cost = 6
+ cost = 3
surplus = 10
excludefrom = list(/datum/game_mode/gang)
/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 anaesthetic and a chemical that is capable of blocking the movement of the vocal chords. \
- The pen holds one dose of the mixture, and cannot be refilled."
+ 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 cannot be refilled. Note that before the target falls asleep, they will be able to move and act."
item = /obj/item/weapon/pen/sleepy
cost = 4
excludefrom = list(/datum/game_mode/nuclear,/datum/game_mode/gang)
@@ -378,14 +391,21 @@ var/list/uplink_items = list()
/datum/uplink_item/stealthy_weapons/traitor_chem_bottle
name = "Poison Kit"
- desc = "An assortment of nasty chemicals."
+ desc = "An assortment of deadly chemicals packed into a compact box. Hard to utilize if there is no method of application."
item = /obj/item/weapon/storage/box/syndie_kit/chemical
cost = 6
surplus = 50
+/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/weapon/gun/syringe/syndicate
+ cost = 4
+ surplus = 50 //High chance of surplus due to poison kit also having a high chance
+
/datum/uplink_item/stealthy_weapons/detomatix
name = "Detomatix PDA Cartridge"
- desc = "When inserted into a personal digital assistant, this cartridge gives you five opportunities to detonate PDAs of crewmembers who have their message feature enabled. \
+ 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. It has a chance to detonate your PDA."
item = /obj/item/weapon/cartridge/syndicate
cost = 6
@@ -401,7 +421,7 @@ var/list/uplink_items = list()
name = "Pizza Bomb"
desc = "A pizza box with a bomb taped inside it. The timer needs to be set by opening the box; afterwards, opening the box again will trigger the detonation."
item = /obj/item/device/pizza_bomb
- cost = 5
+ cost = 6
surplus = 8
/datum/uplink_item/stealthy_weapons/dehy_carp
@@ -414,7 +434,7 @@ var/list/uplink_items = list()
name = "Explosive Airlock Charge"
desc = "A small, easily concealable device. It can be applied to an open airlock panel, and the next person to open that airlock will be knocked down in an explosion. The airlock's maintenance panel will also be destroyed by this."
item = /obj/item/device/doorCharge
- cost = 5
+ cost = 2
surplus = 10
excludefrom = list(/datum/game_mode/nuclear)
@@ -425,7 +445,7 @@ var/list/uplink_items = list()
/datum/uplink_item/stealthy_tools/chameleon_jumpsuit
name = "Chameleon Jumpsuit"
- desc = "A jumpsuit used to imitate the uniforms of Nanotrasen crewmembers."
+ desc = "A jumpsuit used to imitate the uniforms of Nanotrasen crewmembers. It can change form at any time to resemble another jumpsuit. May react unpredictably to electromagnetic disruptions."
item = /obj/item/clothing/under/chameleon
cost = 2
@@ -439,46 +459,47 @@ var/list/uplink_items = list()
/datum/uplink_item/stealthy_tools/syndigaloshes
name = "No-Slip Brown Shoes"
- desc = "These allow you to run on wet floors. They do not work on lubricated surfaces."
+ desc = "These shoes will allow the wearer to run on wet floors and slippery objects without falling down. They do not work on heavily lubricated surfaces."
item = /obj/item/clothing/shoes/sneakers/syndigaloshes
cost = 2
excludefrom = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_tools/syndigaloshes/nuke
name = "Tactical No-Slip Brown Shoes"
- desc = "These allow you to run on wet floors. They do not work on lubricated surfaces, and the maker swears they're better than normal ones, somehow."
+ desc = "These allow you to run on wet floors. They do not work on lubricated surfaces, but the manufacturer guarantees they're somehow better than the normal ones."
cost = 4 //but they aren't
gamemodes = list(/datum/game_mode/nuclear)
/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."
+ 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 can only be accessed with these cards."
item = /obj/item/weapon/card/id/syndicate
cost = 2
/datum/uplink_item/stealthy_tools/voice_changer
name = "Voice Changer"
item = /obj/item/clothing/mask/gas/voice
- desc = "A conspicuous gas mask that mimics the voice named on your identification card. When no identification is worn, the mask will render your voice unrecognizable."
+ desc = "A conspicuous gas mask that mimics the voice named on your identification card. It can be toggled on and off."
cost = 3
/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 cannot run, and projectiles pass over them."
+ 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/device/chameleon
cost = 7
excludefrom = list(/datum/game_mode/gang)
/datum/uplink_item/stealthy_tools/camera_bug
name = "Camera Bug"
- desc = "Enables you to bug cameras to view them remotely. Adding particular items to it alters its functions."
+ 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/device/camera_bug
cost = 1
surplus = 90
/datum/uplink_item/stealthy_tools/smugglersatchel
name = "Smuggler's Satchel"
- desc = "This satchel is thin enough to be hidden in the gap between plating and tiling, great for stashing your stolen goods. Comes with a crowbar and a floor tile inside."
+ desc = "This satchel is thin enough to be hidden in the gap between plating and tiling; great for stashing your stolen goods. Comes with a crowbar and a floor tile inside."
item = /obj/item/weapon/storage/backpack/satchel_flat
cost = 2
surplus = 30
@@ -497,14 +518,14 @@ var/list/uplink_items = list()
/datum/uplink_item/device_tools/emag
name = "Cryptographic Sequencer"
- desc = "The cryptographic sequencer, or emag, is a small card that unlocks hidden functions in electronic devices, subverts intended functions and characteristically breaks security mechanisms."
+ desc = "The cryptographic sequencer, or emag, is a small card that unlocks hidden functions in electronic devices, subverts intended functions, and characteristically breaks security mechanisms."
item = /obj/item/weapon/card/emag
cost = 6
excludefrom = list(/datum/game_mode/gang)
/datum/uplink_item/device_tools/toolbox
name = "Full Syndicate Toolbox"
- desc = "The syndicate toolbox is a suspicious black and red. Aside from tools, it comes with cable and a multitool. Insulated gloves are not included."
+ desc = "The syndicate toolbox is a suspicious black and red. It comes loaded with a full tool set including a multitool and combat gloves that are resistant to shocks and heat."
item = /obj/item/weapon/storage/toolbox/syndicate
cost = 1
@@ -514,10 +535,17 @@ var/list/uplink_items = list()
item = /obj/item/weapon/storage/backpack/dufflebag/syndie/surgery
cost = 4
+/datum/uplink_item/device_tools/military_belt
+ name = "Military Belt"
+ desc = "A robust seven-slot red belt that is capable of holding all items that can fit into it."
+ item = /obj/item/weapon/storage/belt/military
+ cost = 3
+ excludefrom = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/device_tools/medkit
name = "Syndicate Combat Medic Kit"
- desc = "The syndicate medkit is a suspicious black and red. Included is a combat stimulant injector for rapid healing, a medical hud for quick identification of injured comrades, \
- and other medical supplies helpful for a medical field operative."
+ desc = "This first aid kit is a suspicious brown and red. Included is a combat stimulant injector for rapid healing, a medical HUD for quick identification of injured personnel, \
+ and other supplies helpful for a field medic."
item = /obj/item/weapon/storage/firstaid/tactical
cost = 9
gamemodes = list(/datum/game_mode/nuclear,/datum/game_mode/gang)
@@ -531,18 +559,18 @@ var/list/uplink_items = list()
excludefrom = list(/datum/game_mode/gang)
/datum/uplink_item/device_tools/hardsuit
- name = "Blood-red Hardsuit"
+ name = "Blood-Red Hardsuit"
desc = "The feared suit of a syndicate nuclear agent. Features slightly better armoring and a built in jetpack that runs off standard atmospheric tanks. \
When the built in helmet is deployed your identity will be protected, even in death, as the suit cannot be removed by outside forces. Toggling the suit into combat mode \
will allow you all the mobility of a loose fitting uniform without sacrificing armoring. Additionally the suit is collapsible, small enough to fit within a backpack. \
- Nanotrasen crewmembers are trained to report red space suit sightings, these suits in particular are known to drive employees into a panic."
+ Nanotrasen crewmembers are trained to report red space suit sightings; these suits in particular are known to drive employees into a panic."
item = /obj/item/clothing/suit/space/hardsuit/syndi
cost = 8
excludefrom = list(/datum/game_mode/gang)
/datum/uplink_item/device_tools/thermal
name = "Thermal Imaging Glasses"
- desc = "These glasses are thermals disguised as engineers' optical meson scanners. \
+ desc = "These goggles can be turned to resemble common eyewears throughout the station. \
They allow you to see organisms through walls by capturing the upper portion of the infrared light spectrum, emitted as heat and light by objects. \
Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks." //THEN WHY CANT THEY SEE PLASMA FIRES????
item = /obj/item/clothing/glasses/thermal/syndi
@@ -550,14 +578,16 @@ var/list/uplink_items = list()
/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 artificial intelligences and cybernetic organisms in binary. "
+ 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/device/encryptionkey/binary
cost = 5
surplus = 75
/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."
+ 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/device/encryptionkey/syndicate
cost = 2 //Nowhere near as useful as the Binary Key!
surplus = 75
@@ -590,25 +620,26 @@ var/list/uplink_items = list()
cost = 1
/datum/uplink_item/device_tools/powersink
- name = "Power sink"
- desc = "When screwed to wiring attached to an electric grid, then activated, this large device places excessive load on the grid, causing a stationwide blackout. The sink cannot be carried because of its excessive size. \
- Ordering this sends you a small beacon that will teleport the power sink to your location on activation."
+ 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 stationwide blackout. The sink is large and cannot be stored in \
+ most traditional bags and boxes."
item = /obj/item/device/powersink
cost = 10
/datum/uplink_item/device_tools/singularity_beacon
name = "Singularity Beacon"
- desc = "When screwed to wiring attached to an electric grid, then activated, this large device pulls the singularity towards it. \
- Does not work when the singularity is still in containment. A singularity beacon can cause catastrophic damage to a space station, \
- leading to an emergency evacuation. Because of its size, it cannot be carried. Ordering this sends you a small beacon that will teleport the larger beacon to your location on activation."
+ desc = "When screwed to wiring attached to an electric grid and activated, this large device pulls any active gravitational singularities towards it. \
+ This will not work when the singularity is still in containment. A singularity beacon can cause catastrophic damage to a space station, \
+ leading to an emergency evacuation. 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/device/sbeacondrop
cost = 14
excludefrom = list(/datum/game_mode/gang)
/datum/uplink_item/device_tools/syndicate_bomb
name = "Syndicate Bomb"
- desc = "The Syndicate Bomb has an adjustable timer with a minimum setting of 60 seconds. Ordering the bomb sends you a small beacon, which will teleport the explosive to your location when you activate it. \
- You can wrench the bomb down to prevent removal. The crew may attempt to defuse the 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/device/sbeacondrop/bomb
cost = 11
@@ -621,7 +652,7 @@ var/list/uplink_items = list()
/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. \
+ 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/device/syndicatedetonator
cost = 3
@@ -629,7 +660,7 @@ var/list/uplink_items = list()
/datum/uplink_item/device_tools/teleporter
name = "Teleporter Circuit Board"
- desc = "A printed circuit board that completes the teleporter onboard the mothership. Advise you test fire the teleporter before entering it, as malfunctions can occur."
+ desc = "A printed circuit board that completes the teleporter onboard the mothership. It is advised you calibrate the teleporter before entering it, as malfunctions can occur."
item = /obj/item/weapon/circuitboard/teleporter
cost = 40
gamemodes = list(/datum/game_mode/nuclear)
@@ -651,34 +682,34 @@ var/list/uplink_items = list()
/datum/uplink_item/implants/freedom
name = "Freedom Implant"
- desc = "An implant injected into the body and later activated using a bodily gesture to attempt to slip restraints."
+ 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/weapon/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 using a bodily gesture to open an uplink with 10 telecrystals. \
- The ability for an agent to open an uplink after their possessions have been stripped from them makes this implant excellent for escaping confinement."
+ desc = "An implant injected into the body, and later activated at the user's will. It will open a separate uplink with 10 telecrystals. The ability to have these telecrystals, combined with no easy \
+ way to detect the ipmlant, makes this excellent for escaping confinement."
item = /obj/item/weapon/storage/box/syndie_kit/imp_uplink
cost = 14
surplus = 0
/datum/uplink_item/implants/adrenal
name = "Adrenal Implant"
- desc = "An implant injected into the body, and later activated using a bodily gesture to inject a chemical cocktail, which has a mild healing effect along with removing all stuns and increasing his speed."
+ desc = "An implant injected into the body, and later activated at the user's will. It will inject a chemical cocktail which has a mild healing effect along with removing all stuns and increasing movement speed."
item = /obj/item/weapon/storage/box/syndie_kit/imp_adrenal
cost = 8
/datum/uplink_item/implants/storage
name = "Storage Implant"
- desc = "An implant injected into the body and later used to store up to two big items in a subspace pocket."
+ desc = "An implant injected into the body, and later activated at the user's will. It will open a small subspace pocket capable of storing two items."
item = /obj/item/weapon/storage/box/syndie_kit/imp_storage
cost = 8
/datum/uplink_item/implants/microbomb
name = "Microbomb Implant"
desc = "An implant injected into the body, and later activated either manually or automatically upon death. The more implants inside of you, the higher the explosive power. \
- Will permanently destroy your body, however."
+ This will permanently destroy your body, however."
item = /obj/item/weapon/storage/box/syndie_kit/imp_microbomb
cost = 2
gamemodes = list(/datum/game_mode/nuclear)
@@ -693,31 +724,31 @@ var/list/uplink_items = list()
/datum/uplink_item/cyber_implants/thermals
name = "Thermal Vision Implant"
- desc = "These cybernetic eyes will give you thermal vision."
+ desc = "These cybernetic eyes will give you thermal vision. They must be implanted via surgery."
item = /obj/item/organ/internal/cyberimp/eyes/thermals
cost = 8
/datum/uplink_item/cyber_implants/xray
name = "X-Ray Vision Implant"
- desc = "These cybernetic eyes will give you X-ray vision."
+ desc = "These cybernetic eyes will give you X-ray vision. They must be implanted via surgery."
item = /obj/item/organ/internal/cyberimp/eyes/xray
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."
+ desc = "This implant will help you get back up on your feet faster after being stunned. It must be implanted via surgery."
item = /obj/item/organ/internal/cyberimp/brain/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."
+ desc = "This implant will attempt to revive you if you lose consciousness. It must be implanted via surgery."
item = /obj/item/organ/internal/cyberimp/chest/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."
+ desc = "A random selection of cybernetic implants. Guaranteed 5 high quality implants. They must be implanted via surgery."
item = /obj/item/weapon/storage/box/cyber_implants
cost = 40
@@ -730,7 +761,7 @@ var/list/uplink_items = list()
/datum/uplink_item/badass/syndiecigs
name = "Syndicate Smokes"
- desc = "Strong flavor, dense smoke, infused with Omnizine."
+ desc = "Strong flavor, dense smoke, infused with omnizine."
item = /obj/item/weapon/storage/fancy/cigarettes/cigpack_syndicate
cost = 2
@@ -758,14 +789,14 @@ var/list/uplink_items = list()
cost = 1
/datum/uplink_item/badass/balloon
- name = "For showing that you are The Boss"
- desc = "A useless red balloon with the syndicate logo on it, which can blow the deepest of covers."
+ name = "For showing that you are THE BOSS"
+ desc = "A useless red balloon with the Syndicate logo on it. Can blow the deepest of covers."
item = /obj/item/toy/syndicateballoon
cost = 20
/datum/uplink_item/implants/macrobomb
name = "Macrobomb Implant"
- desc = "An implant injected into the body, and later activated either manually or automatically upon death. Maximum explosion power."
+ desc = "An implant injected into the body, and later activated either manually or automatically upon death. Upon death, releases a massive explosion that will wipe out everything nearby."
item = /obj/item/weapon/storage/box/syndie_kit/imp_macrobomb
cost = 20
gamemodes = list(/datum/game_mode/nuclear)
diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm
index 38a62f01487..d8f3cefe45c 100644
--- a/code/datums/wires/wires.dm
+++ b/code/datums/wires/wires.dm
@@ -10,7 +10,6 @@ var/list/same_wires = list()
var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown", "gold", "gray", "cyan", "navy", "purple", "pink")
/datum/wires
-
var/random = 0 // Will the wires be different for every single instance.
var/atom/holder = null // The holder
var/holder_type = null // The holder type; used to make sure that the holder is the correct type.
@@ -46,6 +45,11 @@ var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown",
var/list/wires = same_wires[holder_type]
src.wires = wires // Reference the wires list.
+/datum/wires/Destroy()
+ holder = null
+ signallers = list()
+ return ..()
+
/datum/wires/proc/GenerateWires()
var/list/colours_to_pick = wireColours.Copy() // Get a copy, not a reference.
var/list/indexes_to_pick = list()
@@ -64,13 +68,33 @@ var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown",
src.wires[colour] = index
//wires = shuffle(wires)
+/datum/wires/proc/IsInteractionTool(obj/item/I)
+ if(istype(I, /obj/item/device/multitool))
+ return 1
+
+ if(istype(I, /obj/item/weapon/wirecutters))
+ return 1
+
+ if(istype(I, /obj/item/device/assembly))
+ var/obj/item/device/assembly/A = I
+ if(A.attachable)
+ return 1
+
+ return 0
+
/datum/wires/proc/Interact(mob/living/user)
-
var/html = null
if(holder && CanUse(user))
html = GetInteractWindow()
if(html)
+ if(user.machine != holder)
+ for(var/A in signallers)
+ if(istype(signallers[A], /obj/item))
+ var/obj/item/I = signallers[A]
+ if(I.on_found(user))
+ return
+
user.set_machine(holder)
else
user.unset_machine()
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 316c437c912..9a0c7e18cd8 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -391,7 +391,7 @@
else
qdel(AM)
if(istype(T, /turf/simulated))
- del(T)
+ qdel(T)
/*for(var/atom/movable/bug in src) // If someone (or something) is somehow still in the shuttle's docking area...
if(ismob(bug))
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index df257364a90..373d98c3b36 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -59,7 +59,7 @@
return
/atom/proc/assume_air(datum/gas_mixture/giver)
- del(giver)
+ qdel(giver)
return null
/atom/proc/remove_air(amount)
@@ -258,7 +258,7 @@ its easier to just keep the beam vertical.
/atom/proc/fire_act()
return
-/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush)
+/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked)
if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav.
spawn(2)
step(AM, turn(AM.dir, 180))
@@ -280,16 +280,12 @@ var/list/blood_splatter_icons = list()
//returns 1 if made bloody, returns 0 otherwise
/atom/proc/add_blood(mob/living/carbon/M)
- if(ishuman(M) && M.dna)
+ if(ishuman(M))
var/mob/living/carbon/human/H = M
if(NOBLOOD in H.dna.species.specflags)
return 0
- if(rejects_blood())
+ if(rejects_blood() || !M.has_dna())
return 0
- if(!istype(M))
- return 0
- if(!check_dna_integrity(M)) //check dna is valid and create/setup if necessary
- return 0 //no dna!
return 1
/obj/add_blood(mob/living/carbon/M)
@@ -362,7 +358,7 @@ var/list/blood_splatter_icons = list()
// Only adds blood on the floor -- Skie
/atom/proc/add_blood_floor(mob/living/carbon/M)
if(istype(src, /turf/simulated))
- if(check_dna_integrity(M)) //mobs with dna = (monkeys + humans at time of writing)
+ if(M.has_dna()) //mobs with dna = (monkeys + humans at time of writing)
var/obj/effect/decal/cleanable/blood/B = locate() in contents
if(!B)
blood_splatter(src,M,1)
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 49a050b3bd3..ea6a22a1ef2 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -155,7 +155,7 @@
/atom/movable/proc/throw_impact(atom/hit_atom)
return hit_atom.hitby(src)
-/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = 1)
+/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked)
if(!anchored && hitpush)
step(src, AM.dir)
..()
@@ -217,6 +217,9 @@
break
dist_travelled++
dist_since_sleep++
+
+ if(dist_travelled > 600) //safety to prevent infinite while loop.
+ break
if(dist_since_sleep >= speed)
dist_since_sleep = 0
sleep(1)
diff --git a/code/game/dna.dm b/code/game/dna.dm
index c8c0ceb4cd1..33615f83cfb 100644
--- a/code/game/dna.dm
+++ b/code/game/dna.dm
@@ -1,19 +1,4 @@
-#define INJECTOR_TIMEOUT 300
-#define REJUVENATORS_INJECT 15
-#define REJUVENATORS_MAX 90
-#define NUMBER_OF_BUFFERS 3
-#define RADIATION_STRENGTH_MAX 15
-#define RADIATION_STRENGTH_MULTIPLIER 1 //larger has a more range
-
-#define RADIATION_DURATION_MAX 30
-#define RADIATION_ACCURACY_MULTIPLIER 3 //larger is less accurate
-
-#define RADIATION_IRRADIATION_MULTIPLIER 0.2 //multiplier for how much radiation a test subject recieves
-
-#define BAD_MUTATION_DIFFICULTY 2
-#define GOOD_MUTATION_DIFFICULTY 4
-#define OP_MUTATION_DIFFICULTY 5
/////////////////////////// DNA DATUM
/datum/dna
var/unique_enzymes
@@ -27,26 +12,26 @@
var/mob/living/carbon/holder
/datum/dna/New(mob/living/carbon/new_holder)
- if(new_holder && istype(new_holder))
+ if(new_holder)
holder = new_holder
-/datum/dna/proc/transfer_identity(mob/living/carbon/destination)
- if(check_dna_integrity(destination))
- destination.dna.unique_enzymes = unique_enzymes
- destination.dna.uni_identity = uni_identity
- destination.dna.blood_type = blood_type
- hardset_dna(destination, null, null, null, null, species)
- destination.dna.features = features
- destination.dna.real_name = real_name
- destination.dna.mutations = mutations
+/datum/dna/proc/transfer_identity(mob/living/carbon/destination, transfer_SE = 0)
+ destination.dna.unique_enzymes = unique_enzymes
+ destination.dna.uni_identity = uni_identity
+ destination.dna.blood_type = blood_type
+ destination.set_species(species.type, icon_update=0)
+ destination.dna.features = features
+ destination.dna.real_name = real_name
+ if(transfer_SE)
+ destination.dna.struc_enzymes = struc_enzymes
/datum/dna/proc/copy_dna(datum/dna/new_dna)
new_dna.unique_enzymes = unique_enzymes
new_dna.struc_enzymes = struc_enzymes
new_dna.uni_identity = uni_identity
new_dna.blood_type = blood_type
- new_dna.species = new species.type
new_dna.features = features
+ new_dna.species = new species.type
new_dna.real_name = real_name
new_dna.mutations = mutations
@@ -70,55 +55,72 @@
for(var/datum/mutation/human/HM in group)
HM.force_lose(holder)
-/datum/dna/proc/generate_uni_identity(mob/living/carbon/character)
+/datum/dna/proc/generate_uni_identity()
. = ""
var/list/L = new /list(DNA_UNI_IDENTITY_BLOCKS)
- if(istype(character))
- L[DNA_GENDER_BLOCK] = construct_block((character.gender!=MALE)+1, 2)
- if(istype(character, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = character
- if(!H.dna.species)
- hardset_dna(H, null, null, null, null, /datum/species/human)
- if(!hair_styles_list.len)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/hair, hair_styles_list, hair_styles_male_list, hair_styles_female_list)
- L[DNA_HAIR_STYLE_BLOCK] = construct_block(hair_styles_list.Find(H.hair_style), hair_styles_list.len)
- L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color)
- if(!facial_hair_styles_list.len)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, facial_hair_styles_list, facial_hair_styles_male_list, facial_hair_styles_female_list)
- L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(facial_hair_styles_list.Find(H.facial_hair_style), facial_hair_styles_list.len)
- L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color)
- L[DNA_SKIN_TONE_BLOCK] = construct_block(skin_tones.Find(H.skin_tone), skin_tones.len)
- L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color)
+
+ L[DNA_GENDER_BLOCK] = construct_block((holder.gender!=MALE)+1, 2)
+ if(ishuman(holder))
+ var/mob/living/carbon/human/H = holder
+ if(!hair_styles_list.len)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/hair, hair_styles_list, hair_styles_male_list, hair_styles_female_list)
+ L[DNA_HAIR_STYLE_BLOCK] = construct_block(hair_styles_list.Find(H.hair_style), hair_styles_list.len)
+ L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color)
+ if(!facial_hair_styles_list.len)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, facial_hair_styles_list, facial_hair_styles_male_list, facial_hair_styles_female_list)
+ L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(facial_hair_styles_list.Find(H.facial_hair_style), facial_hair_styles_list.len)
+ L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color)
+ L[DNA_SKIN_TONE_BLOCK] = construct_block(skin_tones.Find(H.skin_tone), skin_tones.len)
+ L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color)
for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++)
if(L[i]) . += L[i]
else . += random_string(DNA_BLOCK_SIZE,hex_characters)
return .
-/datum/dna/proc/generate_struc_enzymes(mob/living/carbon/character)
- var/list/L = list("0","1","2","3","4","5","6")
+/datum/dna/proc/generate_struc_enzymes()
var/list/sorting = new /list(DNA_STRUC_ENZYMES_BLOCKS)
var/result = ""
for(var/datum/mutation/human/A in good_mutations + bad_mutations + not_good_mutations)
- if(A.name == RACEMUT && istype(character,/mob/living/carbon/monkey))
+ if(A.name == RACEMUT && ismonkey(holder))
sorting[A.dna_block] = num2hex(A.lowest_value + rand(0, 256 * 6), DNA_BLOCK_SIZE)
- character.dna.mutations.Add(A)
+ mutations |= A
else
- sorting[A.dna_block] = random_string(DNA_BLOCK_SIZE, L)
+ sorting[A.dna_block] = random_string(DNA_BLOCK_SIZE, list("0","1","2","3","4","5","6"))
for(var/B in sorting)
result += B
return result
-/datum/dna/proc/generate_unique_enzymes(mob/living/carbon/character)
+/datum/dna/proc/generate_unique_enzymes()
. = ""
- if(istype(character))
- real_name = character.real_name
- . += md5(character.real_name)
+ if(istype(holder))
+ real_name = holder.real_name
+ . += md5(holder.real_name)
else
- . += repeat_string(DNA_UNIQUE_ENZYMES_LEN, "0")
+ . += random_string(DNA_UNIQUE_ENZYMES_LEN, hex_characters)
return .
+/datum/dna/proc/update_ui_block(blocknumber)
+ if(!blocknumber || !ishuman(holder))
+ return
+ var/mob/living/carbon/human/H = holder
+ switch(blocknumber)
+ if(DNA_HAIR_COLOR_BLOCK)
+ setblock(uni_identity, blocknumber, sanitize_hexcolor(H.hair_color))
+ if(DNA_FACIAL_HAIR_COLOR_BLOCK)
+ setblock(uni_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color))
+ if(DNA_SKIN_TONE_BLOCK)
+ setblock(uni_identity, blocknumber, construct_block(skin_tones.Find(H.skin_tone), skin_tones.len))
+ if(DNA_EYE_COLOR_BLOCK)
+ setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color))
+ if(DNA_GENDER_BLOCK)
+ setblock(uni_identity, blocknumber, construct_block((H.gender!=MALE)+1, 2))
+ if(DNA_FACIAL_HAIR_STYLE_BLOCK)
+ setblock(uni_identity, blocknumber, construct_block(facial_hair_styles_list.Find(H.facial_hair_style), facial_hair_styles_list.len))
+ if(DNA_HAIR_STYLE_BLOCK)
+ setblock(uni_identity, blocknumber, construct_block(hair_styles_list.Find(H.hair_style), hair_styles_list.len))
+
/datum/dna/proc/mutations_say_mods(message)
if(message)
for(var/datum/mutation/human/M in mutations)
@@ -131,79 +133,130 @@
spans |= M.get_spans()
return spans
-/proc/hardset_dna(mob/living/carbon/owner, ui, se, real_name, blood_type, datum/species/mrace, features)
- if(!ismonkey(owner) && !ishuman(owner))
- return
- if(!owner.dna)
- create_dna(owner, mrace)
+/datum/dna/proc/is_same_as(datum/dna/D)
+ if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name)
+ if(species.type == D.species.type && features == D.features && blood_type == D.blood_type)
+ return 1
+ return 0
- if(mrace && !ismonkey(owner))
- if(owner.dna.species.exotic_blood)
- var/datum/reagent/exotic_blood = new owner.dna.species.exotic_blood
- owner.reagents.del_reagent(exotic_blood.id)
- owner.dna.species = new mrace()
+//used to update dna UI, UE, and dna.real_name.
+/datum/dna/proc/update_dna_identity()
+ uni_identity = generate_uni_identity()
+ unique_enzymes = generate_unique_enzymes()
- if(features)
- owner.dna.features = features
+/datum/dna/proc/initialize_dna(newblood_type)
+ if(newblood_type)
+ blood_type = newblood_type
+ unique_enzymes = generate_unique_enzymes()
+ uni_identity = generate_uni_identity()
+ struc_enzymes = generate_struc_enzymes()
+ features = list("mcolor" = "FFF", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None")
- if(real_name)
- owner.real_name = real_name
- owner.dna.generate_unique_enzymes(owner)
- if(blood_type)
- owner.dna.blood_type = blood_type
- if(ui)
- owner.dna.uni_identity = ui
- updateappearance(owner)
+/////////////////////////// DNA MOB-PROCS //////////////////////
- if(se)
- owner.dna.struc_enzymes = se
- domutcheck(owner)
-
- check_dna_integrity(owner)
-
- owner.regenerate_icons()
+/mob/proc/set_species(datum/species/mrace, icon_update = 1)
return
-/proc/check_dna_integrity(mob/living/carbon/character)
- if(!character || !(istype(character, /mob/living/carbon/human) || istype(character, /mob/living/carbon/monkey))) //Evict xenos from carbon 2012
+/mob/living/carbon/set_species(datum/species/mrace, icon_update = 1)
+ if(has_dna())
+ if(dna.species.exotic_blood)
+ var/datum/reagent/EB = dna.species.exotic_blood
+ reagents.del_reagent(initial(EB.id))
+ dna.species = new mrace()
+
+/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = 1)
+ ..()
+ if(icon_update)
+ update_body()
+ update_hair()
+ update_mutcolor()
+ update_mutations_overlay()// no lizard with human hulk overlay please.
+
+
+/mob/proc/has_dna()
+ return
+
+/mob/living/carbon/has_dna()
+ return dna
+
+
+/mob/living/carbon/human/proc/hardset_dna(ui, se, newreal_name, newblood_type, datum/species/mrace, newfeatures)
+
+ if(newfeatures)
+ dna.features = newfeatures
+
+ if(mrace)
+ set_species(mrace, icon_update=0)
+
+ if(newreal_name)
+ real_name = newreal_name
+ dna.generate_unique_enzymes()
+
+ if(newblood_type)
+ dna.blood_type = newblood_type
+
+ if(ui)
+ dna.uni_identity = ui
+ updateappearance(icon_update=0)
+
+ if(se)
+ dna.struc_enzymes = se
+ domutcheck()
+
+ if(mrace || newfeatures || ui)
+ update_body()
+ update_hair()
+ update_mutcolor()
+ update_mutations_overlay()
+
+
+/mob/living/carbon/proc/create_dna()
+ dna = new /datum/dna(src)
+ if(!dna.species)
+ dna.species = new /datum/species/human()
+
+//proc used to update the mob's appearance after its dna UI has been changed
+/mob/living/carbon/proc/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0)
+ if(!has_dna())
return
- if(!character.dna)
- if(ready_dna(character))
- return character.dna
+ gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE
+
+mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0)
+ ..()
+ var/structure = dna.uni_identity
+ hair_color = sanitize_hexcolor(getblock(structure, DNA_HAIR_COLOR_BLOCK))
+ facial_hair_color = sanitize_hexcolor(getblock(structure, DNA_FACIAL_HAIR_COLOR_BLOCK))
+ skin_tone = skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), skin_tones.len)]
+ eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK))
+ facial_hair_style = facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), facial_hair_styles_list.len)]
+ hair_style = hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), hair_styles_list.len)]
+ if(icon_update)
+ update_body()
+ update_hair()
+ if(mutcolor_update)
+ update_mutcolor()
+ if(mutations_overlay_update)
+ update_mutations_overlay()
+
+
+/mob/proc/domutcheck()
+ return
+
+/mob/living/carbon/domutcheck()
+ if(!has_dna())
return
- if(length(character.dna.uni_identity) != DNA_UNI_IDENTITY_BLOCKS*DNA_BLOCK_SIZE)
- character.dna.uni_identity = character.dna.generate_uni_identity(character)
- if(length(character.dna.struc_enzymes)!= DNA_STRUC_ENZYMES_BLOCKS*DNA_BLOCK_SIZE)
- character.dna.struc_enzymes = character.dna.generate_struc_enzymes()
- if(!character.dna.real_name || length(character.dna.unique_enzymes) != DNA_UNIQUE_ENZYMES_LEN)
- character.dna.unique_enzymes = character.dna.generate_unique_enzymes(character)
- return character.dna
+ for(var/datum/mutation/human/A in good_mutations | bad_mutations | not_good_mutations)
+ if(ismob(A.check_block(src)))
+ return //we got monkeyized/humanized, this mob will be deleted, no need to continue.
-/proc/ready_dna(mob/living/carbon/character, blood_type)
- if(!istype(character, /mob/living/carbon/monkey) && !istype(character, /mob/living/carbon/human))
- return
- if(!character.dna)
- create_dna(character)
- if(blood_type)
- character.dna.blood_type = blood_type
- character.dna.real_name = character.real_name
- character.dna.uni_identity = character.dna.generate_uni_identity(character)
- character.dna.struc_enzymes = character.dna.generate_struc_enzymes(character)
- character.dna.unique_enzymes = character.dna.generate_unique_enzymes(character)
- character.dna.features = character.features
- return character.dna
+ update_mutations_overlay()
-/proc/create_dna(mob/living/carbon/C, datum/species/S) //don't use this unless you're about to use hardset_dna or ready_dna
- C.dna = new /datum/dna(C)
- C.dna.holder = C
- if(S) C.dna.species = new S() // do not remove; this is here to prevent runtimes
-/////////////////////////// DNA DATUM
-/////////////////////////// DNA HELPER-PROCS
+/////////////////////////// DNA HELPER-PROCS //////////////////////////////
/proc/getleftblocks(input,blocknumber,blocksize)
if(blocknumber > 1)
return copytext(input,1,((blocksize*blocknumber)-(blocksize-1)))
@@ -219,45 +272,35 @@
if(!istring || !blocknumber || !replacement || !blocksize) return 0
return getleftblocks(istring, blocknumber, blocksize) + replacement + getrightblocks(istring, blocknumber, blocksize)
-/proc/scramble(input,rs,rd)
- var/length = length(input)
- var/ran = gaussian(0, rs*RADIATION_STRENGTH_MULTIPLIER)
- if(ran == 0) ran = pick(-1,1) //hacky, statistically should almost never happen. 0-change makes people mad though
- else if(ran < 0) ran = round(ran) //negative, so floor it
- else ran = -round(-ran) //positive, so ceiling it
- return num2hex(Wrap(hex2num(input)+ran, 0, 16**length), length)
-
-/proc/randomize_radiation_accuracy(position_we_were_supposed_to_hit, radduration, number_of_blocks)
- return Wrap(round(position_we_were_supposed_to_hit + gaussian(0, RADIATION_ACCURACY_MULTIPLIER/radduration), 1), 1, number_of_blocks+1)
-
/proc/randmut(mob/living/carbon/M, list/candidates, difficulty = 2)
- if(!check_dna_integrity(M))
+ if(!M.has_dna())
return
var/datum/mutation/human/num = pick(candidates)
. = num.force_give(M)
return
/proc/randmutb(mob/living/carbon/M)
- if(!check_dna_integrity(M))
+ if(!M.has_dna())
return
var/datum/mutation/human/HM = pick((bad_mutations | not_good_mutations) - mutations_list[RACEMUT])
. = HM.force_give(M)
/proc/randmutg(mob/living/carbon/M)
- if(!check_dna_integrity(M))
+ if(!M.has_dna())
return
var/datum/mutation/human/HM = pick(good_mutations)
. = HM.force_give(M)
/proc/randmuti(mob/living/carbon/M)
- if(!check_dna_integrity(M)) return
- var/num = rand(1, DNA_STRUC_ENZYMES_BLOCKS)
+ if(!M.has_dna())
+ return
+ var/num = rand(1, DNA_UNI_IDENTITY_BLOCKS)
var/newdna = setblock(M.dna.uni_identity, num, random_string(DNA_BLOCK_SIZE, hex_characters))
M.dna.uni_identity = newdna
return
/proc/clean_dna(mob/living/carbon/M)
- if(!check_dna_integrity(M))
+ if(!M.has_dna())
return
M.dna.remove_all_mutations()
@@ -266,691 +309,20 @@
randmut(M, candidates, difficulty)
/proc/scramble_dna(mob/living/carbon/M, ui=FALSE, se=FALSE, probability)
- if(!check_dna_integrity(M))
+ if(!M.has_dna())
return 0
if(se)
for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++)
if(prob(probability))
M.dna.struc_enzymes = setblock(M.dna.struc_enzymes, i, random_string(DNA_BLOCK_SIZE, hex_characters))
- domutcheck(M)
+ M.domutcheck()
if(ui)
for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++)
if(prob(probability))
M.dna.uni_identity = setblock(M.dna.uni_identity, i, random_string(DNA_BLOCK_SIZE, hex_characters))
- updateappearance(M)
+ M.updateappearance(mutations_overlay_update=1)
return 1
-/////////////////////////// DNA HELPER-PROCS
-
-/////////////////////////// DNA MISC-PROCS
-/proc/updateappearance(mob/living/carbon/C)
- if(!check_dna_integrity(C))
- return 0
-
- var/structure = C.dna.uni_identity
- C.gender = (deconstruct_block(getblock(structure, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE
- if(istype(C, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = C
- H.hair_color = sanitize_hexcolor(getblock(structure, DNA_HAIR_COLOR_BLOCK))
- H.facial_hair_color = sanitize_hexcolor(getblock(structure, DNA_FACIAL_HAIR_COLOR_BLOCK))
- H.skin_tone = skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), skin_tones.len)]
- H.eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK))
- H.facial_hair_style = facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), facial_hair_styles_list.len)]
- H.hair_style = hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), hair_styles_list.len)]
-
- H.update_body()
- H.update_hair()
- return 1
-
-/proc/domutcheck(mob/living/carbon/M)
- if(!check_dna_integrity(M))
- return 0
-
- var/mob/living/carbon/C = M
- var/mob/living/carbon/temp
-
- for(var/datum/mutation/human/A in good_mutations | bad_mutations | not_good_mutations)
- temp = A.check_block(C)
- if(ismob(temp))
- C = temp
-
-//////////////////////////////////////////////////////////// Monkey Block
- if(M)
- M.regenerate_icons()
- return 1
-/////////////////////////// DNA MISC-PROCS
-
-
-/////////////////////////// DNA MACHINES
-/obj/machinery/dna_scannernew
- name = "\improper DNA scanner"
- desc = "It scans DNA structures."
- icon = 'icons/obj/Cryogenic2.dmi'
- icon_state = "scanner"
- density = 1
- var/locked = 0
- anchored = 1
- use_power = 1
- idle_power_usage = 50
- active_power_usage = 300
- var/damage_coeff
- var/scan_level
- var/precision_coeff
-
-/obj/machinery/dna_scannernew/New()
- ..()
- component_parts = list()
- component_parts += new /obj/item/weapon/circuitboard/clonescanner(null)
- component_parts += new /obj/item/weapon/stock_parts/scanning_module(null)
- component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
- component_parts += new /obj/item/weapon/stock_parts/micro_laser(null)
- component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
- component_parts += new /obj/item/stack/cable_coil(null, 1)
- component_parts += new /obj/item/stack/cable_coil(null, 1)
- RefreshParts()
-
-
-/obj/machinery/dna_scannernew/RefreshParts()
- scan_level = 0
- damage_coeff = 0
- precision_coeff = 0
- for(var/obj/item/weapon/stock_parts/scanning_module/P in component_parts)
- scan_level += P.rating
- for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts)
- precision_coeff = P.rating
- for(var/obj/item/weapon/stock_parts/micro_laser/P in component_parts)
- damage_coeff = P.rating
-
-/obj/machinery/dna_scannernew/update_icon()
-
- //no power or maintenance
- if(stat & (NOPOWER|BROKEN))
- icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_unpowered"
- return
-
- if((stat & MAINT) || panel_open)
- icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_maintenance"
- return
-
- //running and someone in there
- if(occupant)
- icon_state = initial(icon_state)+ "_occupied"
- return
-
- //running
- icon_state = initial(icon_state)+ (state_open ? "_open" : "")
-
-/obj/machinery/dna_scannernew/power_change()
- ..()
- update_icon()
-
-/obj/machinery/dna_scannernew/proc/toggle_open(mob/user)
- if(panel_open)
- user << "Close the maintenance panel first."
- return
-
- if(state_open)
- close_machine()
- return
-
- else if(locked)
- user << "The bolts are locked down, securing the door shut."
- return
-
- open_machine()
-
-/obj/machinery/dna_scannernew/container_resist()
- var/mob/living/user = usr
- var/breakout_time = 2
- if(state_open || !locked) //Open and unlocked, no need to escape
- state_open = 1
- return
- user.changeNext_move(CLICK_CD_BREAKOUT)
- user.last_special = world.time + CLICK_CD_BREAKOUT
- user << "You lean on the back of [src] and start pushing the door open... (this will take about [breakout_time] minutes.)"
- user.visible_message("You hear a metallic creaking from [src]!")
-
- if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
- if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked)
- return
-
- locked = 0
- visible_message("[user] successfully broke out of [src]!")
- user << "You successfully break out of [src]!"
-
- open_machine()
-
-/obj/machinery/dna_scannernew/close_machine()
- if(!state_open)
- return 0
-
- ..()
-
- // search for ghosts, if the corpse is empty and the scanner is connected to a cloner
- if(occupant)
- if(locate(/obj/machinery/computer/cloning, get_step(src, NORTH)) \
- || locate(/obj/machinery/computer/cloning, get_step(src, SOUTH)) \
- || locate(/obj/machinery/computer/cloning, get_step(src, EAST)) \
- || locate(/obj/machinery/computer/cloning, get_step(src, WEST)))
-
- occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!")
- return 1
-
-/obj/machinery/dna_scannernew/open_machine()
- if(state_open)
- return 0
-
- ..()
-
- return 1
-
-/obj/machinery/dna_scannernew/relaymove(mob/user as mob)
- if(user.stat || locked)
- return
-
- open_machine()
- return
-
-/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params)
-
- if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))//sent icon_state is irrelevant...
- update_icon()//..since we're updating the icon here, since the scanner can be unpowered when opened/closed
- return
-
- if(exchange_parts(user, I))
- return
-
- if(default_pry_open(I))
- return
-
- if(default_deconstruction_crowbar(I))
- return
-
- if(istype(I, /obj/item/weapon/grab))
- var/obj/item/weapon/grab/G = I
- if(!ismob(G.affecting))
- return
-
- if(!state_open)
- user << "Open the scanner first."
- return
-
- var/mob/M = G.affecting
- M.loc = loc
- user.stop_pulling()
- qdel(G)
-
-/obj/machinery/dna_scannernew/attack_hand(mob/user)
- if(..(user,1,0)) //don't set the machine, since there's no dialog
- return
-
- toggle_open(user)
-
-/obj/machinery/dna_scannernew/blob_act()
- if(prob(75))
- qdel(src)
-
-
-//DNA COMPUTER
-/obj/machinery/computer/scan_consolenew
- name = "\improper DNA scanner access console"
- desc = "Scan DNA."
- icon_screen = "dna"
- icon_keyboard = "med_key"
- density = 1
- circuit = /obj/item/weapon/circuitboard/scan_consolenew
- var/radduration = 2
- var/radstrength = 1
-
- var/list/buffer[NUMBER_OF_BUFFERS]
-
- var/injectorready = 0 //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete
- var/current_screen = "mainmenu"
- var/obj/machinery/dna_scannernew/connected = null
- var/obj/item/weapon/disk/data/diskette = null
- anchored = 1.0
- use_power = 1
- idle_power_usage = 10
- active_power_usage = 400
-
-/obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params)
- if (istype(I, /obj/item/weapon/disk/data)) //INSERT SOME DISKETTES
- if (!src.diskette)
- if(!user.drop_item())
- return
- I.loc = src
- src.diskette = I
- user << "You insert [I]."
- src.updateUsrDialog()
- return
- else
- ..()
- return
-
-/obj/machinery/computer/scan_consolenew/New()
- ..()
-
- spawn(5)
- for(dir in list(NORTH,EAST,SOUTH,WEST))
- connected = locate(/obj/machinery/dna_scannernew, get_step(src, dir))
- if(!isnull(connected))
- break
- spawn(250)
- injectorready = 1
- return
- return
-
-/obj/machinery/computer/scan_consolenew/attack_hand(mob/user)
- if(..())
- return
- ShowInterface(user)
-
-/obj/machinery/computer/scan_consolenew/proc/ShowInterface(mob/user, last_change)
- if(!user) return
- var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 800, 630) // Set up the popup browser window
- if(!( in_range(src, user) || istype(user, /mob/living/silicon) ))
- popup.close()
- return
- popup.add_stylesheet("scannernew", 'html/browser/scannernew.css')
-
- var/mob/living/carbon/viable_occupant
- var/occupant_status = "
"
-
- popup.set_content(temp_html)
- popup.open()
-
-
-/obj/machinery/computer/scan_consolenew/Topic(href, href_list)
- if(..())
- return
- if(!isturf(usr.loc))
- return
- if(!( (isturf(loc) && in_range(src, usr)) || istype(usr, /mob/living/silicon) ))
- return
- if(current_screen == "working")
- return
-
- add_fingerprint(usr)
- usr.set_machine(src)
-
- var/mob/living/carbon/viable_occupant
- if(connected)
- viable_occupant = connected.occupant
- if(!istype(viable_occupant) || !viable_occupant.dna || (NOCLONE in viable_occupant.mutations))
- viable_occupant = null
-
- //Basic Tasks///////////////////////////////////////////
- var/num = round(text2num(href_list["num"]))
- var/last_change
- switch(href_list["task"])
- if("togglelock")
- if(connected) connected.locked = !connected.locked
- if("toggleopen")
- if(connected) connected.toggle_open(usr)
- if("setduration")
- if(!num)
- num = round(input(usr, "Choose pulse duration:", "Input an Integer", null) as num|null)
- if(num)
- radduration = Wrap(num, 1, RADIATION_DURATION_MAX+1)
- if("setstrength")
- if(!num)
- num = round(input(usr, "Choose pulse strength:", "Input an Integer", null) as num|null)
- if(num)
- radstrength = Wrap(num, 1, RADIATION_STRENGTH_MAX+1)
- if("screen")
- current_screen = href_list["text"]
- if("rejuv")
- if(viable_occupant && viable_occupant.reagents)
- var/epinephrine_amount = viable_occupant.reagents.get_reagent_amount("epinephrine")
- var/can_add = max(min(REJUVENATORS_MAX - epinephrine_amount, REJUVENATORS_INJECT), 0)
- viable_occupant.reagents.add_reagent("epinephrine", can_add)
- if("setbufferlabel")
- var/text = sanitize(input(usr, "Input a new label:", "Input an Text", null) as text|null)
- if(num && text)
- num = Clamp(num, 1, NUMBER_OF_BUFFERS)
- var/list/buffer_slot = buffer[num]
- if(istype(buffer_slot))
- buffer_slot["label"] = text
- if("setbuffer")
- if(num && viable_occupant)
- num = Clamp(num, 1, NUMBER_OF_BUFFERS)
- buffer[num] = list(
- "label"="Buffer[num]:[viable_occupant.real_name]",
- "UI"=viable_occupant.dna.uni_identity,
- "SE"=viable_occupant.dna.struc_enzymes,
- "UE"=viable_occupant.dna.unique_enzymes,
- "name"=viable_occupant.real_name,
- "blood_type"=viable_occupant.dna.blood_type
- )
- if("clearbuffer")
- if(num)
- num = Clamp(num, 1, NUMBER_OF_BUFFERS)
- var/list/buffer_slot = buffer[num]
- if(istype(buffer_slot))
- buffer_slot.Cut()
- if("transferbuffer")
- if(num && viable_occupant && viable_occupant.stat != DEAD)
- num = Clamp(num, 1, NUMBER_OF_BUFFERS)
- var/list/buffer_slot = buffer[num]
- if(istype(buffer_slot)) //15 and 40 are just magic numbers that were here before so i didnt touch them, they are initial boundaries of damage
- viable_occupant.radiation += rand(15/(connected.damage_coeff ** 2),40/(connected.damage_coeff ** 2)) //Each laser level reduces damage by lvl^2, so no effect on 1 lvl, 4 times less damage on 2 and 9 times less damage on 3
- switch(href_list["text"]) //Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove
- if("se")
- if(buffer_slot["SE"])
- viable_occupant.dna.struc_enzymes = buffer_slot["SE"]
- domutcheck(viable_occupant)
- if("ui")
- if(buffer_slot["UI"])
- viable_occupant.dna.uni_identity = buffer_slot["UI"]
- updateappearance(viable_occupant)
- else
- if(buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"])
- viable_occupant.real_name = buffer_slot["name"]
- viable_occupant.name = buffer_slot["name"]
- viable_occupant.dna.unique_enzymes = buffer_slot["UE"]
- viable_occupant.dna.blood_type = buffer_slot["blood_type"]
- updateappearance(viable_occupant)
- if("injector")
- if(num && injectorready)
- num = Clamp(num, 1, NUMBER_OF_BUFFERS)
- var/list/buffer_slot = buffer[num]
- if(istype(buffer_slot))
- var/obj/item/weapon/dnainjector/I
- switch(href_list["text"])
- if("se")
- if(buffer_slot["SE"])
- I = new /obj/item/weapon/dnainjector(loc)
- for(var/datum/mutation/human/HM in good_mutations + bad_mutations + not_good_mutations)
- if(HM.check_block_string(buffer_slot["SE"]))
- if(prob(HM.get_chance))
- I.add_mutations.Add(HM)
- else
- I.remove_mutations.Add(HM)
- I.damage_coeff = connected.damage_coeff
- if("ui")
- if(buffer_slot["UI"])
- I = new /obj/item/weapon/dnainjector(loc)
- I.fields = list("UI"=buffer_slot["UI"])
- I.damage_coeff = connected.damage_coeff
- else
- if(buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"])
- I = new /obj/item/weapon/dnainjector(loc)
- I.fields = list("name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"])
- I.damage_coeff = connected.damage_coeff
- if(I)
- injectorready = 0
- spawn(INJECTOR_TIMEOUT)
- injectorready = 1
- if("loaddisk")
- if(num && diskette && diskette.fields)
- num = Clamp(num, 1, NUMBER_OF_BUFFERS)
- buffer[num] = diskette.fields.Copy()
- if("savedisk")
- if(num && diskette && !diskette.read_only)
- num = Clamp(num, 1, NUMBER_OF_BUFFERS)
- var/list/buffer_slot = buffer[num]
- if(istype(buffer_slot))
- diskette.name = "data disk \[[buffer_slot["label"]]\]"
- diskette.fields = buffer_slot.Copy()
- if("ejectdisk")
- if(diskette)
- diskette.loc = get_turf(src)
- diskette = null
- if("pulseui","pulsese")
- if(num && viable_occupant && connected && viable_occupant.stat != DEAD)
- radduration = Wrap(radduration, 1, RADIATION_DURATION_MAX+1)
- radstrength = Wrap(radstrength, 1, RADIATION_STRENGTH_MAX+1)
-
- var/locked_state = connected.locked
- connected.locked = 1
-
- current_screen = "working"
- ShowInterface(usr)
-
- sleep(radduration*10)
- current_screen = "mainmenu"
-
- if(viable_occupant && connected && connected.occupant==viable_occupant)
- viable_occupant.radiation += (RADIATION_IRRADIATION_MULTIPLIER*radduration*radstrength)/(connected.damage_coeff ** 2) //Read comment in "transferbuffer" section above for explanation
- switch(href_list["task"]) //Same thing as there but values are even lower, on best part they are about 0.0*, effectively no damage
- if("pulseui")
- var/len = length(viable_occupant.dna.uni_identity)
- num = Wrap(num, 1, len+1)
- num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len) //Each manipulator level above 1 makes randomization as accurate as selected time + manipulator lvl^2
- //Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low
- var/block = round((num-1)/DNA_BLOCK_SIZE)+1
- var/subblock = num - block*DNA_BLOCK_SIZE
- last_change = "UI #[block]-[subblock]; "
-
- var/hex = copytext(viable_occupant.dna.uni_identity, num, num+1)
- last_change += "[hex]"
- hex = scramble(hex, radstrength, radduration)
- last_change += "->[hex]"
-
- viable_occupant.dna.uni_identity = copytext(viable_occupant.dna.uni_identity, 1, num) + hex + copytext(viable_occupant.dna.uni_identity, num+1, 0)
- updateappearance(viable_occupant)
- if("pulsese")
- var/len = length(viable_occupant.dna.struc_enzymes)
- num = Wrap(num, 1, len+1)
- num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len)
-
- var/block = round((num-1)/DNA_BLOCK_SIZE)+1
- var/subblock = num - block*DNA_BLOCK_SIZE
- last_change = "SE #[block]-[subblock]; "
-
- var/hex = copytext(viable_occupant.dna.struc_enzymes, num, num+1)
- last_change += "[hex]"
- hex = scramble(hex, radstrength, radduration)
- last_change += "->[hex]"
-
- viable_occupant.dna.struc_enzymes = copytext(viable_occupant.dna.struc_enzymes, 1, num) + hex + copytext(viable_occupant.dna.struc_enzymes, num+1, 0)
- domutcheck(viable_occupant)
- else
- current_screen = "mainmenu"
-
- if(connected)
- connected.locked = locked_state
-
- ShowInterface(usr,last_change)
-
-
-/////////////////////////// DNA MACHINES
-#undef INJECTOR_TIMEOUT
-#undef REJUVENATORS_INJECT
-#undef REJUVENATORS_MAX
-#undef NUMBER_OF_BUFFERS
-
-#undef RADIATION_STRENGTH_MAX
-#undef RADIATION_STRENGTH_MULTIPLIER
-
-#undef RADIATION_DURATION_MAX
-#undef RADIATION_ACCURACY_MULTIPLIER
-
-#undef RADIATION_IRRADIATION_MULTIPLIER
-
-//#undef BAD_MUTATION_DIFFICULTY
-//#undef GOOD_MUTATION_DIFFICULTY
-//#undef OP_MUTATION_DIFFICULTY
-
//value in range 1 to values. values must be greater than 0
//all arguments assumed to be positive integers
/proc/construct_block(value, values, blocksize=DNA_BLOCK_SIZE)
@@ -968,10 +340,4 @@
value = values
return value
-
-/datum/dna/proc/is_same_as(datum/dna/D)
- if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name)
- if(species == D.species && features == D.features && blood_type == D.blood_type)
- return 1
- return 0
-
+/////////////////////////// DNA HELPER-PROCS
\ No newline at end of file
diff --git a/code/game/gamemodes/abduction/abduction.dm b/code/game/gamemodes/abduction/abduction.dm
index 8e6662109e3..1151de4f55f 100644
--- a/code/game/gamemodes/abduction/abduction.dm
+++ b/code/game/gamemodes/abduction/abduction.dm
@@ -107,7 +107,7 @@
H = agent.current
L = agent_landmarks[team_number]
H.loc = L.loc
- hardset_dna(H, null, null, null, null, /datum/species/abductor)
+ H.set_species(/datum/species/abductor)
S = H.dna.species
S.agent = 1
S.team = team_number
@@ -115,13 +115,12 @@
equip_common(H,team_number)
equip_agent(H,team_number)
greet_agent(agent,team_number)
- H.regenerate_icons()
scientist = scientists[team_number]
H = scientist.current
L = scientist_landmarks[team_number]
H.loc = L.loc
- hardset_dna(H, null, null, null, null, /datum/species/abductor)
+ H.set_species(/datum/species/abductor)
S = H.dna.species
S.scientist = 1
S.team = team_number
@@ -129,7 +128,6 @@
equip_common(H,team_number)
equip_scientist(H,team_number)
greet_scientist(scientist,team_number)
- H.regenerate_icons()
return ..()
//Used for create antag buttons
@@ -156,7 +154,7 @@
H = agent.current
L = agent_landmarks[team_number]
H.loc = L.loc
- hardset_dna(H, null, null, null, null, /datum/species/abductor)
+ H.set_species(/datum/species/abductor)
S = H.dna.species
S.agent = 1
S.team = team_number
@@ -164,13 +162,13 @@
equip_common(H,team_number)
equip_agent(H,team_number)
greet_agent(agent,team_number)
- H.regenerate_icons()
+
scientist = scientists[team_number]
H = scientist.current
L = scientist_landmarks[team_number]
H.loc = L.loc
- hardset_dna(H, null, null, null, null, /datum/species/abductor)
+ H.set_species(/datum/species/abductor)
S = H.dna.species
S.scientist = 1
S.team = team_number
@@ -178,7 +176,7 @@
equip_common(H,team_number)
equip_scientist(H,team_number)
greet_scientist(scientist,team_number)
- H.regenerate_icons()
+
/datum/game_mode/abduction/proc/greet_agent(datum/mind/abductor,team_number)
@@ -277,9 +275,9 @@
var/datum/objective/objective = team_objectives[team_number]
var/team_name = team_names[team_number]
if(console.experiment.points >= objective.target_amount)
- world << "[team_name] team fullfilled its mission!"
+ world << "[team_name] team fullfilled its mission!"
else
- world << "[team_name] team failed its mission."
+ world << "[team_name] team failed its mission."
..()
return 1
@@ -332,7 +330,7 @@
if(!owner.current || !ishuman(owner.current))
return 0
var/mob/living/carbon/human/H = owner.current
- if(!H.dna || !H.dna.species || !(H.dna.species.id == "abductor"))
+ if(H.dna.species.id != "abductor")
return 0
var/datum/species/abductor/S = H.dna.species
ab_team = S.team
diff --git a/code/game/gamemodes/abduction/abduction_gear.dm b/code/game/gamemodes/abduction/abduction_gear.dm
index 9595f0883b9..94966530738 100644
--- a/code/game/gamemodes/abduction/abduction_gear.dm
+++ b/code/game/gamemodes/abduction/abduction_gear.dm
@@ -288,7 +288,7 @@
var/obj/machinery/abductor/console/console
if(ishuman(source))
var/mob/living/carbon/human/H = source
- if(H.dna && istype(H.dna.species, /datum/species/abductor))
+ if(H.dna.species.id == "abductor")
var/datum/species/abductor/S = H.dna.species
console = get_team_console(S.team)
home = console.pad
@@ -405,8 +405,6 @@ Congratulations! You are now trained for xenobiology research!"}
if(!ishuman(user))
return 0
var/mob/living/carbon/human/H = user
- if(!H.dna)
- return 0
if(H.dna.species.id != "abductor")
return 0
return 1
@@ -460,11 +458,16 @@ Congratulations! You are now trained for xenobiology research!"}
/obj/item/weapon/abductor_baton/proc/SleepAttack(mob/living/L,mob/living/user)
if(L.stunned)
L.SetSleeping(60)
- L.visible_message("[user] has induced sleep in [L] with [src]!", \
+ L.visible_message("[user] has induced sleep in [L] with [src]!", \
"You suddenly feel very drowsy!")
- playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
+ playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
- add_logs(user, L, "put to sleep")
+ add_logs(user, L, "put to sleep")
+ else
+ L.drowsyness += 1
+ user << "Sleep inducement works fully only on stunned specimens! "
+ L.visible_message("[user] tried to induce sleep in [L] with [src]!", \
+ "You suddenly feel drowsy!")
return
/obj/item/weapon/abductor_baton/proc/CuffAttack(mob/living/L,mob/living/user)
@@ -490,13 +493,21 @@ Congratulations! You are now trained for xenobiology research!"}
"[user] probes you!")
var/species = "Unknown species"
+ var/helptext = "Species unsuitable for experiments."
+
if(ishuman(L))
var/mob/living/carbon/human/H = L
- if(H.dna && H.dna.species)
- species = "[H.dna.species.name]"
+ species = "[H.dna.species.name]"
if(L.mind && L.mind.changeling)
species = "Changeling lifeform"
+ var/obj/item/organ/internal/gland/temp = locate() in H.internal_organs
+ if(temp)
+ helptext = "Experimental gland detected!"
+ else
+ helptext = "Subject suitable for experiments."
+
user << "Probing result:[species]"
+ user << "[helptext]"
/obj/item/weapon/restraints/handcuffs/energy
name = "hard-light energy field"
diff --git a/code/game/gamemodes/abduction/abduction_surgery.dm b/code/game/gamemodes/abduction/abduction_surgery.dm
index f22f188945b..a97011d53db 100644
--- a/code/game/gamemodes/abduction/abduction_surgery.dm
+++ b/code/game/gamemodes/abduction/abduction_surgery.dm
@@ -8,7 +8,7 @@
if(!ishuman(user))
return 0
var/mob/living/carbon/human/H = user
- if(H.dna && istype(H.dna.species, /datum/species/abductor))
+ if(H.dna.species.id == "abductor")
return 1
if((locate(/obj/item/weapon/implant/abductor) in H))
return 1
diff --git a/code/game/gamemodes/abduction/gland.dm b/code/game/gamemodes/abduction/gland.dm
index fd2ecdcce4c..db0aa0c32dc 100644
--- a/code/game/gamemodes/abduction/gland.dm
+++ b/code/game/gamemodes/abduction/gland.dm
@@ -120,9 +120,7 @@
/obj/item/organ/internal/gland/pop/activate()
owner << "You feel unlike yourself."
var/species = pick(list(/datum/species/lizard,/datum/species/slime,/datum/species/plant/pod,/datum/species/fly))
- hardset_dna(owner, null, null, null, null, species)
- owner.regenerate_icons()
- return
+ owner.set_species(species)
/obj/item/organ/internal/gland/ventcrawling
origin_tech = "materials=4;biotech=5;bluespace=3"
@@ -241,7 +239,7 @@
/obj/effect/cocoon/abductor/proc/Copy(mob/living/carbon/human/H)
var/mob/living/carbon/human/interactive/greytide/clone = new(src)
- hardset_dna(clone,H.dna.uni_identity,H.dna.struc_enzymes,H.real_name, H.dna.blood_type, H.dna.species.type, H.dna.features)
+ clone.hardset_dna(H.dna.uni_identity,H.dna.struc_enzymes,H.real_name, H.dna.blood_type, H.dna.species.type, H.dna.features)
//There's no define for this / get all items ?
var/list/slots = list(slot_back,slot_w_uniform,slot_wear_suit,\
diff --git a/code/game/gamemodes/abduction/machinery/console.dm b/code/game/gamemodes/abduction/machinery/console.dm
index 7bfcc1cb4bc..24f17a5ce92 100644
--- a/code/game/gamemodes/abduction/machinery/console.dm
+++ b/code/game/gamemodes/abduction/machinery/console.dm
@@ -4,8 +4,6 @@
var/team = 0
/obj/machinery/abductor/proc/IsAbductor(mob/living/carbon/human/H)
- if(!H.dna)
- return 0
return H.dna.species.id == "abductor"
/obj/machinery/abductor/proc/IsAgent(mob/living/carbon/human/H)
@@ -28,7 +26,7 @@
icon = 'icons/obj/abductor.dmi'
icon_state = "console"
density = 1
- anchored = 1.0
+ anchored = 1
var/obj/item/device/abductor/gizmo/gizmo
var/obj/item/clothing/suit/armor/abductor/vest/vest
var/obj/machinery/abductor/experiment/experiment
diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm
index 7d64d4ed815..99541008be4 100644
--- a/code/game/gamemodes/antag_spawner.dm
+++ b/code/game/gamemodes/antag_spawner.dm
@@ -1,7 +1,7 @@
/obj/item/weapon/antag_spawner
throw_speed = 1
throw_range = 5
- w_class = 1.0
+ w_class = 1
var/used = 0
/obj/item/weapon/antag_spawner/proc/spawn_antag(client/C, turf/T, type = "")
@@ -98,6 +98,7 @@
M.mind.name = newname
M.real_name = newname
M.name = newname
+ M.dna.update_dna_identity()
var/datum/objective/protect/new_objective = new /datum/objective/protect
new_objective.owner = M:mind
new_objective:target = usr:mind
@@ -119,16 +120,21 @@
target.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll/apprentice(target), slot_r_store)
/obj/item/weapon/antag_spawner/borg_tele
- name = "Syndicate Cyborg Teleporter"
- desc = "A single-use teleporter used to deploy a Syndicate Cyborg on the field."
+ name = "syndicate cyborg teleporter"
+ desc = "A single-use teleporter used to deploy a Syndicate cyborg on the field."
icon = 'icons/obj/device.dmi'
icon_state = "locator"
var/TC_cost = 0
+ var/borg_to_spawn
+ var/list/possible_types = list("Assault", "Medical")
/obj/item/weapon/antag_spawner/borg_tele/attack_self(mob/user)
if(used)
user << "The teleporter is out of power."
return
+ borg_to_spawn = input("What type?", "Cyborg Type", type) as null|anything in possible_types
+ if(!borg_to_spawn)
+ return
var/list/borg_candicates = get_candidates(BE_OPERATIVE)
if(borg_candicates.len > 0)
used = 1
@@ -138,10 +144,18 @@
user << "Unable to connect to Syndicate Command. Please wait and try again later or use the teleporter on your uplink to get your points refunded."
/obj/item/weapon/antag_spawner/borg_tele/spawn_antag(client/C, turf/T, type = "")
+ if(!borg_to_spawn) //If there's no type at all, let it still be used but don't do anything
+ used = 0
+ return
var/datum/effect/effect/system/spark_spread/S = new /datum/effect/effect/system/spark_spread
S.set_up(4, 1, src)
S.start()
- var/mob/living/silicon/robot/R = new /mob/living/silicon/robot/syndicate(T)
+ var/mob/living/silicon/robot/R
+ switch(borg_to_spawn)
+ if("Medical")
+ R = new /mob/living/silicon/robot/syndicate/medical(T)
+ else
+ R = new /mob/living/silicon/robot/syndicate(T) //Assault borg by default
R.key = C.key
ticker.mode.syndicates += R.mind
ticker.mode.update_synd_icons_added(R.mind)
diff --git a/code/game/gamemodes/blob/blob_finish.dm b/code/game/gamemodes/blob/blob_finish.dm
index 743196fbb2a..55f79d883b8 100644
--- a/code/game/gamemodes/blob/blob_finish.dm
+++ b/code/game/gamemodes/blob/blob_finish.dm
@@ -45,8 +45,7 @@
var/datum/game_mode/blob/blob_mode = src
if(blob_mode.infected_crew.len)
var/text = "The blob[(blob_mode.infected_crew.len > 1 ? "s were" : " was")]:"
-
for(var/datum/mind/blob in blob_mode.infected_crew)
- text += " [blob.key] was [blob.name]"
+ text += printplayer(blob)
world << text
- return 1
+ return 1
\ No newline at end of file
diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm
index eeada126134..17e79f569bd 100644
--- a/code/game/gamemodes/blob/blobs/blob_mobs.dm
+++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm
@@ -26,7 +26,7 @@
/mob/living/simple_animal/hostile/blob/blobspore
name = "blob"
- desc = "Some blob thing."
+ desc = "A floating, fragile spore."
icon_state = "blobpod"
icon_living = "blobpod"
health = 40
@@ -39,6 +39,7 @@
var/obj/effect/blob/factory/factory = null
var/list/human_overlays = list()
var/is_zombie = 0
+ gold_core_spawnable = 1
/mob/living/simple_animal/hostile/blob/blobspore/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
@@ -94,12 +95,12 @@
var/turf/location = get_turf(src)
// Create the reagents to put into the air
- create_reagents(5)
+ create_reagents(10)
if(overmind && overmind.blob_reagent_datum)
- reagents.add_reagent(overmind.blob_reagent_datum.id, 5)
+ reagents.add_reagent(overmind.blob_reagent_datum.id, 10)
else
- reagents.add_reagent("spore", 5)
+ reagents.add_reagent("spore", 10)
// Attach the smoke spreader and setup/start it.
S.attach(location)
@@ -116,7 +117,7 @@
if(contents)
for(var/mob/M in contents)
M.loc = src.loc
- ..()
+ return ..()
/mob/living/simple_animal/hostile/blob/blobspore/update_icons()
@@ -145,7 +146,7 @@
/mob/living/simple_animal/hostile/blob/blobbernaut
name = "blobbernaut"
- desc = "Some HUGE blob thing."
+ desc = "A hulking, mobile chunk of blobmass."
icon_state = "blobbernaut"
icon_living = "blobbernaut"
icon_dead = "blobbernaut_dead"
@@ -161,7 +162,7 @@
force_threshold = 10
environment_smash = 3
mob_size = MOB_SIZE_LARGE
-
+ gold_core_spawnable = 1
/mob/living/simple_animal/hostile/blob/blobbernaut/blob_act()
return
diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm
index dc5fbd797d0..b4abfdc9e57 100644
--- a/code/game/gamemodes/blob/blobs/core.dm
+++ b/code/game/gamemodes/blob/blobs/core.dm
@@ -2,9 +2,10 @@
name = "blob core"
icon = 'icons/mob/blob.dmi'
icon_state = "blank_blob"
- health = 200
- fire_resist = 2
- var/mob/camera/blob/overmind = null // the blob core's overmind
+ desc = "A huge, pulsating yellow mass."
+ health = 400
+ maxhealth = 400
+ explosion_block = 6
var/overmind_get_delay = 0 // we don't want to constantly try to find an overmind, do it every 30 seconds
var/resource_delay = 0
var/point_rate = 2
@@ -40,11 +41,14 @@
overmind.blob_core = null
overmind = null
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/effect/blob/core/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
+/obj/effect/blob/core/ex_act(severity, target)
+ return
+
/obj/effect/blob/core/update_icon()
if(health <= 0)
qdel(src)
@@ -64,18 +68,18 @@
if(resource_delay <= world.time)
resource_delay = world.time + 10 // 1 second
overmind.add_points(point_rate)
- health = min(initial(health), health + 1)
+ health = min(maxhealth, health+health_regen)
if(overmind)
overmind.update_health()
- for(var/i = 1; i < 8; i += i)
- Pulse(0, i, overmind.blob_reagent_datum.color)
+ pulseLoop(0)
for(var/b_dir in alldirs)
if(!prob(5))
continue
var/obj/effect/blob/normal/B = locate() in get_step(src, b_dir)
if(B)
- B.change_to(/obj/effect/blob/shield)
- B.color = overmind.blob_reagent_datum.color
+ var/obj/effect/blob/N = B.change_to(/obj/effect/blob/shield)
+ if(overmind)
+ N.color = overmind.blob_reagent_datum.color
color = null
..()
diff --git a/code/game/gamemodes/blob/blobs/factory.dm b/code/game/gamemodes/blob/blobs/factory.dm
index 4138d56cbc6..f3e15c06ee2 100644
--- a/code/game/gamemodes/blob/blobs/factory.dm
+++ b/code/game/gamemodes/blob/blobs/factory.dm
@@ -2,12 +2,12 @@
name = "factory blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_factory"
- health = 100
- fire_resist = 2
+ desc = "A thick spire of tendrils."
+ health = 200
+ maxhealth = 200
var/list/spores = list()
var/max_spores = 3
var/spore_delay = 0
- var/mob/camera/blob/overmind
/obj/effect/blob/factory/update_icon()
if(health <= 0)
@@ -18,7 +18,7 @@
if(spore.factory == src)
spore.factory = null
spores = null
- ..()
+ return ..()
/obj/effect/blob/factory/PulseAnimation(activate = 0)
if(activate)
diff --git a/code/game/gamemodes/blob/blobs/node.dm b/code/game/gamemodes/blob/blobs/node.dm
index 0b8124daacd..e7882bf60a8 100644
--- a/code/game/gamemodes/blob/blobs/node.dm
+++ b/code/game/gamemodes/blob/blobs/node.dm
@@ -2,9 +2,9 @@
name = "blob node"
icon = 'icons/mob/blob.dmi'
icon_state = "blank_blob"
- health = 100
- fire_resist = 2
- var/mob/camera/blob/overmind
+ desc = "A large, pulsating yellow mass."
+ health = 200
+ maxhealth = 200
/obj/effect/blob/node/New(loc, var/h = 100)
blob_nodes += src
@@ -26,11 +26,10 @@
/obj/effect/blob/node/Destroy()
blob_nodes -= src
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/effect/blob/node/Life()
- for(var/i = 1; i < 8; i += i)
- Pulse(5, i, overmind.blob_reagent_datum.color)
+ pulseLoop(5)
health = min(initial(health), health + 1)
color = null
diff --git a/code/game/gamemodes/blob/blobs/resource.dm b/code/game/gamemodes/blob/blobs/resource.dm
index 45b1e08687d..3237540e385 100644
--- a/code/game/gamemodes/blob/blobs/resource.dm
+++ b/code/game/gamemodes/blob/blobs/resource.dm
@@ -2,9 +2,9 @@
name = "resource blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_resource"
- health = 30
- fire_resist = 2
- var/mob/camera/blob/overmind = null
+ desc = "A thin spire of slightly swaying tendrils."
+ health = 60
+ maxhealth = 60
var/resource_delay = 0
/obj/effect/blob/resource/update_icon()
diff --git a/code/game/gamemodes/blob/blobs/shield.dm b/code/game/gamemodes/blob/blobs/shield.dm
index 1c145f4404f..97b6174d35e 100644
--- a/code/game/gamemodes/blob/blobs/shield.dm
+++ b/code/game/gamemodes/blob/blobs/shield.dm
@@ -2,9 +2,10 @@
name = "strong blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_idle"
- desc = "Some blob creature thingy"
- health = 75
- fire_resist = 2
+ desc = "A solid wall of slightly twitching tendrils."
+ health = 150
+ maxhealth = 150
+ explosion_block = 3
/obj/effect/blob/shield/update_icon()
@@ -16,6 +17,9 @@
/obj/effect/blob/shield/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
+/obj/effect/blob/shield/CanAtmosPass(turf/T)
+ return 0
+
/obj/effect/blob/shield/CanPass(atom/movable/mover, turf/target, height=0)
if(istype(mover) && mover.checkpass(PASSBLOB)) return 1
return 0
diff --git a/code/game/gamemodes/blob/blobs/storage.dm b/code/game/gamemodes/blob/blobs/storage.dm
index 47b50a5bb03..282fe9fca53 100644
--- a/code/game/gamemodes/blob/blobs/storage.dm
+++ b/code/game/gamemodes/blob/blobs/storage.dm
@@ -2,9 +2,9 @@
name = "storage blob"
icon = 'icons/mob/blob.dmi'
icon_state = "blob_resource"
- health = 30
- fire_resist = 2
- var/mob/camera/blob/overmind = null
+ desc = "A huge, smooth mass supported by tendrils."
+ health = 60
+ maxhealth = 60
/obj/effect/blob/storage/update_icon()
if(health <= 0)
diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm
index 26ffc2d65c5..f97ae377668 100644
--- a/code/game/gamemodes/blob/overmind.dm
+++ b/code/game/gamemodes/blob/overmind.dm
@@ -47,7 +47,7 @@
qdel(ghostimage)
ghostimage = null;
updateallghostimages()
- ..()
+ return ..()
/mob/camera/blob/Login()
..()
@@ -96,7 +96,7 @@
if (!message)
return
- var/message_a = say_quote(message)
+ var/message_a = say_quote(message, get_spans())
var/rendered = "Blob Telepathy, [name]([blob_reagent_datum.name])[message_a]"
for (var/mob/M in mob_list)
diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm
index 78c15e08e5e..a0c97c1da99 100644
--- a/code/game/gamemodes/blob/powers.dm
+++ b/code/game/gamemodes/blob/powers.dm
@@ -1,5 +1,3 @@
-// Point controlling procs
-
/mob/camera/blob/proc/can_buy(cost = 15)
if(blob_points < cost)
src << "You cannot afford this!"
@@ -13,7 +11,6 @@
set category = "Blob"
set name = "Jump to Core"
set desc = "Transport back to your core."
-
if(blob_core)
src.loc = blob_core.loc
@@ -21,7 +18,6 @@
set category = "Blob"
set name = "Jump to Node"
set desc = "Transport back to a selected node."
-
if(blob_nodes.len)
var/list/nodes = list()
for(var/i = 1; i <= blob_nodes.len; i++)
@@ -31,288 +27,166 @@
if(chosen_node)
src.loc = chosen_node.loc
+/mob/camera/blob/proc/createSpecial(price, blobType, nearEquals, turf/T)
+ if(!T)
+ T = get_turf(src)
+ var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
+ if(!B)
+ src << "There is no blob here!"
+ return
+ if(!istype(B, /obj/effect/blob/normal))
+ src << "Unable to use this blob, find a normal one."
+ return
+ if(nearEquals)
+ for(var/obj/effect/blob/L in orange(nearEquals, T))
+ if(L.type == blobType)
+ src << "There is a similar blob nearby, move more than [nearEquals] tiles away from it!"
+ return
+ if(!can_buy(price))
+ return
+ B.color = blob_reagent_datum.color
+ var/obj/effect/blob/N = B.change_to(blobType)
+ N.overmind = src
+ N.adjustcolors(blob_reagent_datum.color)
+ return N
+
/mob/camera/blob/verb/create_shield_power()
set category = "Blob"
set name = "Create Shield Blob (10)"
set desc = "Create a shield blob."
-
- var/turf/T = get_turf(src)
- create_shield(T)
+ create_shield()
/mob/camera/blob/proc/create_shield(turf/T)
-
- var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
-
- if(!B)//We are on a blob
- src << "There is no blob here!"
- return
-
- if(!istype(B, /obj/effect/blob/normal))
- src << "Unable to use this blob, find a normal one."
- return
-
- if(!can_buy(10))
- return
-
- B.color = blob_reagent_datum.color
- B.change_to(/obj/effect/blob/shield)
-
- return
-
-
+ createSpecial(10, /obj/effect/blob/shield, 0, T)
/mob/camera/blob/verb/create_resource()
set category = "Blob"
set name = "Create Resource Blob (40)"
set desc = "Create a resource tower which will generate points for you."
-
-
- var/turf/T = get_turf(src)
-
- if(!T)
- return
-
- var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
-
- if(!B)//We are on a blob
- src << "There is no blob here!"
- return
-
- if(!istype(B, /obj/effect/blob/normal))
- src << "Unable to use this blob, find a normal one."
- return
-
- for(var/obj/effect/blob/resource/blob in orange(4, T))
- src << "There is a resource blob nearby, move more than 4 tiles away from it!"
- return
-
- if(!can_buy(40))
- return
-
- B.color = blob_reagent_datum.color
- B.change_to(/obj/effect/blob/resource)
- var/obj/effect/blob/resource/R = locate() in T
- if(R)
- R.overmind = src
-
- return
+ createSpecial(40, /obj/effect/blob/resource, 4)
/mob/camera/blob/verb/create_node()
set category = "Blob"
set name = "Create Node Blob (60)"
set desc = "Create a Node."
-
-
- var/turf/T = get_turf(src)
-
- if(!T)
- return
-
- var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
-
- if(!B)//We are on a blob
- src << "There is no blob here!"
- return
-
- if(!istype(B, /obj/effect/blob/normal))
- src << "Unable to use this blob, find a normal one."
- return
-
- for(var/obj/effect/blob/node/blob in orange(5, T))
- src << "There is another node nearby, move more than 5 tiles away from it!"
- return
-
- if(!can_buy(60))
- return
-
- B.change_to(/obj/effect/blob/node)
- var/obj/effect/blob/node/R = locate() in T
- if(R)
- R.adjustcolors(blob_reagent_datum.color)
- R.overmind = src
- return
-
+ createSpecial(60, /obj/effect/blob/node, 5)
/mob/camera/blob/verb/create_factory()
set category = "Blob"
set name = "Create Factory Blob (60)"
set desc = "Create a Spore producing blob."
+ createSpecial(60, /obj/effect/blob/factory, 7)
-
- var/turf/T = get_turf(src)
-
- if(!T)
- return
-
- var/obj/effect/blob/B = locate(/obj/effect/blob) in T
- if(!B)
- src << "You must be on a blob!"
- return
-
- if(!istype(B, /obj/effect/blob/normal))
- src << "Unable to use this blob, find a normal one."
- return
-
- for(var/obj/effect/blob/factory/blob in orange(7, T))
- src << "There is a factory blob nearby, move more than 7 tiles away from it!"
- return
-
- if(!can_buy(60))
- return
-
- B.change_to(/obj/effect/blob/factory)
- B.color = blob_reagent_datum.color
- var/obj/effect/blob/factory/R = locate() in T
- if(R)
- R.overmind = src
- return
-
+/mob/camera/blob/verb/create_storage()
+ set category = "Blob"
+ set name = "Create Storage Blob (40)"
+ set desc = "Create a storage tower which will store extra resources for you. This increases your max resource cap by 50."
+ var/obj/effect/blob/storage/R = createSpecial(40, /obj/effect/blob/storage, 3)
+ R.update_max_blob_points(50)
/mob/camera/blob/verb/create_blobbernaut()
set category = "Blob"
set name = "Create Blobbernaut (20)"
set desc = "Create a powerful blob-being, a Blobbernaut"
-
var/turf/T = get_turf(src)
-
- if(!T)
- return
-
var/obj/effect/blob/B = locate(/obj/effect/blob) in T
if(!B)
src << "You must be on a blob!"
return
-
if(!istype(B, /obj/effect/blob/factory))
src << "Unable to use this blob, find a factory blob."
return
-
if(!can_buy(20))
return
-
var/mob/living/simple_animal/hostile/blob/blobbernaut/blobber = new /mob/living/simple_animal/hostile/blob/blobbernaut (get_turf(B))
if(blobber)
qdel(B)
blobber.color = blob_reagent_datum.color
blobber.overmind = src
blob_mobs.Add(blobber)
- return
-
/mob/camera/blob/verb/relocate_core()
set category = "Blob"
set name = "Relocate Core (80)"
set desc = "Relocates your core to the node you are on, your old core will be turned into a node."
-
-
var/turf/T = get_turf(src)
-
- if(!T)
- return
-
var/obj/effect/blob/node/B = locate(/obj/effect/blob/node) in T
if(!B)
src << "You must be on a blob node!"
return
-
if(!can_buy(80))
return
-
- // The old switcharoo.
var/turf/old_turf = blob_core.loc
blob_core.loc = T
B.loc = old_turf
- return
-
/mob/camera/blob/verb/revert()
set category = "Blob"
set name = "Remove Blob"
set desc = "Removes a blob."
-
var/turf/T = get_turf(src)
- if(!T)
- return
-
var/obj/effect/blob/B = locate(/obj/effect/blob) in T
if(!B)
src << "You must be on a blob!"
return
-
if(istype(B, /obj/effect/blob/core))
src << "Unable to remove this blob."
return
-
qdel(B)
- return
-
/mob/camera/blob/verb/expand_blob_power()
set category = "Blob"
set name = "Expand/Attack Blob (5)"
set desc = "Attempts to create a new blob in this tile. If the tile isn't clear we will attack it, which might clear it."
-
var/turf/T = get_turf(src)
expand_blob(T)
/mob/camera/blob/proc/expand_blob(turf/T)
- if(!T)
- return
-
if(!can_attack())
return
var/obj/effect/blob/B = locate() in T
if(B)
src << "There is a blob here!"
return
-
var/obj/effect/blob/OB = locate() in circlerange(T, 1)
if(!OB)
src << "There is no blob adjacent to you."
return
-
if(!can_buy(5))
return
last_attack = world.time
OB.expand(T, 0, blob_reagent_datum.color)
for(var/mob/living/L in T)
- blob_reagent_datum.reaction_mob(L, TOUCH, 25)
+ if("blob" in L.faction) //no friendly fire
+ continue
+ var/mob_protection = L.get_permeability_protection()
+ blob_reagent_datum.reaction_mob(L, VAPOR, 25, 1, mob_protection)
blob_reagent_datum.send_message(L)
OB.color = blob_reagent_datum.color
- return
-
/mob/camera/blob/verb/rally_spores_power()
set category = "Blob"
set name = "Rally Spores (5)"
set desc = "Rally the spores to move to your location."
-
var/turf/T = get_turf(src)
rally_spores(T)
/mob/camera/blob/proc/rally_spores(turf/T)
-
if(!can_buy(5))
return
-
src << "You rally your spores."
-
var/list/surrounding_turfs = block(locate(T.x - 1, T.y - 1, T.z), locate(T.x + 1, T.y + 1, T.z))
if(!surrounding_turfs.len)
return
-
for(var/mob/living/simple_animal/hostile/blob/blobspore/BS in living_mob_list)
if(isturf(BS.loc) && get_dist(BS, T) <= 35)
BS.LoseTarget()
BS.Goto(pick(surrounding_turfs), BS.move_to_delay)
- return
-
/mob/camera/blob/verb/split_consciousness()
set category = "Blob"
set name = "Split consciousness (100) (One use)"
set desc = "Expend resources to attempt to produce another sentient overmind"
-
if(!blob_nodes || !blob_nodes.len)
src << "A node is required to birth your offspring..."
return
@@ -320,88 +194,38 @@
if(!N)
src << "A node is required to birth your offspring..."
return
-
if(!can_buy(100))
return
-
- verbs -= /mob/camera/blob/verb/split_consciousness //we've used our split_consciousness
+ verbs -= /mob/camera/blob/verb/split_consciousness
new /obj/effect/blob/core/ (get_turf(N), 200, null, blob_core.point_rate, "offspring")
qdel(N)
-
if(ticker && ticker.mode.name == "blob")
var/datum/game_mode/blob/BL = ticker.mode
BL.blobwincount = initial(BL.blobwincount) * 2
-
/mob/camera/blob/verb/blob_broadcast()
set category = "Blob"
set name = "Blob Broadcast"
set desc = "Speak with your blob spores and blobbernauts as your mouthpieces. This action is free."
-
var/speak_text = input(usr, "What would you like to say with your minions?", "Blob Broadcast", null) as text
-
if(!speak_text)
return
else
usr << "You broadcast with your minions, [speak_text]"
for(var/mob/living/simple_animal/hostile/blob_minion in blob_mobs)
blob_minion.say(speak_text)
- return
-
-/mob/camera/blob/verb/create_storage()
- set category = "Blob"
- set name = "Create Storage Blob (40)"
- set desc = "Create a storage tower which will store extra resources for you. This increases your max resource cap by 50."
-
-
- var/turf/T = get_turf(src)
-
- if(!T)
- return
-
- var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
-
- if(!B)//We are on a blob
- src << "There is no blob here!"
- return
-
- if(!istype(B, /obj/effect/blob/normal))
- src << "Unable to use this blob, find a normal one."
- return
-
- for(var/obj/effect/blob/storage/blob in orange(3, T))
- src << "There is a storage blob nearby, move more than 4 tiles away from it!"
- return
-
- if(!can_buy(40))
- return
-
- B.color = blob_reagent_datum.color
- B.change_to(/obj/effect/blob/storage)
- var/obj/effect/blob/storage/R = locate() in T
- if(R)
- R.overmind = src
- R.update_max_blob_points(50)
-
- return
-
/mob/camera/blob/verb/chemical_reroll()
set category = "Blob"
set name = "Reactive Chemical Adaptation (50)"
set desc = "Replaces your chemical with a different one"
-
if(!can_buy(50))
return
-
- var/list/excluded = list(/datum/reagent/blob, blob_reagent_datum.type) //guaranteed new chemical
+ var/list/excluded = list(/datum/reagent/blob, blob_reagent_datum.type)
var/datum/reagent/blob/B = pick((typesof(/datum/reagent/blob) - excluded))
blob_reagent_datum = new B
-
for(var/obj/effect/blob/BL in blobs)
BL.adjustcolors(blob_reagent_datum.color)
-
for(var/mob/living/simple_animal/hostile/blob/BLO)
BLO.adjustcolors(blob_reagent_datum.color)
-
src << "Your reagent is now: [blob_reagent_datum.name]!"
\ No newline at end of file
diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm
index afed6be3354..3945dc31164 100644
--- a/code/game/gamemodes/blob/theblob.dm
+++ b/code/game/gamemodes/blob/theblob.dm
@@ -3,14 +3,18 @@
name = "blob"
icon = 'icons/mob/blob.dmi'
luminosity = 3
- desc = "Some blob creature thingy"
- density = 0
+ desc = "A thick wall of writhing tendrils."
+ density = 0 //this being 0 causes two bugs, being able to attack blob tiles behind other blobs and being unable to move on blob tiles in no gravity, but turning it to 1 causes the blob mobs to be unable to path through blobs, which is probably worse.
opacity = 0
anchored = 1
+ explosion_block = 1
var/health = 30
+ var/maxhealth = 30
+ var/health_regen = 2
var/health_timestamp = 0
- var/brute_resist = 4
+ var/brute_resist = 2
var/fire_resist = 1
+ var/mob/camera/blob/overmind
/obj/effect/blob/New(loc)
@@ -27,7 +31,7 @@
blobs -= src
if(isturf(loc)) //Necessary because Expand() is retarded and spawns a blob and then deletes it
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
- ..()
+ return ..()
/obj/effect/blob/CanPass(atom/movable/mover, turf/target, height=0)
@@ -57,11 +61,16 @@
// All blobs heal over time when pulsed, but it has a cool down
if(health_timestamp > world.time)
return 0
- if(health < initial(health))
- health++
- update_icon()
- health_timestamp = world.time + 10 // 1 seconds
+ health = min(maxhealth, health+health_regen)
+ update_icon()
+ health_timestamp = world.time + 10 // 1 seconds
+/obj/effect/blob/proc/pulseLoop(num)
+ var/a_color
+ if(overmind)
+ a_color = overmind.blob_reagent_datum.color
+ for(var/i = 1; i < 8; i += i)
+ Pulse(num, i, a_color)
/obj/effect/blob/proc/Pulse(pulse = 0, origin_dir = 0, a_color)//Todo: Fix spaceblob expand
@@ -102,7 +111,6 @@
/obj/effect/blob/proc/expand(turf/T = null, prob = 1, a_color)
if(prob && !prob(health)) return
- if(istype(T, /turf/space) && prob(75)) return
if(!T)
var/list/dirs = list(1,2,4,8)
for(var/i = 1 to 4)
@@ -113,12 +121,15 @@
else T = null
if(!T) return 0
- var/obj/effect/blob/normal/B = new /obj/effect/blob/normal(src.loc, min(src.health, 30))
+ var/obj/effect/blob/B = new /obj/effect/blob/normal(src.loc)
+ if(istype(T, /turf/space) && prob(65))
+ B.health = 0
B.color = a_color
B.density = 1
if(T.Enter(B,src))//Attempt to move into the tile
B.density = initial(B.density)
B.loc = T
+ B.update_icon()
else
T.blob_act()//If we cant move in hit the turf
B.loc = null //So we don't play the splat sound, see Destroy()
@@ -191,6 +202,7 @@
else
B.adjustcolors(color)
qdel(src)
+ return B
/obj/effect/blob/proc/adjustcolors(a_color)
if(a_color)
@@ -199,7 +211,7 @@
/obj/effect/blob/examine(mob/user)
..()
- user << "It looks like it's of a [get_chem_name()] kind."
+ user << "It seems to be made of [get_chem_name()]."
return
/obj/effect/blob/proc/get_chem_name()
@@ -212,14 +224,23 @@
icon_state = "blob"
luminosity = 0
health = 21
+ maxhealth = 25
+ health_regen = 1
+ brute_resist = 4
/obj/effect/blob/normal/update_icon()
if(health <= 0)
qdel(src)
- else if(health <= 15)
+ else if(health <= 10)
icon_state = "blob_damaged"
+ name = "fragile blob"
+ desc = "A thin lattice of slightly twitching tendrils."
+ brute_resist = 2
else
icon_state = "blob"
+ name = "blob"
+ desc = "A thick wall of writhing tendrils."
+ brute_resist = 4
/* // Used to create the glow sprites. Remember to set the animate loop to 1, instead of infinite!
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index 6132d740f33..c6033743ce7 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -1,9 +1,12 @@
-
#define LING_FAKEDEATH_TIME 400 //40 seconds
#define LING_DEAD_GENETICDAMAGE_HEAL_CAP 50 //The lowest value of geneticdamage handle_changeling() can take it to while dead.
#define LING_ABSORB_RECENT_SPEECH 8 //The amount of recent spoken lines to gain on absorbing a mob
var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega")
+var/list/slots = list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store")
+var/list/slot2slot = list("head" = slot_head, "wear_mask" = slot_wear_mask, "back" = slot_back, "wear_suit" = slot_wear_suit, "w_uniform" = slot_w_uniform, "shoes" = slot_shoes, "belt" = slot_belt, "gloves" = slot_gloves, "glasses" = slot_glasses, "ears" = slot_ears, "wear_id" = slot_wear_id, "s_store" = slot_s_store)
+var/list/slot2type = list("head" = /obj/item/clothing/head/changeling, "wear_mask" = /obj/item/clothing/mask/changeling, "back" = /obj/item/changeling, "wear_suit" = /obj/item/clothing/suit/changeling, "w_uniform" = /obj/item/clothing/under/changeling, "shoes" = /obj/item/clothing/shoes/changeling, "belt" = /obj/item/changeling, "gloves" = /obj/item/clothing/gloves/changeling, "glasses" = /obj/item/clothing/glasses/changeling, "ears" = /obj/item/changeling, "wear_id" = /obj/item/changeling, "s_store" = /obj/item/changeling)
+
/datum/game_mode
var/list/datum/mind/changelings = list()
@@ -40,6 +43,8 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
var/const/changeling_amount = 4 //hard limit on changelings if scaling is turned off
+ var/changeling_team_objective_type = null //If this is not null, we hand our this objective to all lings
+
/datum/game_mode/changeling/announce()
world << "The current game mode is - Changeling!"
world << "There are alien changelings on the station. Do not let the changelings succeed!"
@@ -72,6 +77,20 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
return 0
/datum/game_mode/changeling/post_setup()
+
+ //Decide if it's ok for the lings to have a team objective
+ //And then set it up to be handed out in forge_changeling_objectives
+ var/list/team_objectives = typesof(/datum/objective/changeling_team_objective) - /datum/objective/changeling_team_objective
+ var/list/possible_team_objectives = list()
+ for(var/T in team_objectives)
+ var/datum/objective/changeling_team_objective/CTO = T
+
+ if(changelings.len >= initial(CTO.min_lings))
+ possible_team_objectives += T
+
+ if(possible_team_objectives.len && prob(20*changelings.len))
+ changeling_team_objective_type = pick(possible_team_objectives)
+
for(var/datum/mind/changeling in changelings)
log_game("[changeling.key] (ckey) has been selected as a changeling")
changeling.current.make_changeling()
@@ -92,11 +111,18 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
if(!(character.job in restricted_jobs))
character.mind.make_Changling()
-/datum/game_mode/proc/forge_changeling_objectives(datum/mind/changeling)
+/datum/game_mode/proc/forge_changeling_objectives(datum/mind/changeling, var/team_mode = 0)
//OBJECTIVES - random traitor objectives. Unique objectives "steal brain" and "identity theft".
//No escape alone because changelings aren't suited for it and it'd probably just lead to rampant robusting
//If it seems like they'd be able to do it in play, add a 10% chance to have to escape alone
+ var/escape_objective_possible = TRUE
+
+ //if there's a team objective, check if it's compatible with escape objectives
+ for(var/datum/objective/changeling_team_objective/CTO in changeling.objectives)
+ if(!CTO.escape_objective_compatible)
+ escape_objective_possible = FALSE
+ break
var/datum/objective/absorb/absorb_objective = new
absorb_objective.owner = changeling
@@ -108,12 +134,6 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
steal_objective.owner = changeling
steal_objective.find_target()
changeling.objectives += steal_objective
- else
- var/datum/objective/debrain/debrain_objective = new
- debrain_objective.owner = changeling
- debrain_objective.find_target()
- changeling.objectives += debrain_objective
-
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/joined_player_list.len))
@@ -125,22 +145,29 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
if(prob(70))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = changeling
- kill_objective.find_target()
+ if(team_mode) //No backstabbing while in a team
+ kill_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
+ else
+ kill_objective.find_target()
changeling.objectives += kill_objective
else
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = changeling
- maroon_objective.find_target()
+ if(team_mode)
+ maroon_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
+ else
+ maroon_objective.find_target()
changeling.objectives += maroon_objective
- if (!(locate(/datum/objective/escape) in changeling.objectives))
+ if (!(locate(/datum/objective/escape) in changeling.objectives) && escape_objective_possible)
var/datum/objective/escape/escape_with_identity/identity_theft = new
identity_theft.owner = changeling
identity_theft.target = maroon_objective.target
identity_theft.update_explanation_text()
changeling.objectives += identity_theft
+ escape_objective_possible = FALSE
- if (!(locate(/datum/objective/escape) in changeling.objectives))
+ if (!(locate(/datum/objective/escape) in changeling.objectives) && escape_objective_possible)
if(prob(50))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = changeling
@@ -148,9 +175,25 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
else
var/datum/objective/escape/escape_with_identity/identity_theft = new
identity_theft.owner = changeling
- identity_theft.find_target()
+ if(team_mode)
+ identity_theft.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
+ else
+ identity_theft.find_target()
changeling.objectives += identity_theft
- return
+ escape_objective_possible = FALSE
+
+
+
+/datum/game_mode/changeling/forge_changeling_objectives(datum/mind/changeling)
+ if(changeling_team_objective_type)
+ var/datum/objective/changeling_team_objective/team_objective = new changeling_team_objective_type
+ team_objective.owner = changeling
+ changeling.objectives += team_objective
+
+ ..(changeling,1)
+ else
+ ..(changeling,0)
+
/datum/game_mode/proc/greet_changeling(datum/mind/changeling, you_are=1)
if (you_are)
@@ -232,13 +275,15 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
return 1
/datum/changeling //stores changeling powers, changeling recharge thingie, changeling absorbed DNA and changeling ID (for changeling hivemind)
- var/list/absorbed_dna = list()
- var/list/protected_dna = list() //dna that is not lost when capacity is otherwise full
- var/dna_max = 4 //How many extra DNA strands the changeling can store for transformation.
- var/absorbedcount = 1 //We would require at least 1 sample of compatible DNA to have taken on the form of a human.
+ var/list/stored_profiles = list() //list of datum/changelingprofile
+ var/datum/changelingprofile/first_prof = null
+ //var/list/absorbed_dna = list()
+ //var/list/protected_dna = list() //dna that is not lost when capacity is otherwise full
+ var/dna_max = 6 //How many extra DNA strands the changeling can store for transformation.
+ var/absorbedcount = 0
var/chem_charges = 20
- var/chem_storage = 50
- var/chem_recharge_rate = 0.5
+ var/chem_storage = 75
+ var/chem_recharge_rate = 1
var/chem_recharge_slowdown = 0
var/sting_range = 2
var/changelingID = "Changeling"
@@ -263,7 +308,6 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
changelingID = "[honorific] [changelingID]"
else
changelingID = "[honorific] [rand(1,999)]"
- absorbed_dna.len = dna_max
/datum/changeling/proc/regenerate(var/mob/living/carbon/the_ling)
@@ -277,31 +321,159 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
/datum/changeling/proc/get_dna(dna_owner)
- for(var/datum/dna/DNA in (absorbed_dna+protected_dna))
- if(dna_owner == DNA.real_name)
- return DNA
+ for(var/datum/changelingprofile/prof in stored_profiles)
+ if(dna_owner == prof.name)
+ return prof
/datum/changeling/proc/has_dna(datum/dna/tDNA)
- for(var/datum/dna/D in (absorbed_dna+protected_dna))
- if(tDNA.is_same_as(D))
+ for(var/datum/changelingprofile/prof in stored_profiles)
+ if(tDNA.is_same_as(prof.dna))
return 1
return 0
-/datum/changeling/proc/can_absorb_dna(mob/living/carbon/user, mob/living/carbon/target)
- if(absorbed_dna[1] == user.dna)//If our current DNA is the stalest, we gotta ditch it.
- user << "We have reached our capacity to store genetic information! We must transform before absorbing more."
- return
+/datum/changeling/proc/can_absorb_dna(mob/living/carbon/user, mob/living/carbon/human/target, var/verbose=1)
+ if(stored_profiles.len)
+ var/datum/changelingprofile/prof = stored_profiles[1]
+ if(prof.dna == user.dna && stored_profiles.len >= dna_max)//If our current DNA is the stalest, we gotta ditch it.
+ if(verbose)
+ user << "We have reached our capacity to store genetic information! We must transform before absorbing more."
+ return
if(!target)
return
if((target.disabilities & NOCLONE) || (target.disabilities & HUSK))
- user << "DNA of [target] is ruined beyond usability!"
+ if(verbose)
+ user << "DNA of [target] is ruined beyond usability!"
return
if(!ishuman(target))//Absorbing monkeys is entirely possible, but it can cause issues with transforming. That's what lesser form is for anyway!
- user << "We could gain no benefit from absorbing a lesser creature."
+ if(verbose)
+ user << "We could gain no benefit from absorbing a lesser creature."
return
if(has_dna(target.dna))
- user << "We already have this DNA in storage!"
- if(!check_dna_integrity(target))
- user << "[target] is not compatible with our biology."
+ if(verbose)
+ user << "We already have this DNA in storage!"
+ return
+ if(!target.has_dna())
+ if(verbose)
+ user << "[target] is not compatible with our biology."
return
return 1
+
+/datum/changeling/proc/add_profile(var/mob/living/carbon/human/H, var/mob/living/carbon/user, protect = 0)
+ if(stored_profiles.len > dna_max)
+ if(!push_out_profile())
+ return
+
+ var/datum/changelingprofile/prof = new()
+
+ H.dna.real_name = H.real_name //Set this again, just to be sure that it's properly set.
+ var/datum/dna/new_dna = new H.dna.type
+ H.dna.copy_dna(new_dna)
+ prof.dna = new_dna
+ prof.name = H.real_name
+ prof.protected = protect
+
+ prof.underwear = H.underwear
+ prof.undershirt = H.undershirt
+ prof.socks = H.socks
+
+ var/list/slots = list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store")
+ for(var/slot in slots)
+ if(slot in H.vars)
+ var/obj/item/I = H.vars[slot]
+ if(!I)
+ continue
+ prof.name_list[slot] = I.name
+ prof.appearance_list[slot] = I.appearance
+ prof.flags_cover_list[slot] = I.flags_cover
+ prof.item_color_list[slot] = I.item_color
+ prof.item_state_list[slot] = I.item_state
+ prof.exists_list[slot] = 1
+ else
+ continue
+
+ stored_profiles += prof
+ absorbedcount++
+
+ return prof
+
+/datum/changeling/proc/remove_profile(var/mob/living/carbon/human/H, force = 0)
+ for(var/datum/changelingprofile/prof in stored_profiles)
+ if(H.real_name == prof.name)
+ if(prof.protected && !force)
+ continue
+ stored_profiles -= prof
+ qdel(prof)
+
+/datum/changeling/proc/get_profile_to_remove()
+ for(var/datum/changelingprofile/prof in stored_profiles)
+ if(!prof.protected)
+ return prof
+
+/datum/changeling/proc/push_out_profile()
+ var/datum/changelingprofile/removeprofile = get_profile_to_remove()
+ if(removeprofile)
+ stored_profiles -= removeprofile
+ return 1
+ return 0
+
+/proc/changeling_transform(var/mob/living/carbon/human/user, var/datum/changelingprofile/chosen_prof)
+ var/datum/dna/chosen_dna = chosen_prof.dna
+ user.real_name = chosen_prof.name
+ user.underwear = chosen_prof.underwear
+ user.undershirt = chosen_prof.undershirt
+ user.socks = chosen_prof.socks
+
+ chosen_dna.transfer_identity(user, 1)
+ user.updateappearance(mutcolor_update=1)
+ user.update_body()
+ user.domutcheck()
+
+ //vars hackery. not pretty, but better than the alternative.
+ for(var/slot in slots)
+ if(istype(user.vars[slot], slot2type[slot]) && !(chosen_prof.exists_list[slot])) //remove unnecessary flesh items
+ qdel(user.vars[slot])
+ continue
+
+ if((user.vars[slot] && !istype(user.vars[slot], slot2type[slot])) || !(chosen_prof.exists_list[slot]))
+ continue
+
+ var/obj/item/C
+ var/equip = 0
+ if(!user.vars[slot])
+ var/thetype = slot2type[slot]
+ equip = 1
+ C = new thetype(user)
+
+ else if(istype(user.vars[slot], slot2type[slot]))
+ C = user.vars[slot]
+
+ C.appearance = chosen_prof.appearance_list[slot]
+ C.name = chosen_prof.name_list[slot]
+ C.flags_cover = chosen_prof.flags_cover_list[slot]
+ C.item_color = chosen_prof.item_color_list[slot]
+ C.item_state = chosen_prof.item_state_list[slot]
+ if(equip)
+ user.equip_to_slot_or_del(C, slot2slot[slot])
+
+ user.regenerate_icons()
+
+/datum/changelingprofile
+ var/name = "a bug"
+
+ var/protected = 0
+
+ var/datum/dna/dna = null
+ var/list/name_list = list() //associative list of slotname = itemname
+ var/list/appearance_list = list()
+ var/list/flags_cover_list = list()
+ var/list/exists_list = list()
+ var/list/item_color_list = list()
+ var/list/item_state_list = list()
+
+ var/underwear
+ var/undershirt
+ var/socks
+
+/datum/changelingprofile/Destroy()
+ qdel(dna)
+ return ..()
\ No newline at end of file
diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm
index 19315f476c0..bdd7fc1ac7c 100644
--- a/code/game/gamemodes/changeling/changeling_power.dm
+++ b/code/game/gamemodes/changeling/changeling_power.dm
@@ -20,6 +20,9 @@
/obj/effect/proc_holder/changeling/proc/on_purchase(mob/user)
return
+/obj/effect/proc_holder/changeling/proc/on_refund(mob/user)
+ return
+
/obj/effect/proc_holder/changeling/Click()
var/mob/user = usr
if(!user || !user.mind || !user.mind.changeling)
diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm
index 9269dc71be1..db88f244ce0 100644
--- a/code/game/gamemodes/changeling/evolution_menu.dm
+++ b/code/game/gamemodes/changeling/evolution_menu.dm
@@ -370,8 +370,10 @@ var/list/sting_paths
mind.changeling.purchasedpowers+=S
S.on_purchase(src)
- var/mob/living/carbon/C = src //only carbons have dna now, so we have to typecaste
- mind.changeling.absorbed_dna |= C.dna
+ var/mob/living/carbon/C = src //only carbons have dna now, so we have to typecaste
+ if(ishuman(C))
+ var/datum/changelingprofile/prof = mind.changeling.add_profile(C)
+ mind.changeling.first_prof = prof
return 1
/datum/changeling/proc/reset()
@@ -387,15 +389,13 @@ var/list/sting_paths
/mob/proc/remove_changeling_powers(keep_free_powers=0)
if(ishuman(src) || ismonkey(src))
if(mind && mind.changeling)
- digitalcamo = 0
mind.changeling.changeling_speak = 0
mind.changeling.reset()
for(var/obj/effect/proc_holder/changeling/p in mind.changeling.purchasedpowers)
- if(!(p.dna_cost == 0 && keep_free_powers))
- mind.changeling.purchasedpowers -= p
- if(istype(p,/obj/effect/proc_holder/changeling/augmented_eyesight))
- permanent_sight_flags -= SEE_MOBS
- sight -= SEE_MOBS
+ if(p.dna_cost == 0 && keep_free_powers)
+ continue
+ mind.changeling.purchasedpowers -= p
+ p.on_refund(src)
if(hud_used)
hud_used.lingstingdisplay.icon_state = null
hud_used.lingstingdisplay.invisibility = 101
diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm
index 2b9e7c3c9d8..2d8316edfa5 100644
--- a/code/game/gamemodes/changeling/powers/absorb.dm
+++ b/code/game/gamemodes/changeling/powers/absorb.dm
@@ -54,7 +54,7 @@
target << "You are absorbed by the changeling!"
if(!changeling.has_dna(target.dna))
- changeling.absorb_dna(target, user)
+ changeling.add_profile(target, user)
if(user.nutrition < NUTRITION_LEVEL_WELL_FED)
user.nutrition = min((user.nutrition + target.nutrition), NUTRITION_LEVEL_WELL_FED)
@@ -88,7 +88,7 @@
changeling.chem_charges += min(target.mind.changeling.chem_charges, changeling.chem_storage)
changeling.absorbedcount += (target.mind.changeling.absorbedcount)
- target.mind.changeling.absorbed_dna.len = 1
+ target.mind.changeling.stored_profiles.len = 1
target.mind.changeling.absorbedcount = 0
@@ -104,26 +104,9 @@
//Absorbs the target DNA.
-/datum/changeling/proc/absorb_dna(mob/living/carbon/T, mob/user)
- if(absorbed_dna.len)
- absorbed_dna.Cut(1,2)
- T.dna.real_name = T.real_name //Set this again, just to be sure that it's properly set.
- var/datum/dna/new_dna = new T.dna.type
- new_dna.uni_identity = T.dna.uni_identity
- new_dna.struc_enzymes = T.dna.struc_enzymes
- new_dna.real_name = T.dna.real_name
- new_dna.species = T.dna.species
- new_dna.features = T.dna.features
- new_dna.blood_type = T.dna.blood_type
- absorbedcount++
- store_dna(new_dna, user)
+//datum/changeling/proc/absorb_dna(mob/living/carbon/T, mob/user)
-/datum/changeling/proc/store_dna(datum/dna/new_dna, mob/user)
- for(var/datum/objective/escape/escape_with_identity/E in user.mind.objectives)
- if(E.target_real_name == new_dna.real_name)
- protected_dna |= new_dna
- return
- absorbed_dna |= new_dna
+//datum/changeling/proc/store_dna(datum/dna/new_dna, mob/user)
@@ -147,7 +130,7 @@
if((target.disabilities & NOCLONE) || (target.disabilities & HUSK))
user << "DNA of [target] is ruined beyond usability!"
return
- if(!check_dna_integrity(target) || !ishuman(target))
+ if(!ishuman(target))
user << "[target] is not compatible with this ability."
return
return 1
@@ -169,9 +152,8 @@
target << "[user] tightens their grip as a painful sensation invades your body."
if(!changeling.has_dna(target.dna))
- changeling.absorb_dna(target, user)
- changeling.protected_dna -= user.dna
- changeling.absorbed_dna -= user.dna
+ changeling.add_profile(target, user)
+ changeling.remove_profile(user)
var/mob/dead/observer/ghost = target.ghostize(0)
user.mind.transfer_to(target)
diff --git a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm
index fb25c4401c0..92fc36842e4 100644
--- a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm
+++ b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm
@@ -3,8 +3,8 @@
/obj/effect/proc_holder/changeling/augmented_eyesight
name = "Augmented Eyesight"
- desc = "Creates heat receptors in our eyes and dramatically increases light sensing ability."
- helptext = "Grants us night vision and thermal vision. It may be toggled on or off. We will become more vulnerable to flash-based devices while active."
+ desc = "Creates heat receptors in our eyes and dramatically increases light sensing ability, or protects your vision from flashes."
+ helptext = "Grants us thermal vision or flash protection. We will become a lot more vulnerable to flash-based devices while thermal vision is active."
chemical_cost = 0
dna_cost = 2 //Would be 1 without thermal vision
var/active = 0 //Whether or not vision is enhanced
@@ -12,19 +12,70 @@
/obj/effect/proc_holder/changeling/augmented_eyesight/sting_action(mob/living/carbon/human/user)
if(!istype(user))
return
- active = !active
- if(active)
- user << "We feel a minute twitch in our eyes, and darkness creeps away."
- user.weakeyes = 1
- user.sight |= SEE_MOBS
- user.permanent_sight_flags |= SEE_MOBS
- user.see_in_dark = 8
- user.dna.species.invis_sight = SEE_INVISIBLE_MINIMUM
+ if(user.getorgan(/obj/item/organ/internal/cyberimp/eyes/thermals/ling))
+ user << "Our eyes are protected from flashes."
+ var/obj/item/organ/internal/cyberimp/eyes/O = new /obj/item/organ/internal/cyberimp/eyes/shield/ling()
+ O.Insert(user)
+
else
- user << "Our vision dulls. Shadows gather."
- user.weakeyes = 0
- user.sight &= ~SEE_MOBS
- user.permanent_sight_flags &= ~SEE_MOBS
- user.see_in_dark = 0
- user.dna.species.invis_sight = initial(user.dna.species.invis_sight)
+ var/obj/item/organ/internal/cyberimp/eyes/O = new /obj/item/organ/internal/cyberimp/eyes/thermals/ling()
+ O.Insert(user)
+
return 1
+
+
+/obj/effect/proc_holder/changeling/augmented_eyesight/on_refund(mob/user)
+ var/obj/item/organ/internal/cyberimp/eyes/O = user.getorganslot("eye_ling")
+ O.Remove(user)
+ qdel(O)
+
+
+
+
+
+/obj/item/organ/internal/cyberimp/eyes/shield/ling
+ name = "protective membranes"
+ desc = "These variable transparency organic membranes will protect you from welders and flashes and heal your eye damage."
+ icon_state = "ling_eyeshield"
+ eye_color = null
+ implant_overlay = null
+ origin_tech = "biotech=4"
+ slot = "eye_ling"
+ status = ORGAN_ORGANIC
+
+/obj/item/organ/internal/cyberimp/eyes/shield/ling/on_life()
+ ..()
+ if(owner.eye_blind || owner.eye_stat || owner.eye_blurry || (owner.disabilities & BLIND) || (owner.disabilities & NEARSIGHT))
+ owner.reagents.add_reagent("oculine", 1)
+
+/obj/item/organ/internal/cyberimp/eyes/shield/ling/prepare_eat()
+ var/obj/S = ..()
+ S.reagents.add_reagent("oculine", 15)
+ return S
+
+
+/obj/item/organ/internal/cyberimp/eyes/thermals/ling
+ name = "heat receptors"
+ desc = "These heat receptors dramatically increases eyes light sensing ability."
+ icon_state = "ling_thermal"
+ eye_color = null
+ implant_overlay = null
+ origin_tech = "biotech=5;magnets=5"
+ slot = "eye_ling"
+ status = ORGAN_ORGANIC
+ aug_message = "You feel a minute twitch in our eyes, and darkness creeps away."
+
+/obj/item/organ/internal/cyberimp/eyes/thermals/ling/emp_act(severity)
+ return
+
+/obj/item/organ/internal/cyberimp/eyes/thermals/ling/Insert(mob/living/carbon/M, special = 0)
+ ..()
+ if(ishuman(owner))
+ var/mob/living/carbon/human/H = owner
+ H.weakeyes = 1
+
+/obj/item/organ/internal/cyberimp/eyes/thermals/ling/Remove(mob/living/carbon/M, special = 0)
+ if(ishuman(owner))
+ var/mob/living/carbon/human/H = owner
+ H.weakeyes = 0
+ ..()
\ No newline at end of file
diff --git a/code/game/gamemodes/changeling/powers/biodegrade.dm b/code/game/gamemodes/changeling/powers/biodegrade.dm
new file mode 100644
index 00000000000..f831655d2c8
--- /dev/null
+++ b/code/game/gamemodes/changeling/powers/biodegrade.dm
@@ -0,0 +1,61 @@
+/obj/effect/proc_holder/changeling/biodegrade
+ name = "Biodegrade"
+ desc = "Dissolves restraints or other objects preventing free movement."
+ helptext = "This is obvious to nearby people, and can destroy standard restraints and closets."
+ chemical_cost = 30 //High cost to prevent spam
+ dna_cost = 1
+ req_human = 1
+
+
+/obj/effect/proc_holder/changeling/biodegrade/sting_action(mob/living/carbon/human/user)
+ var/used = 0
+ if(!user.restrained() && !istype(user.loc, /obj/structure/closet))
+ user << "We are already free!"
+ return 0
+
+ if(user.handcuffed)
+ used = 1
+ var/obj/O = user.get_item_by_slot(slot_handcuffed)
+ if(!O || !istype(O))
+ return 0
+ user.visible_message("[user] vomits a glob of acid on \his [O]!", \
+ "We vomit acidic ooze onto our restraints!")
+ spawn(30)
+ if(O && user.handcuffed == O)
+ user.unEquip(O)
+ O.visible_message("[O] dissolves into a puddle of sizzling goop.")
+ O.loc = get_turf(user)
+ qdel(O)
+
+ if(istype(user.wear_suit, /obj/item/clothing/suit/straight_jacket) && !used)
+ used = 1
+ var/obj/item/clothing/suit/straight_jacket/SJ = user.get_item_by_slot(slot_wear_suit)
+ if(!SJ || !istype(SJ))
+ return 0
+ user.visible_message("[user] vomits a glob of acid across the front of \his [SJ]!", \
+ "We vomit acidic ooze onto our straight jacket!")
+ spawn(30)
+ if(SJ && user.wear_suit == SJ)
+ user.unEquip(SJ)
+ SJ.visible_message("[SJ] dissolves into a puddle of sizzling goop.")
+ SJ.loc = get_turf(user)
+ qdel(SJ)
+
+ if(istype(user.loc, /obj/structure/closet) && !used)
+ used = 1
+ var/obj/structure/closet/C = user.loc
+ if(!C || !istype(C)) //The !C check slightly scares me, but...
+ return 0
+ C.visible_message("[C]'s hinges suddenly begin to melt and run!")
+ user << "We vomit acidic goop onto the interior of [C]!"
+ spawn(70)
+ if(C && user.loc == C)
+ C.visible_message("[C]'s door breaks and opens!")
+ C.welded = 0
+ C.locked = 0
+ C.broken = 1
+ C.open()
+ user << "We open the container restraining us!"
+
+ feedback_add_details("changeling_powers","BD")
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/chameleon_skin.dm b/code/game/gamemodes/changeling/powers/chameleon_skin.dm
new file mode 100644
index 00000000000..f39505fa712
--- /dev/null
+++ b/code/game/gamemodes/changeling/powers/chameleon_skin.dm
@@ -0,0 +1,30 @@
+/obj/effect/proc_holder/changeling/chameleon_skin
+ name = "Chameleon Skin"
+ desc = "Our skin pigmentation rapidly changes to suit our current environment."
+ helptext = "Allows us to become invisible after a few seconds of standing still. Can be toggled on and off."
+ dna_cost = 2
+ chemical_cost = 25
+ req_human = 1
+ genetic_damage = 10
+ max_genetic_damage = 50
+
+
+/obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user)
+ var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1 //phil235 so why is it needd?
+ if(!istype(H)) // req_human could be done in can_sting stuff.
+ return
+ var/datum/mutation/human/HM = mutations_list[CHAMELEON]
+ if(HM in H.dna.mutations)
+ HM.force_lose(H)
+ else
+ HM.force_give(H)
+
+ feedback_add_details("changeling_powers","CS")
+ return 1
+
+/obj/effect/proc_holder/changeling/chameleon_skin/on_refund(mob/user)
+ if(user.has_dna())
+ var/mob/living/carbon/C = user
+ var/datum/mutation/human/HM = mutations_list[CHAMELEON]
+ if(HM in C.dna.mutations)
+ HM.force_lose(C)
\ No newline at end of file
diff --git a/code/game/gamemodes/changeling/powers/digitalcamo.dm b/code/game/gamemodes/changeling/powers/digitalcamo.dm
index 2404041ae17..79651c98a97 100644
--- a/code/game/gamemodes/changeling/powers/digitalcamo.dm
+++ b/code/game/gamemodes/changeling/powers/digitalcamo.dm
@@ -1,7 +1,7 @@
/obj/effect/proc_holder/changeling/digitalcamo
name = "Digital Camouflage"
desc = "By evolving the ability to distort our form and proprotions, we defeat common altgorithms used to detect lifeforms on cameras."
- helptext = "We cannot be tracked by camera while using this skill. However, humans looking at us will find us... uncanny."
+ helptext = "We cannot be tracked by camera or seen by AI units while using this skill. However, humans looking at us will find us... uncanny."
dna_cost = 1
//Prevents AIs tracking you but makes you easily detectable to the human-eye.
@@ -9,9 +9,16 @@
if(user.digitalcamo)
user << "We return to normal."
+ user.digitalinvis = 0
else
- user << "We distort our form to prevent AI-tracking."
- user.digitalcamo = !user.digitalcamo
+ user << "We distort our form to hide from the AI"
+ user.digitalcamo = 1
+ user.digitalinvis = !user.digitalcamo
+
feedback_add_details("changeling_powers","CAM")
return 1
+
+/obj/effect/proc_holder/changeling/digitalcamo/on_refund(mob/user)
+ user.digitalcamo = 0
+ user.digitalinvis = 0
\ No newline at end of file
diff --git a/code/game/gamemodes/changeling/powers/fleshmend.dm b/code/game/gamemodes/changeling/powers/fleshmend.dm
index dcc28941ed0..c581d3fb35e 100644
--- a/code/game/gamemodes/changeling/powers/fleshmend.dm
+++ b/code/game/gamemodes/changeling/powers/fleshmend.dm
@@ -1,25 +1,41 @@
/obj/effect/proc_holder/changeling/fleshmend
name = "Fleshmend"
- desc = "Our flesh rapidly regenerates, healing our wounds."
- helptext = "Heals a moderate amount of damage over a short period of time. Can be used while unconscious."
+ desc = "Our flesh rapidly regenerates, healing our wounds. Effectiveness decreases with quick, repeated use."
+ helptext = "Heals a moderate amount of damage over a short period of time. Can be used while unconscious, and will alert nearby crew."
chemical_cost = 25
dna_cost = 2
req_stat = UNCONSCIOUS
+ var/recent_uses = 1 //The factor of which the healing should be divided by
+
+/obj/effect/proc_holder/changeling/fleshmend/New()
+ ..()
+ SSobj.processing.Add(src)
+
+/obj/effect/proc_holder/changeling/fleshmend/Destroy()
+ SSobj.processing.Remove(src)
+ ..()
+
+/obj/effect/proc_holder/changeling/fleshmend/process()
+ if(recent_uses > 1)
+ recent_uses--
//Starts healing you every second for 10 seconds. Can be used whilst unconscious.
/obj/effect/proc_holder/changeling/fleshmend/sting_action(mob/living/user)
user << "We begin to heal rapidly."
+ if(recent_uses > 1)
+ user << "Our healing's effectiveness is reduced by quickly repeated use!"
spawn(0)
+ recent_uses++
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.restore_blood()
H.remove_all_embedded_objects()
- for(var/i = 0, i<10,i++)
- user.adjustBruteLoss(-10)
- user.adjustOxyLoss(-10)
- user.adjustFireLoss(-10)
+ for(var/i = 0, i < 10, i++) //The healing itself - doesn't heal toxin damage (that's anatomic panacea) and effectiveness decreases with each use in a short timespan
+ user.adjustBruteLoss(-10 / recent_uses)
+ user.adjustOxyLoss(-10 / recent_uses)
+ user.adjustFireLoss(-10 / recent_uses)
sleep(10)
feedback_add_details("changeling_powers","RR")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/headcrab.dm b/code/game/gamemodes/changeling/powers/headcrab.dm
index 4440e9b63d9..71ffc3480ba 100644
--- a/code/game/gamemodes/changeling/powers/headcrab.dm
+++ b/code/game/gamemodes/changeling/powers/headcrab.dm
@@ -1,6 +1,7 @@
/obj/effect/proc_holder/changeling/headcrab
name = "Last Resort"
- desc = "We sacrifice our current body in a moment of need, stunning and damaging everyone nearby. If a dead body is nearby we infect it to raise again."
+ desc = "We sacrifice our current body in a moment of need, placing us in control of a vessel."
+ helptext = "We will be placed in control of a small, fragile creature. We may attack a corpse like this to plant an egg which will slowly mature into a new form for us."
chemical_cost = 20
dna_cost = 1
req_human = 1
@@ -13,14 +14,24 @@
I.Remove(user, 1)
explosion(get_turf(user),0,0,2,0,silent=1)
+ for(var/mob/living/carbon/human/H in range(2,user))
+ H << "You are blinded by a shower of blood!"
+ H.Stun(1)
+ H.eye_blurry = 20
+ H.eye_stat += 5
+ H.confused += 3
+ for(var/mob/living/silicon/S in range(2,user))
+ S << "Your sensors are disabled by a shower of blood!"
+ S.Weaken(3)
var/turf = get_turf(user)
spawn(5) // So it's not killed in explosion
var/mob/living/simple_animal/hostile/headcrab/crab = new(turf)
for(var/obj/item/organ/internal/I in organs)
I.loc = crab
crab.origin = M
- if(M)
- M.transfer_to(crab)
+ if(crab.origin)
+ crab.origin.active = 1
+ crab.origin.transfer_to(crab)
crab << "You burst out of the remains of your former body in a shower of gore!"
user.gib()
feedback_add_details("changeling_powers","LR")
diff --git a/code/game/gamemodes/changeling/powers/hivemind.dm b/code/game/gamemodes/changeling/powers/hivemind.dm
index 69a795ad9c4..74bee7886f1 100644
--- a/code/game/gamemodes/changeling/powers/hivemind.dm
+++ b/code/game/gamemodes/changeling/powers/hivemind.dm
@@ -31,9 +31,9 @@ var/list/datum/dna/hivemind_bank = list()
/obj/effect/proc_holder/changeling/hivemind_upload/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling
var/list/names = list()
- for(var/datum/dna/DNA in (changeling.absorbed_dna+changeling.protected_dna))
- if(!(DNA in hivemind_bank))
- names += DNA.real_name
+ for(var/datum/changelingprofile/prof in changeling.stored_profiles)
+ if(!(prof in hivemind_bank))
+ names += prof.name
if(names.len <= 0)
user << "The airwaves already have all of our DNA."
@@ -43,7 +43,7 @@ var/list/datum/dna/hivemind_bank = list()
if(!chosen_name)
return
- var/datum/dna/chosen_dna = changeling.get_dna(chosen_name)
+ var/datum/changelingprofile/chosen_dna = changeling.get_dna(chosen_name)
if(!chosen_dna)
return
@@ -62,7 +62,8 @@ var/list/datum/dna/hivemind_bank = list()
if(!..())
return
var/datum/changeling/changeling = user.mind.changeling
- if(changeling.absorbed_dna[1] == user.dna)//If our current DNA is the stalest, we gotta ditch it.
+ var/datum/changelingprofile/first_prof = changeling.stored_profiles[1]
+ if(first_prof.name == user.real_name)//If our current DNA is the stalest, we gotta ditch it.
user << "We have reached our capacity to store genetic information! We must transform before absorbing more."
return
return 1
@@ -70,9 +71,9 @@ var/list/datum/dna/hivemind_bank = list()
/obj/effect/proc_holder/changeling/hivemind_download/sting_action(mob/user)
var/datum/changeling/changeling = user.mind.changeling
var/list/names = list()
- for(var/datum/dna/DNA in hivemind_bank)
- if(!(DNA in changeling.absorbed_dna))
- names[DNA.real_name] = DNA
+ for(var/datum/changelingprofile/prof in hivemind_bank)
+ if(!(prof in changeling.stored_profiles))
+ names[prof.name] = prof
if(names.len <= 0)
user << "There's no new DNA to absorb from the air."
@@ -80,13 +81,11 @@ var/list/datum/dna/hivemind_bank = list()
var/S = input("Select a DNA absorb from the air: ", "Absorb DNA", null) as null|anything in names
if(!S) return
- var/datum/dna/chosen_dna = names[S]
- if(!chosen_dna)
+ var/datum/changelingprofile/chosen_prof = names[S]
+ if(!chosen_prof)
return
- if(changeling.absorbed_dna.len)
- changeling.absorbed_dna.Cut(1,2)
- changeling.store_dna(chosen_dna, user)
+ changeling.add_profile(chosen_prof, user)
user << "We absorb the DNA of [S] from the air."
feedback_add_details("changeling_powers","HD")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm
index 3d8916e6b66..5fde1238159 100644
--- a/code/game/gamemodes/changeling/powers/humanform.dm
+++ b/code/game/gamemodes/changeling/powers/humanform.dm
@@ -11,25 +11,24 @@
/obj/effect/proc_holder/changeling/humanform/sting_action(mob/living/carbon/user)
var/datum/changeling/changeling = user.mind.changeling
var/list/names = list()
- for(var/datum/dna/DNA in (changeling.absorbed_dna+changeling.protected_dna))
- names += "[DNA.real_name]"
+ for(var/datum/changelingprofile/prof in changeling.stored_profiles)
+ names += "[prof.name]"
var/chosen_name = input("Select the target DNA: ", "Target DNA", null) as null|anything in names
if(!chosen_name)
return
- var/datum/dna/chosen_dna = changeling.get_dna(chosen_name)
- if(!chosen_dna)
+ var/datum/changelingprofile/chosen_prof = changeling.get_dna(chosen_name)
+ if(!chosen_prof)
return
if(!user || user.notransform)
return 0
user << "We transform our appearance."
- user.dna = chosen_dna
-
- user.humanize((TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPSRC),chosen_dna.real_name)
changeling.purchasedpowers -= src
- feedback_add_details("changeling_powers","LFT")
- qdel(user)
- return 1
+ var/newmob = user.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS)
+
+ changeling_transform(newmob, chosen_prof)
+ feedback_add_details("changeling_powers","LFT")
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/lesserform.dm b/code/game/gamemodes/changeling/powers/lesserform.dm
index 2ce8470c19c..05406b02bdf 100644
--- a/code/game/gamemodes/changeling/powers/lesserform.dm
+++ b/code/game/gamemodes/changeling/powers/lesserform.dm
@@ -12,9 +12,7 @@
return 0
user << "Our genes cry out!"
- user.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPSE | TR_KEEPSRC)
+ user.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
- // Human-form power now handled in monkeyize()
feedback_add_details("changeling_powers","LF")
- .=1
- qdel(user)
\ No newline at end of file
+ return 1
\ No newline at end of file
diff --git a/code/game/gamemodes/changeling/powers/mimic_voice.dm b/code/game/gamemodes/changeling/powers/mimic_voice.dm
index d33532015ad..c3483983b67 100644
--- a/code/game/gamemodes/changeling/powers/mimic_voice.dm
+++ b/code/game/gamemodes/changeling/powers/mimic_voice.dm
@@ -22,7 +22,7 @@
changeling.mimicing = mimic_voice
changeling.chem_recharge_slowdown += 0.5
- user << "We shape our glands to take the voice of [mimic_voice], this will stop us from regenerating chemicals while active."
- user << "Use this power again to return to our original voice and reproduce chemicals again."
+ user << "We shape our glands to take the voice of [mimic_voice], this will slow down regenerating chemicals while active."
+ user << "Use this power again to return to our original voice and return chemical production to normal levels."
feedback_add_details("changeling_powers","MV")
diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm
index ca3ba2594de..2392376bf09 100644
--- a/code/game/gamemodes/changeling/powers/mutations.dm
+++ b/code/game/gamemodes/changeling/powers/mutations.dm
@@ -21,20 +21,23 @@
var/weapon_name_simple
/obj/effect/proc_holder/changeling/weapon/try_to_sting(mob/user, mob/target)
- if(istype(user.l_hand, weapon_type)) //Not the nicest way to do it, but eh
- playsound(user, 'sound/effects/blobattack.ogg', 30, 1)
- qdel(user.l_hand)
- user.visible_message("With a sickening crunch, [user] reforms their [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "With a sickening crunch, [user] reforms their [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "With a sickening crunch, [user] reforms their [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "The [user.get_active_hand()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!"
@@ -44,6 +47,10 @@
playsound(user, 'sound/effects/blobattack.ogg', 30, 1)
return W
+/obj/effect/proc_holder/changeling/weapon/on_refund(mob/user)
+ check_weapon(user, user.r_hand, 1)
+ check_weapon(user, user.l_hand, 0)
+
//Parent to space suits and armor.
/obj/effect/proc_holder/changeling/suit
name = "Organic Suit"
@@ -61,10 +68,16 @@
var/blood_on_castoff = 0
/obj/effect/proc_holder/changeling/suit/try_to_sting(mob/user, mob/target)
+ if(check_suit(user))
+ return
+ var/mob/living/carbon/human/H = user
+ ..(H, target)
+
+//checks if we already have an organic suit and casts it off.
+/obj/effect/proc_holder/changeling/suit/proc/check_suit(mob/user)
var/datum/changeling/changeling = user.mind.changeling
if(!ishuman(user) || !changeling)
- return
-
+ return 1
var/mob/living/carbon/human/H = user
if(istype(H.wear_suit, suit_type) || istype(H.head, helmet_type))
H.visible_message("[H] casts off their [suit_name_simple]!", "We cast off our [suit_name_simple][genetic_damage > 0 ? ", temporarily weakening our genomes." : "."]", "You hear the organic matter ripping and tearing!")
@@ -82,8 +95,13 @@
changeling.geneticdamage += genetic_damage //Casting off a space suit leaves you weak for a few seconds.
changeling.chem_recharge_slowdown -= recharge_slowdown
+ return 1
+
+/obj/effect/proc_holder/changeling/suit/on_refund(mob/user)
+ if(!ishuman(user))
return
- ..(H, target)
+ var/mob/living/carbon/human/H = user
+ check_suit(H)
/obj/effect/proc_holder/changeling/suit/sting_action(mob/living/carbon/human/user)
if(!user.canUnEquip(user.wear_suit))
@@ -159,7 +177,12 @@
return
if(A.hasPower())
- user << "The airlock's motors resist our efforts to force it!"
+ if(A.locked)
+ user << "The airlock's bolts prevent it from being forced!"
+ return
+ user << "The airlock's motors are resisting, this may take time..."
+ if(do_after(user, 100, target = A))
+ A.open(2)
return
else if(A.locked)
@@ -289,16 +312,16 @@
desc = "We turn our skin into tough chitin to protect us from damage."
helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Retreating the armor damages our genomes. Cannot be used in lesser form."
chemical_cost = 20
- dna_cost = 2
+ dna_cost = 1
genetic_damage = 11
req_human = 1
max_genetic_damage = 20
+ recharge_slowdown = 0.25
suit_type = /obj/item/clothing/suit/armor/changeling
helmet_type = /obj/item/clothing/head/helmet/changeling
suit_name_simple = "armor"
helmet_name_simple = "helmet"
- recharge_slowdown = 0.25
/obj/item/clothing/suit/armor/changeling
name = "chitinous mass"
@@ -306,7 +329,7 @@
icon_state = "lingarmor"
flags = NODROP
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- armor = list(melee = 40, bullet = 20, laser = 30, energy = 13, bomb = 0, bio = 0, rad = 0)
+ armor = list(melee = 40, bullet = 40, laser = 40, energy = 20, bomb = 10, bio = 4, rad = 0)
flags_inv = HIDEJUMPSUIT
cold_protection = 0
heat_protection = 0
@@ -324,7 +347,7 @@
desc = "A tough, hard covering of black chitin with transparent chitin in front."
icon_state = "lingarmorhelmet"
flags = BLOCKHAIR | NODROP
- armor = list(melee = 40, bullet = 15, laser = 30,energy = 10, bomb = 5, bio = 2, rad = 0)
+ armor = list(melee = 30, bullet = 30, laser = 40, energy = 20, bomb = 10, bio = 4, rad = 0)
flags_inv = HIDEEARS
flags_cover = HEADCOVERSEYES
diff --git a/code/game/gamemodes/changeling/powers/panacea.dm b/code/game/gamemodes/changeling/powers/panacea.dm
index b6880a371e7..9d4bb4ff2b8 100644
--- a/code/game/gamemodes/changeling/powers/panacea.dm
+++ b/code/game/gamemodes/changeling/powers/panacea.dm
@@ -1,6 +1,6 @@
/obj/effect/proc_holder/changeling/panacea
name = "Anatomic Panacea"
- desc = "Expels impurifications from our form; curing diseases, removing toxins and radiation, and resetting our genetic code completely."
+ desc = "Expels impurifications from our form; curing diseases, removing parasites, toxins and radiation, and resetting our genetic code completely."
helptext = "Can be used while unconscious."
chemical_cost = 20
dna_cost = 1
@@ -8,14 +8,24 @@
//Heals the things that the other regenerative abilities don't.
/obj/effect/proc_holder/changeling/panacea/sting_action(mob/user)
+ user << "We begin cleansing impurities from our form."
+
+ var/obj/item/organ/internal/body_egg/egg = user.getorgan(/obj/item/organ/internal/body_egg)
+ if(egg)
+ egg.Remove(user)
+ user.visible_message("[user] vomits up [egg]!", "[user] vomits up [egg]!")
+ playsound(user.loc, 'sound/effects/splat.ogg', 50, 1)
+
+ var/turf/location = user.loc
+ if(istype(location, /turf/simulated))
+ location.add_vomit_floor(user, 1)
+ egg.loc = location
- user << "We cleanse impurities from our form."
user.reagents.add_reagent("mutadone", 10)
user.reagents.add_reagent("potass_iodide", 10)
user.reagents.add_reagent("charcoal", 20)
for(var/datum/disease/D in user.viruses)
D.cure()
-
feedback_add_details("changeling_powers","AP")
return 1
\ No newline at end of file
diff --git a/code/game/gamemodes/changeling/powers/shriek.dm b/code/game/gamemodes/changeling/powers/shriek.dm
index 92d6c84daee..e9e28c37a4d 100644
--- a/code/game/gamemodes/changeling/powers/shriek.dm
+++ b/code/game/gamemodes/changeling/powers/shriek.dm
@@ -12,7 +12,7 @@
if(iscarbon(M))
if(!M.mind || !M.mind.changeling)
M.adjustEarDamage(0,30)
- M.confused += 20
+ M.confused += 25
M.Jitter(50)
else
M << sound('sound/effects/screech.ogg')
diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm
index 576a4102baa..24fbc8ec07d 100644
--- a/code/game/gamemodes/changeling/powers/tiny_prick.dm
+++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm
@@ -65,7 +65,7 @@
chemical_cost = 40
dna_cost = 3
genetic_damage = 100
- var/datum/dna/selected_dna = null
+ var/datum/changelingprofile/selected_dna = null
/obj/effect/proc_holder/changeling/sting/transformation/Click()
var/mob/user = usr
@@ -81,26 +81,29 @@
/obj/effect/proc_holder/changeling/sting/transformation/can_sting(mob/user, mob/target)
if(!..())
return
- if((target.disabilities & HUSK) || !check_dna_integrity(target))
+ if((target.disabilities & HUSK) || !target.has_dna())
user << "Our sting appears ineffective against its DNA."
return 0
return 1
/obj/effect/proc_holder/changeling/sting/transformation/sting_action(mob/user, mob/target)
- add_logs(user, target, "stung", "transformation sting", " new identity is [selected_dna.real_name]")
- var/datum/dna/NewDNA = selected_dna
+ add_logs(user, target, "stung", "transformation sting", " new identity is [selected_dna.dna.real_name]")
+ var/datum/dna/NewDNA = selected_dna.dna
if(ismonkey(target))
user << "Our genes cry out as we sting [target.name]!"
- if(iscarbon(target) && (target.status_flags & CANWEAKEN))
+ if(iscarbon(target))
var/mob/living/carbon/C = target
- C.do_jitter_animation(500)
- C.take_organ_damage(20, 0) //The process is extremely painful
+ if(C.status_flags & CANWEAKEN)
+ C.do_jitter_animation(500)
+ C.take_organ_damage(20, 0) //The process is extremely painful
- target.visible_message("[target] begins to violenty convulse!","You feel a tiny prick and a begin to uncontrollably convulse!")
- spawn(10)
- hardset_dna(target, NewDNA.uni_identity, NewDNA.struc_enzymes, NewDNA.real_name, NewDNA.blood_type, NewDNA.species.type, NewDNA.features)
- updateappearance(target)
+ target.visible_message("[target] begins to violenty convulse!","You feel a tiny prick and a begin to uncontrollably convulse!")
+ spawn(10)
+ user.real_name = NewDNA.real_name
+ NewDNA.transfer_identity(C, transfer_SE=1)
+ C.updateappearance(mutcolor_update=1)
+ C.domutcheck()
feedback_add_details("changeling_powers","TS")
return 1
@@ -125,7 +128,7 @@
/obj/effect/proc_holder/changeling/sting/false_armblade/can_sting(mob/user, mob/target)
if(!..())
return
- if((target.disabilities & HUSK) || !check_dna_integrity(target))
+ if((target.disabilities & HUSK) || !target.has_dna())
user << "Our sting appears ineffective against its DNA."
return 0
return 1
@@ -171,7 +174,7 @@
/obj/effect/proc_holder/changeling/sting/extract_dna/sting_action(mob/user, mob/living/carbon/human/target)
add_logs(user, target, "stung", "extraction sting")
if(!(user.mind.changeling.has_dna(target.dna)))
- user.mind.changeling.absorb_dna(target, user)
+ user.mind.changeling.add_profile(target, user)
feedback_add_details("changeling_powers","ED")
return 1
diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm
index 105c92c570c..87db3fe28d1 100644
--- a/code/game/gamemodes/changeling/powers/transform.dm
+++ b/code/game/gamemodes/changeling/powers/transform.dm
@@ -7,30 +7,66 @@
req_human = 1
max_genetic_damage = 3
+/obj/item/clothing/glasses/changeling
+ name = "flesh"
+ flags = NODROP
+
+/obj/item/clothing/under/changeling
+ name = "flesh"
+ flags = NODROP
+
+/obj/item/clothing/suit/changeling
+ name = "flesh"
+ flags = NODROP
+ allowed = list(/obj/item/changeling)
+
+/obj/item/clothing/head/changeling
+ name = "flesh"
+ flags = NODROP
+/obj/item/clothing/shoes/changeling
+ name = "flesh"
+ flags = NODROP
+
+/obj/item/clothing/gloves/changeling
+ name = "flesh"
+ flags = NODROP
+
+/obj/item/clothing/mask/changeling
+ name = "flesh"
+ flags = NODROP
+
+/obj/item/changeling
+ name = "flesh"
+ flags = NODROP
+ slot_flags = ALL
+ allowed = list(/obj/item/changeling)
+
//Change our DNA to that of somebody we've absorbed.
/obj/effect/proc_holder/changeling/transform/sting_action(mob/living/carbon/human/user)
var/datum/changeling/changeling = user.mind.changeling
- var/datum/dna/chosen_dna = changeling.select_dna("Select the target DNA: ", "Target DNA")
+ var/datum/changelingprofile/chosen_prof = changeling.select_dna("Select the target DNA: ", "Target DNA", user)
- if(!chosen_dna)
+ if(!chosen_prof)
return
- user.dna = chosen_dna
- user.real_name = chosen_dna.real_name
- hardset_dna(user, null, null, null, null, chosen_dna.species.type, chosen_dna.features)
- updateappearance(user)
- domutcheck(user)
+ changeling_transform(user, chosen_prof)
feedback_add_details("changeling_powers","TR")
return 1
-/datum/changeling/proc/select_dna(var/prompt, var/title)
- var/list/names = list()
- for(var/datum/dna/DNA in (absorbed_dna+protected_dna))
- names += "[DNA.real_name]"
+/datum/changeling/proc/select_dna(var/prompt, var/title, var/mob/living/carbon/user)
+ var/list/names = list("Drop Flesh Disguise")
+ for(var/datum/changelingprofile/prof in stored_profiles)
+ names += "[prof.name]"
var/chosen_name = input(prompt, title, null) as null|anything in names
if(!chosen_name)
return
- var/datum/dna/chosen_dna = get_dna(chosen_name)
- return chosen_dna
\ No newline at end of file
+
+ if(chosen_name == "Drop Flesh Disguise")
+ for(var/slot in slots)
+ if(istype(user.vars[slot], slot2type[slot]))
+ qdel(user.vars[slot])
+
+ var/datum/changelingprofile/prof = get_dna(chosen_name)
+ return prof
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 50fac253f91..eb56a644fb6 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -2,21 +2,26 @@
/datum/game_mode
var/list/datum/mind/cult = list()
- var/list/allwords = list("travel","self","see","hell","blood","join","tech","destroy", "other", "hide")
- var/list/grantwords = list("travel", "see", "hell", "tech", "destroy", "other", "hide")
var/list/cult_objectives = list()
/proc/iscultist(mob/living/M)
return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.cult)
+/proc/is_sacrifice_target(datum/mind/mind)
+ if(ticker.mode.name == "cult")
+ var/datum/game_mode/cult/cult_mode = ticker.mode
+ if(mind == cult_mode.sacrifice_target)
+ return 1
+ return 0
+
/proc/is_convertable_to_cult(datum/mind/mind)
if(!istype(mind)) return 0
if(istype(mind.current, /mob/living/carbon/human) && (mind.assigned_role in list("Captain", "Chaplain"))) return 0
if(isloyal(mind.current))
return 0
if (ticker.mode.name == "cult") //redundent?
- if(mind.current == ticker.mode.sacrifice_target) return 0
+ if(is_sacrifice_target(mind)) return 0
return 1
/proc/cultist_commune(mob/living/user, clear = 0, say = 0, message)
@@ -27,6 +32,8 @@
else
user.whisper("O bidai nabora se[pick("'","`")]sma!")
sleep(10)
+ if(!user)
+ return
if(say)
user.say(message)
else
@@ -54,14 +61,13 @@
var/finished = 0
- var/list/startwords = list("blood","join","self","hell")
- var/list/secondwords = list("travel", "see", "tech", "destroy", "other", "hide")
-
var/eldergod = 1 //for the summon god objective
var/acolytes_needed = 10 //for the survive objective
var/acolytes_survived = 0
+ var/datum/mind/sacrifice_target = null//The target to be sacrificed
+
/datum/game_mode/cult/announce()
world << "The current game mode is - Cult!"
@@ -86,6 +92,8 @@
if(config.protect_assistant_from_antagonist)
restricted_jobs += "Assistant"
+ acolytes_needed = round(num_players()/5,1) //Scales the escape requirement with the amount of people in the round; for every 5 players, one cultist added to the count, i.e. 25 players = 5 to escape
+ acolytes_needed = Clamp(acolytes_needed, 1, 15) //Max at 15 and minimum at 1 - before the update, people rarely got even 15
for(var/cultists_number = 1 to recommended_enemies)
if(!antag_candidates.len)
@@ -120,10 +128,8 @@
for(var/datum/mind/cult_mind in cult)
equip_cultist(cult_mind.current)
-// grant_runeword(cult_mind.current)
-// grant_secondword(cult_mind.current)
update_cult_icons_added(cult_mind)
- cult_mind.current << "You are a member of the cult!"
+ cult_mind.current << "You are a member of the cult!"
memorize_cult_objectives(cult_mind)
..()
@@ -136,24 +142,18 @@
explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station."
if("sacrifice")
if(sacrifice_target)
- explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune (Hell blood join) and three acolytes to do so."
+ explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. You will need the Sacrifice rune and three acolytes to do so."
else
explanation = "Free objective."
if("eldergod")
- explanation = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it."
+ explanation = "Summon Nar-Sie via the rune 'Call Forth The Geometer'. It will only work if nine acolytes stand on and around it."
cult_mind.current << "Objective #[obj_count]: [explanation]"
cult_mind.memory += "Objective #[obj_count]: [explanation] "
- cult_mind.current << "The Geometer of Blood grants you the knowledge to sacrifice non-believers. (Hell Blood Join)"
- cult_mind.memory += "The Geometer of Blood grants you the knowledge to sacrifice non-believers. (Hell Blood Join) "
- for(var/startingword in startwords)
- grant_runeword(cult_mind.current,startingword)
-// grant_runeword(cult_mind.current,"blood")
-// grant_runeword(cult_mind.current,"hell")
/datum/game_mode/proc/equip_cultist(mob/living/carbon/human/mob)
if(!istype(mob))
return
-
+ mob.cult_add_comm()
if (mob.mind)
if (mob.mind.assigned_role == "Clown")
mob << "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself."
@@ -169,10 +169,10 @@
"right hand" = slot_r_hand,
)
var/where = mob.equip_in_one_of_slots(T, slots)
- if (!where)
+ if(!where)
mob << "Unfortunately, you weren't able to get a talisman. This is very bad and you should adminhelp immediately."
else
- mob << "You have a talisman in your [where], one that will help you start the cult on this station. Use it well and remember - there are others."
+ mob << "You have a talisman in your [where], one that will help you start the cult on this station. Use it well, and remember - you are not the only one."
mob.update_icons()
if(where == "backpack")
var/obj/item/weapon/storage/B = mob.back
@@ -181,58 +181,6 @@
return 1
-//datum/game_mode/cult/proc/grant_secondword(mob/living/carbon/human/cult_mob, var/word)
-// if (!word)
-// if(secondwords.len > 0)
-// word=pick(secondwords)
-// secondwords -= word
-// grant_runeword(cult_mob,word)
-
-//datum/game_mode/cult/grant_runeword(mob/living/carbon/human/cult_mob, var/word)
-// if (!word)
-// if(startwords.len > 0)
-// word=pick(startwords)
-// startwords -= word
-// return ..(cult_mob,word)
-
-/datum/game_mode/proc/grant_runeword(mob/living/carbon/human/cult_mob, word)
- if(!wordtravel)
- runerandom()
- if (!word)
- word=pick(grantwords)
- var/wordexp
- switch(word)
- if("travel")
- wordexp = "[wordtravel] is travel..."
- if("blood")
- wordexp = "[wordblood] is blood..."
- if("join")
- wordexp = "[wordjoin] is join..."
- if("hell")
- wordexp = "[wordhell] is Hell..."
- if("self")
- wordexp = "[wordself] is self..."
- if("see")
- wordexp = "[wordsee] is see..."
- if("tech")
- wordexp = "[wordtech] is technology..."
- if("destroy")
- wordexp = "[worddestr] is destroy..."
- if("other")
- wordexp = "[wordother] is other..."
-// if("hear")
-// wordexp = "[wordhear] is hear..."
-// if("free")
-// wordexp = "[wordfree] is free..."
- if("hide")
- wordexp = "[wordhide] is hide..."
- cult_mob << "[pick("You remember something from the dark teachings of your master","You hear a dark voice on the wind","Black blood oozes into your vision and forms into symbols","You catch a brief glimmer of the otherside")]... [wordexp]"
- cult_mob.mind.store_memory("You remember that [wordexp]", 0, 0)
- cult_mob.mind.cult_words += word
- if(cult_mob.mind.cult_words.len == allwords.len)
- cult_mob << "\green You feel enlightened, as if you have gained all the secrets of the other side."
-
-
/datum/game_mode/proc/add_cultist(datum/mind/cult_mind) //BASE
if (!istype(cult_mind))
return 0
@@ -256,14 +204,13 @@
cult -= cult_mind
cult_mind.current.verbs -= /mob/living/proc/cult_innate_comm
cult_mind.current.Paralyse(5)
- cult_mind.current << "An unfamiliar white light flashes through your mind, cleansing the taint of the dark-one and the memories of your time as his servant with it."
+ cult_mind.current << "An unfamiliar white light flashes through your mind, cleansing the taint of the Dark One and all your memories as its servant."
cult_mind.memory = ""
- cult_mind.cult_words = initial(cult_mind.cult_words)
update_cult_icons_removed(cult_mind)
cult_mind.current.attack_log += "\[[time_stamp()]\] Has renounced the cult!"
if(show_message)
for(var/mob/M in viewers(cult_mind.current))
- M << "[cult_mind.current] looks like they just reverted to their old faith!"
+ M << "[cult_mind.current] looks like they just reverted to their old faith!"
/datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind)
var/datum/atom_hud/antag/culthud = huds[ANTAG_HUD_CULT]
@@ -313,11 +260,11 @@
if(!check_cult_victory())
feedback_set_details("round_end_result","win - cult win")
feedback_set("round_end_result",acolytes_survived)
- world << "The cult wins! It has succeeded in serving its dark masters!"
+ world << "The cult wins! It has succeeded in serving its dark master!"
else
feedback_set_details("round_end_result","loss - staff stopped the cult")
feedback_set("round_end_result",acolytes_survived)
- world << "The staff managed to stop the cult!"
+ world << "The staff managed to stop the cult!"
var/text = ""
@@ -328,28 +275,28 @@
switch(cult_objectives[obj_count])
if("survive")
if(!check_survive())
- explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Success!"
+ explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Success!"
feedback_add_details("cult_objective","cult_survive|SUCCESS|[acolytes_needed]")
else
- explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Fail."
+ explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Fail."
feedback_add_details("cult_objective","cult_survive|FAIL|[acolytes_needed]")
if("sacrifice")
if(sacrifice_target)
if(sacrifice_target in sacrificed)
- explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Success!"
+ explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Success!"
feedback_add_details("cult_objective","cult_sacrifice|SUCCESS")
else if(sacrifice_target && sacrifice_target.current)
- explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail."
+ explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail."
feedback_add_details("cult_objective","cult_sacrifice|FAIL")
else
- explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail (Gibbed)."
+ explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail (Gibbed)."
feedback_add_details("cult_objective","cult_sacrifice|FAIL|GIBBED")
if("eldergod")
if(!eldergod)
- explanation = "Summon Nar-Sie. Success!"
+ explanation = "Summon Nar-Sie. Success!"
feedback_add_details("cult_objective","cult_narsie|SUCCESS")
else
- explanation = "Summon Nar-Sie. Fail."
+ explanation = "Summon Nar-Sie. Fail."
feedback_add_details("cult_objective","cult_narsie|FAIL")
text += " Objective #[obj_count]: [explanation]"
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 6aaeba71931..c519f805608 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -1,6 +1,6 @@
/obj/item/weapon/melee/cultblade
- name = "cult blade"
- desc = "An arcane weapon wielded by the followers of Nar-Sie"
+ name = "eldritch longsword"
+ desc = "A sword humming with unholy energy. It glows with a dim red light."
icon_state = "cultblade"
item_state = "cultblade"
flags = CONDUCT
@@ -11,28 +11,31 @@
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+
/obj/item/weapon/melee/cultblade/attack(mob/living/target, mob/living/carbon/human/user)
- if(iscultist(user))
- return ..()
- else
- user.Paralyse(5)
- user << "An unexplicable force powerfully repels the sword from [target]!"
- var/organ = ((user.hand ? "l_":"r_") + "arm")
- var/obj/item/organ/limb/affecting = user.get_organ(organ)
- if(affecting.take_damage(rand(force/2, force))) //random amount of damage between half of the blade's force and the full force of the blade.
- user.update_damage_overlays(0)
- return
+ if(!iscultist(user))
+ user.Weaken(5)
+ user.visible_message("A powerful force shoves [user] away from [target]!", \
+ "\"You shouldn't play with sharp things. You'll poke someone's eye out.\"")
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ H.apply_damage(rand(force/2, force), BRUTE, pick("l_arm", "r_arm"))
+ else
+ user.adjustBruteLoss(rand(force/2,force))
+ return
+ ..()
/obj/item/weapon/melee/cultblade/pickup(mob/living/user)
if(!iscultist(user))
- user << "An overwhelming feeling of dread comes over you as you pick up the cultist's sword. It would be wise to be rid of this blade quickly."
+ user << "\"I wouldn't advise that.\""
+ user << "An overwhelming sense of nausea overpowers you!"
user.Dizzy(120)
/obj/item/clothing/head/culthood
- name = "cult hood"
+ name = "ancient cultist hood"
icon_state = "culthood"
- desc = "A hood worn by the followers of Nar-Sie."
+ desc = "A torn, dust-caked hood. Strange letters line the inside."
flags_inv = HIDEFACE
flags_cover = HEADCOVERSEYES
armor = list(melee = 30, bullet = 10, laser = 5,energy = 5, bomb = 0, bio = 0, rad = 0)
@@ -41,18 +44,9 @@
heat_protection = HEAD
max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT
-
-/obj/item/clothing/head/culthood/alt
- icon_state = "cult_hoodalt"
- item_state = "cult_hoodalt"
-
-/obj/item/clothing/suit/cultrobes/alt
- icon_state = "cultrobesalt"
- item_state = "cultrobesalt"
-
/obj/item/clothing/suit/cultrobes
- name = "cult robes"
- desc = "A set of armored robes worn by the followers of Nar-Sie"
+ name = "ancient cultist robes"
+ desc = "A ragged, dusty set of robes. Strange letters line the inside."
icon_state = "cultrobes"
item_state = "cultrobes"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
@@ -64,6 +58,20 @@
heat_protection = CHEST|GROIN|LEGS|ARMS
max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
+
+/obj/item/clothing/head/culthood/alt
+ name = "cultist hood"
+ desc = "An armored hood worn by the followers of Nar-Sie."
+ icon_state = "cult_hoodalt"
+ item_state = "cult_hoodalt"
+
+/obj/item/clothing/suit/cultrobes/alt
+ name = "cultist hood"
+ desc = "An armored set of robes worn by the followers of Nar-Sie."
+ icon_state = "cultrobesalt"
+ item_state = "cultrobesalt"
+
+
/obj/item/clothing/head/magus
name = "magus helm"
icon_state = "magus"
@@ -86,18 +94,18 @@
/obj/item/clothing/head/helmet/space/cult
- name = "cult helmet"
- desc = "A space worthy helmet used by the followers of Nar-Sie"
+ name = "nar-sian bruiser's helmet"
+ desc = "A heavily-armored helmet worn by warriors of the Nar-Sian cult. It can withstand hard vacuum."
icon_state = "cult_helmet"
item_state = "cult_helmet"
armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
/obj/item/clothing/suit/space/cult
- name = "cult armor"
+ name = "nar-sian bruiser's armor"
icon_state = "cult_armor"
item_state = "cult_armor"
- desc = "A bulky suit of armor, bristling with spikes. It looks space proof."
+ desc = "A heavily-armored exosuit worn by warriors of the Nar-Sian cult. It can withstand hard vacuum."
w_class = 3
- allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/internals/emergency_oxygen)
+ allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/internals/)
slowdown = 1
- armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
\ No newline at end of file
+ armor = list(melee = 70, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index aaac82f87df..95b685beb29 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -24,6 +24,7 @@
name = "desk"
desc = "A desk covered in arcane manuscripts and tomes in unknown languages. Looking at the text makes your skin crawl"
icon_state = "tomealtar"
+ luminosity = 1
/obj/effect/gateway
name = "gateway"
@@ -32,4 +33,4 @@
icon_state = "hole"
density = 1
unacidable = 1
- anchored = 1.0
+ anchored = 1
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index e146e9b349a..122705e782a 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -1,35 +1,18 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
+/*
-var/wordtravel = null
-var/wordself = null
-var/wordsee = null
-var/wordhell = null
-var/wordblood = null
-var/wordjoin = null
-var/wordtech = null
-var/worddestr = null
-var/wordother = null
-//var/wordhear = null
-//var/wordfree = null
-var/wordhide = null
-var/runedec = 0
-var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", "self", "see", "other", "hide")
+This file contains the arcane tome files as well as innate cultist emergency communications.
+It also contains rune words, which are soon to be removed.
-/client/proc/check_words() // -- Urist
- set category = "Special Verbs"
- set name = "Check Rune Words"
- set desc = "Check the rune-word meaning"
- if(!wordtravel)
- runerandom()
- usr << "[wordtravel] is travel, [wordblood] is blood, [wordjoin] is join, [wordhell] is Hell, [worddestr] is destroy, [wordtech] is technology, [wordself] is self, [wordsee] is see, [wordother] is other, [wordhide] is hide."
+*/
-/mob/proc/cult_add_comm()
+/mob/proc/cult_add_comm() //why the fuck does this have its own proc? not removing it because it might be used somewhere but...
verbs += /mob/living/proc/cult_innate_comm
/mob/living/proc/cult_innate_comm()
set category = "Cultist"
- set name = "Communicate"
+ set name = "Imperfect Communion"
if(!iscultist(usr)) //they shouldn't have this verb, but just to be sure...
return
@@ -42,7 +25,7 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
return
if(ishuman(usr) || ismonkey(usr)) //Damage only applies to humans and monkeys, to allow constructs to communicate
- usr.visible_message("[usr.name] starts clawing at \his arms with \his fingernails!", "You begin slicing open your arms with your fingers!")
+ usr.visible_message("[usr] starts clawing at \his arms with \his fingernails!", "You begin slicing open your arms with your fingernails!")
apply_damage(10,BRUTE, "l_arm")
apply_damage(10,BRUTE, "r_arm")
sleep(50)
@@ -55,447 +38,31 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
apply_damage(10,BRUTE, "r_arm")
if(usr.incapacitated())
return
- usr.visible_message("[usr.name] paints strange symbols with their own blood.", "You paint a messy rune with your own blood.")
+ usr.visible_message("[usr] paints strange symbols with their own blood.", "You paint a messy rune with your own blood.")
sleep(20)
cultist_commune(usr, 0, 1, input)
return
-/proc/runerandom() //randomizes word meaning
- var/list/runewords=list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri") ///"orkan" and "allaq" removed.
- wordtravel=pick(runewords)
- runewords-=wordtravel
- wordself=pick(runewords)
- runewords-=wordself
- wordsee=pick(runewords)
- runewords-=wordsee
- wordhell=pick(runewords)
- runewords-=wordhell
- wordblood=pick(runewords)
- runewords-=wordblood
- wordjoin=pick(runewords)
- runewords-=wordjoin
- wordtech=pick(runewords)
- runewords-=wordtech
- worddestr=pick(runewords)
- runewords-=worddestr
- wordother=pick(runewords)
- runewords-=wordother
-// wordhear=pick(runewords)
-// runewords-=wordhear
-// wordfree=pick(runewords)
-// runewords-=wordfree
- wordhide=pick(runewords)
- runewords-=wordhide
-
-
-/obj/effect/rune
- desc = "A strange collection of symbols drawn in blood."
- anchored = 1
- icon = 'icons/obj/rune.dmi'
- icon_state = "1"
- unacidable = 1
- layer = TURF_LAYER
-
-
- var/word1
- var/word2
- var/word3
-// Places these combos are mentioned: this file - twice in the rune code, once in imbued tome, once in tome's HTML runes.dm - in the imbue rune code. If you change a combination - dont forget to change it everywhere.
-
-// travel self [word] - Teleport to random [rune with word destination matching]
-// travel other [word] - Portal to rune with word destination matching - kinda doesnt work. At least the icon. No idea why.
-// see blood Hell - Create a new tome
-// join blood self - Incorporate person over the rune into the group
-// Hell join self - Summon TERROR
-// destroy see technology - EMP rune
-// travel blood self - Drain blood
-// see Hell join - See invisible
-// blood join Hell - Raise dead
-
-// hide see blood - Hide nearby runes
-// blood see hide - Reveal nearby runes - The point of this rune is that its reversed obscure rune. So you always know the words to reveal the rune once oyu have obscured it.
-
-// Hell travel self - Leave your body and ghost around
-// blood see travel - Manifest a ghost into a mortal body
-// Hell tech join - Imbue a rune into a talisman
-// Hell blood join - Sacrifice rune
-// destroy travel self - Wall rune
-// join other self - Summon cultist rune
-// travel technology other - Freeing rune // other blood travel was freedom join other
-
-// hide other see - Deafening rune // was destroy see hear
-// destroy see other - Blinding rune
-// destroy see blood - BLOOD BOIL
-
-// self other technology - Communication rune //was other hear blood
-// join hide technology - stun rune. Rune color: bright pink.
-/obj/effect/rune/New()
- ..()
- var/image/blood = image(loc = src)
- blood.override = 1
- for(var/mob/living/silicon/ai/AI in player_list)
- AI.client.images += blood
-
-/obj/effect/rune/examine(mob/user)
- ..()
- if(iscultist(user))
- user << "This spell circle reads: [word1] [word2] [word3]."
-
-
-
-/obj/effect/rune/attackby(obj/I, mob/user, params)
- if(istype(I, /obj/item/weapon/tome) && iscultist(user))
- user << "You retrace your steps, carefully undoing the lines of the rune."
- qdel(src)
- return
- else if(istype(I, /obj/item/weapon/nullrod))
- user << "You disrupt the vile magic with the deadening field of the null rod!"
- qdel(src)
- return
- return
-
-
-/obj/effect/rune/attack_hand(mob/living/user) // OH GOD this is horrible
- if(!iscultist(user))
- user << "You can't mouth the arcane scratchings without fumbling over them!"
- return
- var/message = "You are unable to speak the words of the rune!"
- if(!user.can_speak(message) && (user.mind && !user.mind.miming))
- user << message
- return
- if(!word1 || !word2 || !word3 || prob(user.getBrainLoss()))
- return fizzle(user)
- if(word1 == wordtravel && word2 == wordself)
- return teleport(src.word3)
- if(word1 == wordsee && word2 == wordblood && word3 == wordhell)
- return tomesummon()
- if(word1 == wordhell && word2 == worddestr && word3 == wordother)
- return armor()
- if(word1 == wordjoin && word2 == wordblood && word3 == wordself)
- return convert()
- if(word1 == wordhell && word2 == wordjoin && word3 == wordself)
- return tearreality()
- if(word1 == worddestr && word2 == wordsee && word3 == wordtech)
- return emp(src.loc,3)
- if(word1 == wordtravel && word2 == wordblood && word3 == wordself)
- return drain()
- if(word1 == wordblood && word2 == wordjoin && word3 == wordhell)
- return raise()
- if(word1 == wordhide && word2 == wordsee && word3 == wordblood)
- return obscure(4)
- if(word1 == wordhell && word2 == wordtravel && word3 == wordself)
- return ajourney()
- if(word1 == wordblood && word2 == wordsee && word3 == wordtravel)
- return manifest()
- if(word1 == wordhell && word2 == wordtech && word3 == wordjoin)
- return talisman()
- if(word1 == wordhell && word2 == wordblood && word3 == wordjoin)
- return sacrifice()
- if(word1 == wordblood && word2 == wordsee && word3 == wordhide)
- return revealrunes(src)
- if(word1 == worddestr && word2 == wordtravel && word3 == wordself)
- return wall()
- if(word1 == wordtravel && word2 == wordtech && word3 == wordother)
- return freedom()
- if(word1 == wordjoin && word2 == wordother && word3 == wordself)
- return cultsummon()
- if(word1 == wordhide && word2 == wordother && word3 == wordsee)
- return deafen()
- if(word1 == worddestr && word2 == wordsee && word3 == wordother)
- return blind()
- if(word1 == worddestr && word2 == wordsee && word3 == wordblood)
- return bloodboil()
- if(word1 == wordself && word2 == wordother && word3 == wordtech)
- return communicate()
- if(word1 == wordtravel && word2 == wordother)
- return itemport(src.word3)
- if(word1 == wordjoin && word2 == wordhide && word3 == wordtech)
- return runestun()
- if(word1 == wordtravel && word2 == wordhell && word3 == wordtech)
- return summon_shell()
- else
- user.take_overall_damage(30, 0)
- user << "You feel the life draining from you, as if Lord Nar-Sie is displeased with you."
- return fizzle(user)
-
-
-/obj/effect/rune/proc/fizzle(mob/living/cultist = null)
- var/gibberish = pick("B'ADMINES SP'WNIN SH'T","IC'IN O'OC","RO'SHA'M I'SA GRI'FF'N ME'AI","TOX'IN'S O'NM FI'RAH","IA BL'AME TOX'IN'S","FIR'A NON'AN RE'SONA","A'OI I'RS ROUA'GE","LE'OAN JU'STA SP'A'C Z'EE SH'EF","IA PT'WOBEA'RD, IA A'DMI'NEH'LP")
-
- if(cultist)
- if(istype(src,/obj/effect/rune))
- cultist.say(gibberish)
- else
- cultist.whisper(gibberish)
- visible_message("The markings pulse with a small burst of light, then fall dark.", 3, "You hear a faint fizzle.", 2)
- return
-
-/obj/effect/rune/proc/check_icon()
- src.color = rgb(255, 0, 0)
- if(word1 == wordtravel && word2 == wordself)
- icon_state = "2"
- src.color = rgb(0, 0, 255)
- return
- if(word1 == wordjoin && word2 == wordblood && word3 == wordself)
- icon_state = "3"
- return
- if(word1 == wordhell && word2 == wordjoin && word3 == wordself)
- icon_state = "4"
- return
- if(word1 == wordsee && word2 == wordblood && word3 == wordhell)
- icon_state = "5"
- src.color = rgb(0, 0 , 255)
- return
- if(word1 == worddestr && word2 == wordsee && word3 == wordtech)
- icon_state = "5"
- return
- if(word1 == wordtravel && word2 == wordblood && word3 == wordself)
- icon_state = "2"
- return
- if(word1 == wordsee && word2 == wordhell && word3 == wordjoin)
- icon_state = "4"
- src.color = rgb(0, 0 , 255)
- return
- if(word1 == wordblood && word2 == wordjoin && word3 == wordhell)
- icon_state = "1"
- return
- if(word1 == wordhide && word2 == wordsee && word3 == wordblood)
- icon_state = "1"
- src.color = rgb(0, 0 , 255)
- return
- if(word1 == wordhell && word2 == wordtravel && word3 == wordself)
- icon_state = "6"
- src.color = rgb(0, 0 , 255)
- return
- if(word1 == wordblood && word2 == wordsee && word3 == wordtravel)
- icon_state = "6"
- return
- if(word1 == wordhell && word2 == wordtech && word3 == wordjoin)
- icon_state = "3"
- src.color = rgb(0, 0 , 255)
- return
- if(word1 == wordhell && word2 == wordblood && word3 == wordjoin)
- icon_state = "[rand(1,6)]"
- src.color = rgb(255, 255, 255)
- return
- if(word1 == wordblood && word2 == wordsee && word3 == wordhide)
- icon_state = "4"
- src.color = rgb(255, 255, 255)
- return
- if(word1 == worddestr && word2 == wordtravel && word3 == wordself)
- icon_state = "1"
- src.color = rgb(255, 0, 0)
- return
- if(word1 == wordtravel && word2 == wordtech && word3 == wordother)
- icon_state = "4"
- src.color = rgb(255, 0, 255)
- return
- if(word1 == wordjoin && word2 == wordother && word3 == wordself)
- icon_state = "2"
- src.color = rgb(0, 255, 0)
- return
- if(word1 == wordhide && word2 == wordother && word3 == wordsee)
- icon_state = "4"
- src.color = rgb(0, 255, 0)
- return
- if(word1 == worddestr && word2 == wordsee && word3 == wordother)
- icon_state = "4"
- src.color = rgb(0, 0, 255)
- return
- if(word1 == worddestr && word2 == wordsee && word3 == wordblood)
- icon_state = "4"
- src.color = rgb(255, 0, 0)
- return
- if(word1 == wordself && word2 == wordother && word3 == wordtech)
- icon_state = "3"
- src.color = rgb(200, 0, 0)
- return
- if(word1 == wordtravel && word2 == wordother)
- icon_state = "1"
- src.color = rgb(200, 0, 0)
- return
- if(word1 == wordjoin && word2 == wordhide && word3 == wordtech)
- icon_state = "2"
- src.color = rgb(100, 0, 100)
- return
- icon_state="[rand(1,6)]" //random shape and color for dummy runes
- src.color = rgb(rand(1,255),rand(1,255),rand(1,255))
-
-
/obj/item/weapon/tome
name = "arcane tome"
- desc = "An old, dusty tome with frayed edges and a sinister looking cover."
+ desc = "An old, dusty tome with frayed edges and a sinister-looking cover."
icon_state ="tome"
throw_speed = 2
throw_range = 5
- w_class = 2.0
- var/notedat = ""
- var/tomedat = ""
- var/list/words = list("ire" = "ire", "ego" = "ego", "nahlizet" = "nahlizet", "certum" = "certum", "veri" = "veri", "jatkaa" = "jatkaa", "balaq" = "balaq", "mgar" = "mgar", "karazet" = "karazet", "geeri" = "geeri")
+ w_class = 2
-
- tomedat = {"
-
-
-
-
-
The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood.
-
- The book is written in an unknown dialect, there are lots of pictures of various complex geometric shapes. You find some notes in english that give you basic understanding of the many runes written in the book. The notes give you an understanding what the words for the runes should be. However, you do not know how to write all these words in this dialect.
- Below is the summary of the runes.
-
-
Contents
-
- Teleport self: Travel Self (word)
- Teleport other: Travel Other (word)
- Summon new tome: See Blood Hell
- Convert a person: Join Blood Self
- Summon Nar-Sie: Hell Join Self
- Disable technology: Destroy See Technology
- Drain blood: Travel Blood Self
- Raise dead: Blood Join Hell
- Hide runes: Hide See Blood
- Reveal hidden runes: Blood See Hide
- Leave your body: Hell travel self
- Ghost Manifest: Blood See Travel
- Imbue a talisman: Hell Technology Join
- Sacrifice: Hell Blood Join
- Create a wall: Destroy Travel Self
- Summon cultist: Join Other Self
- Free a cultist: Travel technology other
- Deafen: Hide Other See
- Blind: Destroy See Other
- Blood Boil: Destroy See Blood
- Communicate: Self Other Technology
- Stun: Join Hide Technology
- Summon Cultist Armor: Hell Destroy Other
- See Invisible: See Hell Join
-
-
Rune Descriptions
-
Teleport self
- Teleport rune is a special rune, as it only needs two words, with the third word being destination. Basically, when you have two runes with the same destination, invoking one will teleport you to the other one. If there are more than 2 runes, you will be teleported to a random one. Runes with different third words will create separate networks. You can imbue this rune into a talisman, giving you a great escape mechanism.
-
Teleport other
- Teleport other allows for teleportation for any movable object to another rune with the same third word.
-
Summon new tome
- Invoking this rune summons a new arcane tome.
-
Convert a person
- This rune opens target's mind to the realm of Nar-Sie, which usually results in this person joining the cult. However, some people (mostly the ones who posess high authority) have strong enough will to stay true to their old ideals.
-
Summon Nar-Sie
- The ultimate rune. It summons the Avatar of Nar-Sie himself, tearing a huge hole in reality and consuming everything around it. Summoning it is the final goal of any cult.
-
Disable Technology
- Invoking this rune creates a strong electromagnetic pulse in a small radius, making it basically analogic to an EMP grenade. You can imbue this rune into a talisman, making it a decent defensive item.
-
Drain Blood
- This rune instantly heals you of some brute damage at the expense of a person placed on top of the rune. Whenever you invoke a drain rune, ALL drain runes on the station are activated, draining blood from anyone located on top of those runes. This includes yourself, though the blood you drain from yourself just comes back to you. This might help you identify this rune when studying words. One drain gives up to 25HP per each victim, but you can repeat it if you need more. Draining only works on living people, so you might need to recharge your "Battery" once its empty. Drinking too much blood at once might cause blood hunger.
-
Raise Dead
- This rune allows for the resurrection of any dead person. You will need a dead human body and a living human sacrifice. Make 2 raise dead runes. Put a living non-braindead human on top of one, and a dead body on the other one. When you invoke the rune, the life force of the living human will be transferred into the dead body, allowing a ghost standing on top of the dead body to enter it, instantly and fully healing it. Use other runes to ensure there is a ghost ready to be resurrected.
-
Hide runes
- This rune makes all nearby runes completely invisible. They are still there and will work if activated somehow, but you cannot invoke them directly if you do not see them.
-
Reveal runes
- This rune is made to reverse the process of hiding a rune. It reveals all hidden runes in a rather large area around it.
-
Leave your body
- This rune gently rips your soul out of your body, leaving it intact. You can observe the surroundings as a ghost as well as communicate with other ghosts. Your body takes damage while you are there, so ensure your journey is not too long, or you might never come back.
-
Manifest a ghost
- Unlike the Raise Dead rune, this rune does not require any special preparations or vessels. Instead of using full lifeforce of a sacrifice, it will drain YOUR lifeforce. Stand on the rune and invoke it. If theres a ghost standing over the rune, it will materialise, and will live as long as you dont move off the rune or die. You can put a paper with a name on the rune to make the new body look like that person.
-
Imbue a talisman
- This rune allows you to imbue the magic of some runes into paper talismans. Create an imbue rune, then an appropriate rune beside it. Put an empty piece of paper on the imbue rune and invoke it. You will now have a one-use talisman with the power of the target rune. Using a talisman drains some health, so be careful with it. You can imbue a talisman with power of the following runes: summon tome, reveal, conceal, teleport, tisable technology, communicate, deafen, blind and stun.
-
Sacrifice
- Sacrifice rune allows you to sacrifice a living thing or a body to the Geometer of Blood. Monkeys and dead humans are the most basic sacrifices, they might or might not be enough to gain His favor. A living human is what a real sacrifice should be, however, you will need 3 people chanting the invocation to sacrifice a living person.
-
Create a wall
- Invoking this rune solidifies the air above it, creating an an invisible wall. To remove the wall, simply invoke the rune again.
-
Summon cultist
- This rune allows you to summon a fellow cultist to your location. The target cultist must be unhandcuffed ant not buckled to anything. You also need to have 3 people chanting at the rune to successfully invoke it. Invoking it takes heavy strain on the bodies of all chanting cultists.
-
Free a cultist
- This rune unhandcuffs and unbuckles any cultist of your choice, no matter where he is. Invoking it takes heavy strain on the bodies of all chanting cultists.
-
Deafen
- This rune temporarily deafens all non-cultists around you.
-
Blind
- This rune temporarily blinds all non-cultists around you. Very robust. Use together with the deafen rune to leave your enemies completely helpless.
-
Blood boil
- This rune boils the blood all non-cultists in visible range. The damage is enough to instantly critically hurt any person. You need 3 cultists invoking the rune for it to work. This rune is unreliable and may cause unpredicted effect when invoked. It also drains significant amount of your health when successfully invoked.
-
Communicate
- Invoking this rune allows you to relay a message to all cultists on the station and nearby space objects.
-
Stun
- Unlike other runes, this ons is supposed to be used in talisman form. When invoked directly, it simply releases some dark energy, briefly stunning everyone around. When imbued into a talisman, you can force all of its energy into one person, stunning him so hard he cant even speak. However, effect wears off rather fast.
-
Equip Armor
- When this rune is invoked, either from a rune or a talisman, it will equip the user with the armor of the followers of Nar-Sie. To use this rune to its fullest extent, make sure you are not wearing any form of headgear, armor, gloves or shoes, and make sure you are not holding anything in your hands.
-
See Invisible
- When invoked when standing on it, this rune allows the user to see the the world beyond as long as he does not move.
-
-
- "}
-
-
-/obj/item/weapon/tome/Topic(href,href_list[])
- if (src.loc == usr)
- var/number = text2num(href_list["number"])
- if (usr.stat|| usr.restrained())
- return
- switch(href_list["action"])
- if("clear")
- words[words[number]] = words[number]
- if("read")
- if(usr.get_active_hand() != src)
- return
- usr << browse("[tomedat]", "window=Arcane Tome")
- return
- if("change")
- words[words[number]] = input("Enter the translation for [words[number]]", "Word notes") in engwords
- for (var/entry in words)
- if ((words[entry] == words[words[number]]) && (entry != words[number]))
- words[entry] = entry
- notedat = {"
- Word translation notes
- [words[1]] is [words[words[1]]]Clear
- [words[2]] is [words[words[2]]]Clear
- [words[3]] is [words[words[3]]]Clear
- [words[4]] is [words[words[4]]]Clear
- [words[5]] is [words[words[5]]]Clear
- [words[6]] is [words[words[6]]]Clear
- [words[7]] is [words[words[7]]]Clear
- [words[8]] is [words[words[8]]]Clear
- [words[9]] is [words[words[9]]]Clear
- [words[10]] is [words[words[10]]]Clear
- "}
- usr << browse("[notedat]", "window=notes")
-// call(/obj/item/weapon/tome/proc/edit_notes)()
- else
- usr << browse(null, "window=notes")
- return
-
-
-// proc/edit_notes() FUCK IT. Cant get it to work properly. - K0000
-// world << "its been called! [usr]"
-// notedat = {"
-// Word translation notes
-// [words[1]] is [words[words[1]]]Clear
-// [words[2]] is [words[words[2]]]Clear
-// [words[3]] is [words[words[3]]]Clear
-// [words[4]] is [words[words[4]]]Clear
-// [words[5]] is [words[words[5]]]Clear
-// [words[6]] is [words[words[6]]]Clear
-// [words[7]] is [words[words[7]]]Clear
-// [words[8]] is [words[words[8]]]Clear
-// [words[9]] is [words[words[9]]]Clear
-// [words[10]] is [words[words[10]]]Clear
-// "}
-// usr << "whatev"
-// usr << browse(null, "window=tank")
+/obj/item/weapon/tome/examine(mob/user)
+ ..()
+ if(iscultist(user))
+ user << "The scriptures of the Geometer. Allows the scribing of runes and access of knowledge archives."
/obj/item/weapon/tome/attack(mob/living/M, mob/living/user)
- if(istype(M,/mob/dead))
+ if(istype(M,/mob/dead/observer))
M.invisibility = 0
- user.visible_message( \
- "[user] drags the ghost to our plane of reality!", \
- "You drag the ghost to our plane of reality!" \
- )
+ user.visible_message("[user] strikes the air with [src], and a spirit appears!", \
+ "You drag the ghost to your plane of reality!")
add_logs(user, M, "smacked", src)
return
if(!istype(M))
@@ -510,334 +77,204 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
M.reagents.add_reagent("unholywater",holy2unholy)
add_logs(user, M, "smacked", src, " removing the holy water from them")
return
- M.take_organ_damage(0,rand(5,20)) //really lucky - 5 hits for a crit
- M.visible_message("[user] beats [M] with the arcane tome!", \
- "[user] beats you with the tome, and you feel a searing heat inside you!")
+ M.take_organ_damage(0, 15) //Used to be a random between 5 and 20
+ playsound(M, 'sound/weapons/sear.ogg', 50, 1)
+ M.visible_message("[user] strikes [M] with the arcane tome!", \
+ "[user] strikes you with the tome, searing your flesh!")
+ flick("tome_attack", src)
+ user.do_attack_animation(M)
add_logs(user, M, "smacked", src)
-
-/obj/item/weapon/tome/attack_self(mob/living/user)
- usr = user
- if(!usr.canmove || usr.stat || usr.restrained())
+/obj/item/weapon/tome/attack_self(mob/user)
+ if(!iscultist(user))
+ user << "[src] seems full of unintelligible shapes, scribbles, and notes. Is this some sort of joke?"
return
+ open_tome(user)
- if(!wordtravel)
- runerandom()
- if(iscultist(user))
- var/C = 0
- for(var/obj/effect/rune/N in world)
- C++
- if (!istype(user.loc,/turf))
- user << "You do not have enough space to write a proper rune."
- return
- switch(alert("You open the tome",,"Commune","Scribe a rune", "Notes")) //Fuck the "Cancel" option. Rewrite the whole tome interface yourself if you want it to work better. And input() is just ugly. - K0000
- if("Cancel")
+/obj/item/weapon/tome/proc/open_tome(mob/user)
+ var/choice = alert(user,"You open the tome...",,"Commune","Scribe Rune","(More...)")
+ switch(choice)
+ if("(More...)")
+ var/choice2 = alert(user,"You open the tome...",,"(Back...)", "Information")
+ switch(choice2)
+ if("(Back...)")
+ return open_tome(user)
+ if("Information")
+ read_tome(user)
+ if("Scribe Rune")
+ scribe_rune(user)
+ if("Commune")
+ var/input = stripped_input(usr, "Please enter a message to tell to the other acolytes.", "Voice of Blood", "")
+ if(!input)
return
- if("Commune")
- if(usr.get_active_hand() != src)
- return
- var/input = stripped_input(usr, "Please choose a message to tell to the other acolytes.", "Voice of Blood", "")
- if(!input)
- return
- cultist_commune(user, 1, 0, input)
- return
- if("Notes")
- if(usr.get_active_hand() != src)
- return
- notedat = {"
- Read the Arcane Tome.
- Word translation notes
- [words[1]] is [words[words[1]]]Clear
- [words[2]] is [words[words[2]]]Clear
- [words[3]] is [words[words[3]]]Clear
- [words[4]] is [words[words[4]]]Clear
- [words[5]] is [words[words[5]]]Clear
- [words[6]] is [words[words[6]]]Clear
- [words[7]] is [words[words[7]]]Clear
- [words[8]] is [words[words[8]]]Clear
- [words[9]] is [words[words[9]]]Clear
- [words[10]] is [words[words[10]]]Clear
- "} // whoever screwed the tabbing on this originally is an asshole.
-// call(/obj/item/weapon/tome/proc/edit_notes)()
- user << browse("[notedat]", "window=notes")
- return
- if("Scribe a rune") //fixed more assbackward tabbing
- if(usr.get_active_hand() != src)
- return
- if (C>=26+runedec+ticker.mode.cult.len) //including the useless rune at the secret room, shouldn't count against the limit of 25 runes - Urist
- alert("The cloth of reality can't take that much of a strain. Remove some runes first!")
- return
- var/list/dictionary = list(
- "convert" = list("join","blood","self"),
- "wall" = list("destroy","travel","self"),
- "blood boil" = list("destroy","see","blood"),
- "blood drain" = list("travel","blood","self"),
- "raise dead" = list("blood","join","hell"),
- "summon narsie" = list("hell","join","self"),
- "communicate" = list("self","other","technology"),
- "emp" = list("destroy","see","technology"),
- "manifest" = list("blood","see","travel"),
- "summon tome" = list("see","blood","hell"),
- "see invisible" = list("see","hell","join"),
- "hide" = list("hide","see","blood"),
- "reveal" = list("blood","see","hide"),
- "astral journey" = list("hell","travel","self"),
- "imbue" = list("hell","technology","join"),
- "sacrifice" = list("hell","blood","join"),
- "summon cultist" = list("join","other","self"),
- "free cultist" = list("travel","technology","other"),
- "deafen" = list("hide","other","see"),
- "blind" = list("destroy","see","other"),
- "stun" = list("join","hide","technology"),
- "armor" = list("hell","destroy","other"),
- "teleport" = list("travel","self"),
- "teleport other" = list("travel","other"),
- "summon shell" = list("travel","hell","technology")
- )
+ cultist_commune(user, 1, 0, input)
+/obj/item/weapon/tome/proc/read_tome(mob/user)
+ var/text = ""
+ text += "
Archives of the Dark One
"
+ text += "As a member of the cult, your goals are almost or entirely impossible to complete without special aid from the Geometer's plane. The primary method of doing this are runes. These \
+ scribings, drawn in blood, are concentrated nodes of the magic within Nar-Sie's realm and will allow the performance of many tasks to aid you and the rest of the cult in your objectives. Runes \
+ have many different names, and almost all of them are known as Rites. The only rune that is not a Rite is the Ritual of Dimensional Rending, which can only be performed with nine cultists and calls \
+ forth the avatar of the Geometer itself (so long as it consents). A small description of each rune can be found below.
Do note that sometimes runes can be drawn incorrectly. Runes such as these \
+ will be colorful and written in gibberish. They are malformed, and invoking them serves only to ignite the Geometer's wrath. Be cautious in your scribings.
A rune's name and effects can be \
+ revealed by examining the rune.
"/*In order to write a rune, you must know the combination of words required for the rune. These words are in the tongue of the Geometer and must be written as such. \
+ A rune will always have a specific combination, and the combination for runes may be revealed by perfomring actions such as conversion or sacrifice. Once a rune has been written, any cultists can \
+ examine it to find out its \"grammar\", or the words required to scribe it. To scribe the rune, the words must be entered in lowercase and separated by exactly one space. For instance, to draw a \
+ Rite of Enlightenment, one would enter the sentence \"certum nahlizet ego\", which means \"join blood self\". You may guess at combinations or perform actions to discover them.
A full list of \
+ the Words of Power as well as their meanings in plain English are listed below, although a more complete archive may be accessed at a research desk.
\
+ The Words of Power \
+ \"ire\" is Travel \
+ \"ego\" is Self \
+ \"nahlizet\" is Blood \
+ \"certum\" is Join \
+ \"veri\" is Hell \
+ \"jatkaa\" is Other \
+ \"mgar\" is Destroy \
+ \"balaq\" is Technology \
+ \"karazet\" is See \
+ \"geeri\" is Hide
\
+ A few basic runes \
+ Rite of Translocation: \"ire ego\" \
+ Rite of Enlightenment: \"certum nahlizet ego\" \
+ Rite of Tribute: \"veri nahlizet certum\" \
+ Rite of Knowledge: \"karazet nahlizet ego\" \
+
"*/
- var/list/scribewords = list("none")
+ text += "Teleport The Rite of Translocation is a unique rite in that it requires a keyword before the scribing can begin. When invoked, the rune will \
+ search for other Rites of Translocation with the same keyword. Assuming one is found, the user will be instantaneously transported to the location of the other rune. If more than two runes are scribed \
+ with the same keyword, it will choose randomly between all eligible runes and send the invoker to one of them.
"
- var/list/english = list()
+ text += "Teleport Other The Rite of Forced Translocation, like the Rite of Translocation, works by teleporting the person on the rune to one of the \
+ same keyword. However, this rune will only work on people other than the user, allowing the user to send any living creature somewhere else.
"
- for (var/entry in words)
- if (words[entry] != entry)
- english+=list(words[entry] = entry)
+ text += "Summon Tome The Rite of Knowledge is a simplistic rune. When invoked, it will summon a single arcane tome to the rune's location before vanishing. \
+
"
- for (var/entry in dictionary)
- var/list/required = dictionary[entry]
- if (length(english&required) == required.len)
- scribewords += entry
+ text += "Convert The Rite of Enlightment is paramount to the success of the cult. It will allow you to convert normal crew members into cultists. \
+ To do this, simply place the crew member upon the rune and invoke it. This rune requires two acolytes to use. If the target to be converted is loyalty-implanted or a certain assignment, they will \
+ be unable to be converted. People the Geometer wishes sacrificed will also be ineligible for conversion, and anyone with a shielding presence like a null rod will not be converted.
"
- var/chosen_rune = null
+ text += "Sacrifice The Rite of Tribute is used to offer sacrifice to the Geometer. Simply place any living creature upon the rune and invoke it (this will not \
+ target cultists!). If this creature has a mind, a soul shard will be created and the creature's soul transported to it. This rune is required if the cult's objectives include the sacrifice of a crew \
+ member.
"
+ text += "Raise Dead The Rite of Resurrection is a delicate rite that requires two corpses. To perform the ritual, place the corpse you wish to revive onto \
+ the rune and the offering body adjacent to it. When the rune is invoked, the body to be sacrificed will turn to ashes, the life force flowing into the revival target. Assuming the target is not moved \
+ within a few seconds, they will be brought back to life, healed of all ailments.
"
- if(usr)
- chosen_rune = input ("Choose a rune to scribe.") in scribewords
- if (!chosen_rune)
- return
- if (chosen_rune == "none")
- user << "You decide against scribing a rune, perhaps you should take this time to study your notes."
- return
- if (chosen_rune == "teleport")
- dictionary[chosen_rune] += input ("Choose a destination word") in english
- if (chosen_rune == "teleport other")
- dictionary[chosen_rune] += input ("Choose a destination word") in english
+ text += "Veil Runes The Rite of Obscurity is a rite that will cause all nearby runes to become invisible. The runes will still be considered by other rites \
+ (such as the Rite of Translocation) but is unusuable directly.
"
- if(user.get_active_hand() != src)
- return
+ text += "Reveal Runes The Rite of True Sight is the foil of the Rite of Obscurity. It will turn all invisible runes visible once more, in addition to causing \
+ all spirits nearby to become partially corporeal.
"
- for (var/mob/V in viewers(src))
- V.show_message("[user] slices open a finger and begins to chant and paint symbols on the floor.", 3, "You hear chanting.", 2)
- user << "You slice open one of your fingers and begin drawing a rune on the floor whilst chanting the ritual that binds your life essence with the dark arcane energies flowing through the surrounding world."
- user.take_overall_damage((rand(9)+1)/10) // 0.1 to 1.0 damage
- if(do_after(user, 50, target = user))
- if(usr.get_active_hand() != src)
- return
- var/mob/living/carbon/human/H = user
- var/obj/effect/rune/R = new /obj/effect/rune(user.loc)
- user << "You finish drawing the arcane markings of the Geometer."
- var/list/required = dictionary[chosen_rune]
- R.word1 = english[required[1]]
- R.word2 = english[required[2]]
- R.word3 = english[required[3]]
- R.check_icon()
- R.blood_DNA = list()
- R.blood_DNA[H.dna.unique_enzymes] = H.dna.blood_type
- return
- else
- user << "The book seems full of illegible scribbles. Is this a joke?"
+ text += "Disguise Runes Many crew men enjoy drawing runes in crayon that resemble spell circles in order to play pranks on their fellow crewmen. The Rite of \
+ False Truths takes advantage of this very joke. When invoked, all nearby runes will appear dull, precisely resembling those drawn in crayon. They still cannot be cleaned by conventional means, so \
+ anyone trying to clean up the rune may become suspicious as it does not respond.
"
+
+ text += "Electromagnetic Disruption Robotic lifeforms have time and time again been the downfall of fledgling cults. The Rite of Disruption may allow you to gain the upper \
+ hand against these pests. By using the rune, a large electromagnetic pulse will be emitted from the rune's location.
"
+
+ text += "Astral Communion The Rite of Astral Communion is perhaps the most ingenious rune that is usable by a single person. Upon invoking the rune, the \
+ user's spirit will be ripped from their body. In this state, the user's physical body will be locked in place to the rune itself - any attempts to move it will result in the rune pulling it back. \
+ The body will also take constant damage while in this form, and may even die. The user's spirit will contain their consciousness, and will allow them to freely wander the station as a ghost. This may \
+ also be used to commune with the dead.
"
+
+ text += "Form Shield While simple, the Rite of the Corporeal Shield serves an important purpose in defense and hindering passage. When invoked, the \
+ rune will draw a small amount of life force from the user and make the space above the rune completely dense, rendering it impassable to all but the most complex means. The rune may be invoked again to \
+ undo this effect and allow passage again.
"
+
+ text += "Deafen The Rite of the Unheard Whisper is simple. When invoked, it will cause all non-cultists within a radius of seven tiles to become \
+ completely deaf for a large amount of time.
"
+
+ text += "Blind Much like the Rite of the Unheard Whisper, the Rite of the Unseen Glance serves a single purpose. Any non-cultists who can see \
+ the rune will instantly be blinded for a substantial amount of time.
"
+
+ text += "Stun A somewhat empowered version of the Rite of the Unseen Glance, this rune will cause any non-cultists that can see the rune to become \
+ disoriented, disabling them for a short time.
"
+
+ text += "Summon Cultist The Rite of Joined Souls requires two acolytes to use. When invoked, it will allow the user to summon a single cultist to the rune from \
+ any location. This will deal a moderate amount of damage to all invokers.
"
+
+ text += "Imbue Talisman The Rite of Binding is the only way to create talismans. A blank sheet of paper must be on top of the rune, with a valid rune nearby. After \
+ invoking it, the paper will be converted into a talisman, and the rune inlaid upon it.
"
+
+ text += "Fabricate Shell The Rite of Fabrication is the main way of creating construct shells. To use it, one must place five sheets of plasteel on top of the rune \
+ and invoke it. The sheets will them be twisted into a construct shell, ready to recieve a soul to occupy it.
"
+
+ text += "Summon Arnaments The Rite of Arming will equip the user with invoker's robes, a backpack, a Nar-Sian longsword, and a pair of boots. Any items that cannot \
+ be equipped will instead not be summoned regardless.
"
+
+ text += "Drain Life The Rite of Leeching will drain the life of any non-cultist above the rune and heal the invoker for the same amount.
"
+
+ text += "Boil Blood The Rite of Boiling Blood may be considered one of the most dangerous rites composed by the Nar-Sian cult. When invoked, it will do a \
+ massive amount of damage to all non-cultist viewers, but it will also emit an explosion upon invocation. Use with caution
"
+
+ text += "Manifest Spirit If you wish to bring a spirit back from the dead with a wish for vengeance and desire to serve, the Rite of Spectral \
+ Manifestation can do just that. When invoked, any spirits above the rune will be brought to life as a human wearing nothing that seeks only to serve you and the Geometer. However, the spirit's link \
+ to reality is fragile - you must remain on top of the rune, and you will slowly take damage. Upon stepping off the rune, the spirits will dissipate, dropping their items to the ground. You may manifest \
+ multiple spirits with one rune, but you will rapidly take damage in doing so.
"
+
+ text += "Call Forth The Geometer There is only one way to summon the avatar of Nar-Sie, and that is the Ritual of Dimensional Rending. This ritual, in \
+ comparison to other runes, is very large, requiring a 3x3 space of empty tiles to create. To invoke the rune, nine cultists must stand on the rune, so that all of them are within its circle. Then, \
+ simply invoke it. A brief tearing will be heard as the barrier between dimensions is torn open, and the avatar will come forth.
"
+
+ text += "While runes are excellent for many tasks, they lack portability. The advent of talismans has, to a degree, solved this inconvenience. Simply put, a talisman is a piece of paper with a \
+ rune inlaid within it. The words of the rune can be whispered in order to invoke its effects, although usually to a lesser extent. To create a talisman, simply use a Rite of Binding as described above. \
+ Unless stated otherwise, talismans are invoked by activating them in your hand. A list of valid rites, as well as the effects of their talisman form, can be found below.
"
+
+ text += "Talisman of Teleportation The talisman form of the Rite of Translocation will transport the invoker to a randomly chosen rune of the same keyword, then \
+ disappear.
"
+
+ text += "Talisman of Tome summoning This talisman functions identically to the rune. It can be used once, then disappears.
"
+
+ text += "Talismans of Veiling, Revealing, and Disguising These talismans all function identically to their rune counterparts, but with less range. In addition, \
+ the Talisman of True Sight will not reveal spirits. They will disappear after one use.
"
+
+ text += "Talisman of Electromagnets This talisman functions like the Rite of Disruption. It disappears after one use.
"
+
+ text += "Talisman of Stunning Without this talisman, the cult would have no way of easily acquiring targets to convert. Commonly called \"stunpapers\", this \
+ talisman functions differently from others. Rather than simply reading the words, the target must be attacked directly with the talisman. The talisman will then knock down the target for a long \
+ duration in addition to rendering them incapable of speech. Robotic lifeforms will suffer the effects of a heavy electromagnetic pulse instead."
+
+ var/datum/browser/popup = new(user, "tome", "", 800, 600)
+ popup.set_content(text)
+ popup.open()
+ return 1
+
+/obj/item/weapon/tome/proc/scribe_rune(mob/user)
+ var/chosen_keyword
+ var/rune_to_scribe
+ var/entered_rune_name
+ var/list/possible_runes = list()
+ for(var/T in typesof(/obj/effect/rune) - /obj/effect/rune/malformed - /obj/effect/rune)
+ var/obj/effect/rune/R = T
+ if(initial(R.cultist_name))
+ possible_runes.Add(initial(R.cultist_name)) //This is to allow the menu to let cultists select runes by name rather than by object path. I don't know a better way to do this
+ if(!possible_runes.len)
return
-
-/obj/item/weapon/tome/attackby(obj/item/weapon/tome/T, mob/living/user, params)
- if(istype(T, /obj/item/weapon/tome)) // sanity check to prevent a runtime error
- switch(alert("Copy the runes from your tome?",,"Copy", "Cancel"))
- if("cancel")
- return
- // var/list/nearby = viewers(1,src) //- Fuck this as well. No clue why this doesnt work. -K0000
- // if (T.loc != user)
- // return
- // for(var/mob/M in nearby)
- // if(M == user)
- for(var/entry in words)
- words[entry] = T.words[entry]
- user << "You copy the translation notes from your tome."
-
-
-/obj/item/weapon/tome/examine(mob/user)
- ..()
- if(iscultist(user))
- user << "The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood. Contains the details of every ritual his followers could think of."
-
-/obj/item/weapon/tome/imbued //admin tome, spawns working runes without waiting
- w_class = 2.0
- var/cultistsonly = 1
- attack_self(mob/user as mob)
- if(src.cultistsonly && !iscultist(usr))
- return
- if(!wordtravel)
- runerandom()
- if(user)
- var/r
- if (!istype(user.loc,/turf))
- user << "You do not have enough space to write a proper rune."
- var/list/runes = list("teleport", "itemport", "tome", "armor", "convert", "tear in reality", "emp", "drain", "raise", "obscure", "reveal", "astral journey", "manifest", "imbue talisman", "sacrifice", "wall", "freedom", "cultsummon", "deafen", "blind", "bloodboil", "communicate", "stun", "summon shell")
- r = input("Choose a rune to scribe", "Rune Scribing") in runes //not cancellable.
- var/obj/effect/rune/R = new /obj/effect/rune
- if(istype(user, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = user
- R.blood_DNA = list()
- R.blood_DNA[H.dna.unique_enzymes] = H.dna.blood_type
- switch(r)
- if("teleport")
- var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri")
- var/beacon
- if(usr)
- beacon = input("Select the last rune", "Rune Scribing") in words
- R.word1=wordtravel
- R.word2=wordself
- R.word3=beacon
- R.loc = user.loc
- R.check_icon()
- if("itemport")
- var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri")
- var/beacon
- if(usr)
- beacon = input("Select the last rune", "Rune Scribing") in words
- R.word1=wordtravel
- R.word2=wordother
- R.word3=beacon
- R.loc = user.loc
- R.check_icon()
- if("tome")
- R.word1=wordsee
- R.word2=wordblood
- R.word3=wordhell
- R.loc = user.loc
- R.check_icon()
- if("armor")
- R.word1=wordhell
- R.word2=worddestr
- R.word3=wordother
- R.loc = user.loc
- R.check_icon()
- if("convert")
- R.word1=wordjoin
- R.word2=wordblood
- R.word3=wordself
- R.loc = user.loc
- R.check_icon()
- if("tear in reality")
- R.word1=wordhell
- R.word2=wordjoin
- R.word3=wordself
- R.loc = user.loc
- R.check_icon()
- if("emp")
- R.word1=worddestr
- R.word2=wordsee
- R.word3=wordtech
- R.loc = user.loc
- R.check_icon()
- if("drain")
- R.word1=wordtravel
- R.word2=wordblood
- R.word3=wordself
- R.loc = user.loc
- R.check_icon()
- if("raise")
- R.word1=wordblood
- R.word2=wordjoin
- R.word3=wordhell
- R.loc = user.loc
- R.check_icon()
- if("obscure")
- R.word1=wordhide
- R.word2=wordsee
- R.word3=wordblood
- R.loc = user.loc
- R.check_icon()
- if("astral journey")
- R.word1=wordhell
- R.word2=wordtravel
- R.word3=wordself
- R.loc = user.loc
- R.check_icon()
- if("manifest")
- R.word1=wordblood
- R.word2=wordsee
- R.word3=wordtravel
- R.loc = user.loc
- R.check_icon()
- if("imbue talisman")
- R.word1=wordhell
- R.word2=wordtech
- R.word3=wordjoin
- R.loc = user.loc
- R.check_icon()
- if("sacrifice")
- R.word1=wordhell
- R.word2=wordblood
- R.word3=wordjoin
- R.loc = user.loc
- R.check_icon()
- if("reveal")
- R.word1=wordblood
- R.word2=wordsee
- R.word3=wordhide
- R.loc = user.loc
- R.check_icon()
- if("wall")
- R.word1=worddestr
- R.word2=wordtravel
- R.word3=wordself
- R.loc = user.loc
- R.check_icon()
- if("freedom")
- R.word1=wordtravel
- R.word2=wordtech
- R.word3=wordother
- R.loc = user.loc
- R.check_icon()
- if("cultsummon")
- R.word1=wordjoin
- R.word2=wordother
- R.word3=wordself
- R.loc = user.loc
- R.check_icon()
- if("deafen")
- R.word1=wordhide
- R.word2=wordother
- R.word3=wordsee
- R.loc = user.loc
- R.check_icon()
- if("blind")
- R.word1=worddestr
- R.word2=wordsee
- R.word3=wordother
- R.loc = user.loc
- R.check_icon()
- if("bloodboil")
- R.word1=worddestr
- R.word2=wordsee
- R.word3=wordblood
- R.loc = user.loc
- R.check_icon()
- if("communicate")
- R.word1=wordself
- R.word2=wordother
- R.word3=wordtech
- R.loc = user.loc
- R.check_icon()
- if("stun")
- R.word1=wordjoin
- R.word2=wordhide
- R.word3=wordtech
- R.loc = user.loc
- R.check_icon()
- if("summon shell")
- R.word1=wordtravel
- R.word2=wordhell
- R.word3=wordtech
- R.loc = user.loc
- R.check_icon()
+ entered_rune_name = input(user, "Choose a rite to scribe.", "Sigils of Power") as null|anything in possible_runes
+ for(var/T in typesof(/obj/effect/rune))
+ var/obj/effect/rune/R = T
+ if(initial(R.cultist_name) == entered_rune_name)
+ rune_to_scribe = R
+ if(initial(R.req_keyword))
+ var/the_keyword = stripped_input(usr, "Please enter a keyword for the rune.", "Enter Keyword", "")
+ if(!the_keyword)
+ return
+ chosen_keyword = the_keyword
+ break
+ if(!rune_to_scribe)
+ return
+ user.visible_message("[user] cuts open their arm and begins writing in their own blood!", \
+ "You slice open your arm and begin drawing a sigil of the Geometer.")
+ if(iscarbon(user))
+ var/mob/living/carbon/C = user
+ C.apply_damage(0.1, BRUTE, pick("l_arm", "r_arm"))
+ if(!do_after(user, 50, target = get_turf(user)))
+ return
+ user.visible_message("[user] creates a strange circle in their own blood.", \
+ "You finish drawing the arcane markings of the Geometer.")
+ var/obj/effect/rune/R = new rune_to_scribe(get_turf(user))
+ if(chosen_keyword)
+ R.keyword = chosen_keyword
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index ab505d83329..d9ce858c153 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -1,1053 +1,1001 @@
var/list/sacrificed = list()
+var/list/non_revealed_runes = (typesof(/obj/effect/rune) - /obj/effect/rune/malformed - /obj/effect/rune )
+
+/*
+
+This file contains runes.
+Runes are used by the cult to cause many different effects and are paramount to their success.
+They are drawn with an arcane tome in blood, and are distinguishable to cultists and normal crew by examining.
+Fake runes can be drawn in crayon to fool people.
+Runes can either be invoked by one's self or with many different cultists. Each rune has a specific incantation that the cultists will say when invoking it.
+
+To draw a rune, use an arcane tome and enter the words required. These words are in the tongue of the Geometer and must be entered as such.
+Word definitions:
+"ire" is Travel
+"ego" is Self
+"nahlizet" is Blood
+"certum" is Join
+"veri" is Hell
+"jatkaa" is Other
+"mgar" is Destroy
+"balaq" is Technology
+"karazet" is See
+"geeri" is Hide
+
+*/
/obj/effect/rune
+ name = "rune"
+ var/cultist_name = "basic rune"
+ desc = "An odd collection of symbols drawn in what seems to be blood."
+ var/cultist_desc = "A basic rune with no function." //This is shown to cultists who examine the rune in order to determine its true purpose.
+ anchored = 1
+ icon = 'icons/obj/rune.dmi'
+ icon_state = "1"
+ unacidable = 1
+ layer = TURF_LAYER
+ color = rgb(255,0,0)
+ mouse_opacity = 2
+ var/invocation = "Aiy ele-mayo!" //This is said by cultists when the rune is invoked.
+ var/grammar //This is only framework at the moment, but may be required to draw runes in the future
+ var/req_cultists = 1 //The amount of cultists required around the rune to invoke it. If only 1, any cultist can invoke it.
-///Teleport: Teleports the user to a random teleport rune with the same rune. Can be imbued into a talisman.
+ var/req_pylons = 0
+ var/req_forges = 0
+ var/req_archives = 0
+ var/req_altars = 0
+ var/req_keyword = 0 //If the rune requires a keyword - go figure amirite
+ var/keyword //The actual keyword for the rune
-/obj/effect/rune/proc/teleport(key)
- var/mob/living/user = usr
- var/allrunesloc[]
- allrunesloc = new/list()
- var/index = 0
- // var/tempnum = 0
- for(var/obj/effect/rune/R in world)
- if(R == src)
- continue
- if(R.word1 == wordtravel && R.word2 == wordself && R.word3 == key && R.z != ZLEVEL_CENTCOM)
- index++
- allrunesloc.len = index
- allrunesloc[index] = R.loc
- if(index >= 5)
- user << "You feel pain, as rune disappears in reality shift caused by too much wear of space-time fabric"
- if (istype(user, /mob/living))
- user.take_overall_damage(5, 0)
+/obj/effect/rune/examine(mob/user)
+ ..()
+ if(iscultist(user) || user.stat == DEAD) //If they're a cultist or a ghost, tell them the effects
+ user << "Name: [cultist_name]"
+ user << "Effects: [cultist_desc]"
+ //user << "Words: [grammar]"
+ user << "Required Acolytes: [req_cultists]"
+ if(req_keyword && keyword)
+ user << "Keyword: [keyword]"
+
+/obj/effect/rune/attackby(obj/I, mob/user, params)
+ if(istype(I, /obj/item/weapon/tome) && iscultist(user))
+ user << "You carefully erase [src]."
qdel(src)
- if(allrunesloc && index != 0)
- if(istype(src,/obj/effect/rune))
- user.say("Sas[pick("'","`")]so c'arta forbici!")//Only you can stop auto-muting
- else
- user.whisper("Sas[pick("'","`")]so c'arta forbici!")
- user.visible_message("[user] disappears in a flash of red light!", \
- "You feel as your body gets dragged through the dimension of Nar-Sie!", \
- "You hear a sickening crunch and sloshing of viscera.")
- user.loc = allrunesloc[rand(1,index)]
return
- if(istype(src,/obj/effect/rune))
- return fizzle(user) //Use friggin manuals, Dorf, your list was of zero length.
- else
- call(/obj/effect/rune/proc/fizzle)()
- return
-
-
-//Subtype of teleport, teleports any items and mobs on top of the rune rather than the user themselves
-/obj/effect/rune/proc/itemport(key)
-// var/allrunesloc[]
-// allrunesloc = new/list()
-// var/index = 0
-// var/tempnum = 0
- var/culcount = 0
- var/runecount = 0
- var/obj/effect/rune/IP = null
- var/mob/living/user = usr
- for(var/obj/effect/rune/R in world)
- if(R == src)
- continue
- if(R.word1 == wordtravel && R.word2 == wordother && R.word3 == key)
- IP = R
- runecount++
- if(runecount >= 2)
- user << "You feel pain, as the rune disappears in reality shift caused by too much wear of space-time fabric"
- if (istype(user, /mob/living))
- user.take_overall_damage(5, 0)
+ else if(istype(I, /obj/item/weapon/nullrod))
+ user << "You disrupt the magic with [I]."
qdel(src)
- for(var/mob/living/C in orange(1,src))
- if(iscultist(C) && !C.stat)
- culcount++
- if(user.loc==src.loc)
- return fizzle(user)
- if(culcount>=1)
- user.say("Sas[pick("'","`")]so c'arta forbici tarem!")
- user.visible_message("You feel air moving from the rune - like as it was swapped with somewhere else.", \
- "You feel air moving from the rune - like as it was swapped with somewhere else.", \
- "You smell ozone.")
- for(var/obj/O in src.loc)
- if(!O.anchored)
- O.loc = IP.loc
- for(var/mob/M in src.loc)
- M.loc = IP.loc
return
-
- return fizzle(user)
-
-
-///Summon Tome: Summons a completely untranslated tome.
-
-
-/obj/effect/rune/proc/tomesummon()
- if(istype(src,/obj/effect/rune))
- usr.say("N[pick("'","`")]ath reth sh'yro eth d'raggathnor!")
- else
- usr.whisper("N[pick("'","`")]ath reth sh'yro eth d'raggathnor!")
- usr.visible_message("Rune disappears with a flash of red light, and in its place now a book lies.", \
- "You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a book.", \
- "You hear a pop and smell ozone.")
- if(istype(src,/obj/effect/rune))
- new /obj/item/weapon/tome(src.loc)
- else
- new /obj/item/weapon/tome(usr.loc)
- qdel(src)
return
-
-///Convert: The primary method of gaining new followers. Requires three cultists, doesn't work on loyalty implanted people, captains, or chaplains.
-
-
-/obj/effect/rune/proc/convert()
- var/list/mob/living/cultsinrange = list()
- for(var/mob/living/carbon/M in src.loc)
- if(iscultist(M))
- continue
- if(M.stat==2)
- continue
- for(var/mob/living/C in orange(1,src))
- if(iscultist(C) && !C.stat) //converting requires three cultists
- cultsinrange += C
- C.say("Mah[pick("'","`")]weyh pleggh at e'ntrath!")
- if(cultsinrange.len >= 3)
- M.visible_message("[M] writhes in pain as the markings below him glow a bloody red.", \
- "AAAAAAHHHH!", \
- "You hear an anguished scream.")
- if(is_convertable_to_cult(M.mind))
- ticker.mode.add_cultist(M.mind)
- M.mind.special_role = "Cultist"
- M << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root."
- M << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back."
- else
- M << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root."
- M << "And not a single fuck was given, exterminate the cult at all costs."
- if(ticker.mode.name == "cult")
- if(M.mind == ticker.mode.sacrifice_target)
- for(var/mob/living/carbon/human/cultist in cultsinrange)
- cultist << "The Chosen One!! KILL THE CHOSEN ONE!!! "
- return 0
- else
- for(var/mob/living/carbon/human/cultist in cultsinrange)
- cultist << "You need more brothers to overcome their lies and make them see Truth. "
- return fizzle()
-
-
-///Summon Nar-Sie: Summons the avatar of Nar-Sie to wreak havoc on the station. Will turn walls and floors to cult version and make anyone it touches into a harvester.
-
-
-/obj/effect/rune/proc/tearreality()
- var/list/mob/living/cultist_count = list()
- var/mob/living/user = usr
- user.say("Tok-lyr rqa'nap g[pick("'","`")]lt-ulotf!")
- for(var/mob/M in range(1,src))
- if(iscultist(M) && !M.stat)
- cultist_count += M
- if(cultist_count.len >= 9)
- if(ticker.mode.name == "cult")
- var/datum/game_mode/cult/cultmode = ticker.mode
- if(!("eldergod" in cultmode.cult_objectives))
- message_admins("[usr.real_name]([usr.ckey]) tried to summon a god when she didn't want to come out to play.") // Admin alert because you *KNOW* dickbutts are going to abuse this.
- for(var/mob/M in cultist_count)
- M.reagents.add_reagent("hell_water", 10)
- M << "YOUR SOUL BURNS WITH YOUR ARROGANCE!!!"
- return
- else
- for(var/obj_count=1, obj_count <= cultmode.cult_objectives.len, obj_count++)
- if(cultmode.cult_objectives[obj_count] == "sacrifice")
- if(cultmode.sacrifice_target)
- if(!(cultmode.sacrifice_target in sacrificed))
- for(var/mob/M in cultist_count)
- M << "Nar-sie refuses to be summoned while the sacrifice isn't complete."
- return
- cultmode.eldergod = 0
- var/narsie_type = /obj/singularity/narsie/large
- // Moves narsie if she was already summoned.
- var/obj/her = locate(narsie_type, SSobj.processing)
- if(her)
- her.loc = get_turf(src)
- return
- // Otherwise...
- new narsie_type(src.loc) // Summon her!
- qdel(src) // Stops cultists from spamming the rune to summon narsie more than once.
- // Might actually be wise to straight up del() this
+/obj/effect/rune/attack_hand(mob/living/user)
+ if(!iscultist(user))
+ user << "You aren't able to understand the words of [src]."
return
+ if(can_invoke(user))
+ invoke(user)
else
- return fizzle()
+ fail_invoke(user)
+/*
-///EMP: Lets out a large EMP blast
+There are a few different procs each rune runs through when a cultist activates it.
+can_invoke() is called when a cultist activates the rune with an empty hand. If there are multiple cultists, this rune determines if the required amount is nearby.
+invoke() is the rune's actual effects.
+fail_invoke() is called when the rune fails, via not enough people around or otherwise. Typically this just has a generic 'fizzle' effect.
+structure_check() searches for nearby cultist structures required for the invocation. Proper structures are pylons, forges, archives, and altars.
+*/
-/obj/effect/rune/proc/emp(U,range_red) //range_red - var which determines by which number to reduce the default emp range, U is the source loc, needed because of talisman emps which are held in hand at the moment of using and that apparently messes things up -- Urist
- if(istype(src,/obj/effect/rune))
- usr.say("Ta'gh fara[pick("'","`")]qha fel d'amar det!")
+/obj/effect/rune/proc/can_invoke(var/mob/living/user)
+ //This proc determines if the rune can be invoked at the time. If there are multiple required cultists, it will find all nearby cultists.
+ if(!structure_check(req_pylons, req_forges, req_archives, req_altars))
+ return 0
+ if(!keyword && req_keyword)
+ return 0
+ if(req_cultists <= 1)
+ if(invocation)
+ user.say(invocation)
+ return 1
else
- usr.whisper("Ta'gh fara[pick("'","`")]qha fel d'amar det!")
- playsound(U, 'sound/items/Welder2.ogg', 25, 1)
- var/turf/T = get_turf(U)
- if(T)
- T.hotspot_expose(700,125)
- var/rune = src // detaching the proc - in theory
- empulse(U, (range_red - 2), range_red)
- qdel(rune)
-
-///Blood Drain: Deals 1-25 damage to someone on top of it and heals an equivalent amount of brute damage to the user. Can be stacked. Too much blood drain = blood hunger that must be sated.
-
-/obj/effect/rune/proc/drain()
- var/drain = 0
- for(var/obj/effect/rune/R in world)
- if(R.word1==wordtravel && R.word2==wordblood && R.word3==wordself)
- for(var/mob/living/carbon/D in R.loc)
- if(D.stat!=2)
- var/bdrain = rand(1,25)
- D << "You feel weakened."
- D.take_overall_damage(bdrain, 0)
- drain += bdrain
- if(!drain)
- return fizzle()
- usr.say ("Yu[pick("'","`")]gular faras desdae. Havas mithum javara. Umathar uf'kal thenar!")
- usr.visible_message("Blood flows from the rune into [usr]!", \
- "The blood starts flowing from the rune and into your frail mortal body. You feel... empowered.", \
- "You hear a liquid flowing.")
- var/mob/living/user = usr
- if(user.bhunger)
- user.bhunger = max(user.bhunger-2*drain,0)
- if(drain>=50)
- user.visible_message("[user]'s eyes give off eerie red glow!", \
- "...but it wasn't nearly enough. You crave, crave for more. The hunger consumes you from within.", \
- "You hear a heartbeat.")
- user.bhunger += drain
- src = user
- spawn()
- for (,user.bhunger>0,user.bhunger--)
- sleep(50)
- user.take_overall_damage(3, 0)
- return
- user.heal_organ_damage(drain%5, 0)
- drain-=drain%5
- for (,drain>0,drain-=5)
- sleep(2)
- user.heal_organ_damage(5, 0)
- return
-
-
-///Raise Dead: Requires two corpses. Brings one to life and gibs the other.
-
-
-/obj/effect/rune/proc/raise()
- var/mob/living/carbon/human/corpse_to_raise
- var/mob/living/carbon/human/body_to_sacrifice
-
- var/is_sacrifice_target = 0
- for(var/mob/living/carbon/human/M in src.loc)
- if(M.stat == DEAD)
- if(ticker.mode.name == "cult" && M.mind == ticker.mode:sacrifice_target)
- is_sacrifice_target = 1
- else
- corpse_to_raise = M
- if(M.key)
- M.ghostize(1) //kick them out of their body
- break
- if(!corpse_to_raise)
- if(is_sacrifice_target)
- usr << "The Geometer of blood wants this mortal for himself."
- return fizzle()
-
-
- is_sacrifice_target = 0
- find_sacrifice:
- for(var/obj/effect/rune/R in world)
- if(R.word1==wordblood && R.word2==wordjoin && R.word3==wordhell)
- for(var/mob/living/carbon/human/N in R.loc)
- if(ticker.mode.name == "cult" && N.mind && N.mind == ticker.mode:sacrifice_target)
- is_sacrifice_target = 1
- else
- if(N.stat!= DEAD)
- body_to_sacrifice = N
- break find_sacrifice
-
- if(!body_to_sacrifice)
- if (is_sacrifice_target)
- usr << "The Geometer of blood wants that corpse for himself."
- else
- usr << "The sacrifical corpse is not dead. You must free it from this world of illusions before it may be used."
- return fizzle()
-
- var/mob/dead/observer/ghost
- for(var/mob/dead/observer/O in loc)
- if(!O.client) continue
- if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
- ghost = O
- break
-
- if(!ghost)
- usr << "You require a restless spirit which clings to this world. Beckon their prescence with the sacred chants of Nar-Sie."
- return fizzle()
-
- for(var/obj/item/organ/limb/affecting in corpse_to_raise.organs)
- affecting.heal_damage(1000, 1000, 0)
- corpse_to_raise.setToxLoss(0)
- corpse_to_raise.setOxyLoss(0)
- corpse_to_raise.SetParalysis(0)
- corpse_to_raise.SetStunned(0)
- corpse_to_raise.SetWeakened(0)
- corpse_to_raise.radiation = 0
- corpse_to_raise.stat = CONSCIOUS
- corpse_to_raise.updatehealth()
- corpse_to_raise.update_damage_overlays(0)
-
- corpse_to_raise.key = ghost.key //the corpse will keep its old mind! but a new player takes ownership of it (they are essentially possessed)
- //This means, should that player leave the body, the original may re-enter
- if(usr.real_name == "Herbert West")
- usr.say("To life, to life, I bring them!")
- else
- usr.say("Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!")
- corpse_to_raise.visible_message("[corpse_to_raise]'s eyes glow with a faint red as he stands up, slowly starting to breathe again.", \
- "Life... I'm alive again...", \
- "You hear a faint, slightly familiar whisper.")
- body_to_sacrifice.visible_message("[body_to_sacrifice] is torn apart, a black smoke swiftly dissipating from his remains!", \
- "You feel a horrible sensation of being torn apart, and--", \
- "You hear a thousand voices, all crying in pain.")
- body_to_sacrifice.gib()
- corpse_to_raise << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root."
- corpse_to_raise << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back."
- return
-
-
-///Veil: Makes all surrounding runes invisible. They cannot be used directly but still used indirectly (i.e. teleport...)
-
-
-/obj/effect/rune/proc/obscure(rad)
- var/S=0
- for(var/obj/effect/rune/R in orange(rad,src))
- if(R!=src)
- R.invisibility=INVISIBILITY_OBSERVER
- S=1
- if(S)
- if(istype(src,/obj/effect/rune))
- usr.say("Kla[pick("'","`")]atu barada nikt'o!")
- for (var/mob/V in viewers(src))
- V.show_message("The rune turns into gray dust, veiling the surrounding runes.", 3)
- qdel(src)
- else
- usr.whisper("Kla[pick("'","`")]atu barada nikt'o!")
- usr << "Your talisman turns into gray dust, veiling the surrounding runes."
- for (var/mob/V in orange(1,src))
- if(V!=usr)
- V.show_message("Dust emanates from [usr]'s hands for a moment.", 3)
-
- return
- if(istype(src,/obj/effect/rune))
- return fizzle()
- else
- call(/obj/effect/rune/proc/fizzle)()
- return
-
-
-///Astral Journey: Lets a player explore around as a ghost but does 10 brute damage for every tick they are like that. If they are moved from the rune they cannot return.
-
-
-/obj/effect/rune/proc/ajourney() //some bits copypastaed from admin tools - Urist
- if(usr.loc==src.loc)
- var/mob/living/carbon/human/L = usr
- usr.say("Fwe[pick("'","`")]sh mah erl nyag r'ya!")
- usr.visible_message("[usr]'s eyes glow blue as \he freezes in place, absolutely motionless.", \
- "The shadow that is your spirit separates itself from your body. You are now in the realm beyond. While this is a great sight, being here strains your mind and body. Hurry...", \
- "You hear only complete silence for a moment.")
- usr.ghostize(1)
- L.ajourn = 1
- while(L)
- if(L.key)
- L.ajourn=0
- return
- else
- L.take_organ_damage(10, 0)
- sleep(100)
- return fizzle()
-
-
-///Manifest: User must be standing on rune. When invoked, makes a culted human spawn. The user takes damage depending on how many humans there are. If the user moves, all manifested humans are killed.
-
-
-/obj/effect/rune/proc/manifest()
- var/obj/effect/rune/this_rune = src
- src = null
- if(usr.loc!=this_rune.loc)
- return this_rune.fizzle()
- var/mob/dead/observer/ghost
- for(var/mob/dead/observer/O in this_rune.loc)
- if(!O.client) continue
- if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
- ghost = O
- break
- if(!ghost)
- return this_rune.fizzle()
-
- usr.say("Gal'h'rfikk harfrandid mud[pick("'","`")]gib!")
- var/mob/living/carbon/human/dummy/D = new(this_rune.loc)
- usr.visible_message("A shape forms in the center of the rune. A shape of... a man.", \
- "A shape forms in the center of the rune. A shape of... a man.", \
- "You hear liquid flowing.")
- D.real_name = "[pick(first_names_male)] [pick(last_names)]"
- D.status_flags = CANSTUN|CANWEAKEN|CANPARALYSE|CANPUSH
-
- D.key = ghost.key
-
- if(ticker.mode.name == "cult")
- ticker.mode:add_cultist(D.mind)
- else
- ticker.mode.cult+=D.mind
-
- D.mind.special_role = "Cultist"
- D << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root."
- D << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back."
-
- var/mob/living/user = usr
- while(this_rune && user && user.stat==CONSCIOUS && user.client && user.loc==this_rune.loc)
- user.take_organ_damage(1, 0)
- sleep(30)
- if(D)
- D.visible_message("[D] slowly dissipates into dust and bones.", \
- "You feel pain, as bonds formed between your soul and this homunculus break.", \
- "You hear faint rustle.")
- D.dust()
- return
-
-
-///Imbue Talisman: Put a compatible rune near this one and a paper on top of the imbue rune. Activate, and the compatible rune will be imbued into the paper.
-
-
-/obj/effect/rune/proc/talisman()//only hide, emp, teleport, deafen, blind and tome runes can be imbued atm
- var/obj/item/weapon/paper/newtalisman
- var/unsuitable_newtalisman = 0
- for(var/obj/item/weapon/paper/P in src.loc)
- if(!P.info)
- newtalisman = P
- break
- else
- unsuitable_newtalisman = 1
- if (!newtalisman)
- if (unsuitable_newtalisman)
- usr << "The blank is tainted. It is unsuitable."
- return fizzle()
-
- var/obj/effect/rune/imbued_from
- var/obj/item/weapon/paper/talisman/T
- for(var/obj/effect/rune/R in orange(1,src))
- if(R==src)
- continue
- if(R.word1==wordtravel && R.word2==wordself) //teleport
- T = new(src.loc)
- T.imbue = "[R.word3]"
- T.info = "[R.word3]"
- imbued_from = R
- break
- if(R.word1==wordsee && R.word2==wordblood && R.word3==wordhell) //tome
- T = new(src.loc)
- T.imbue = "newtome"
- imbued_from = R
- break
- if(R.word1==worddestr && R.word2==wordsee && R.word3==wordtech) //emp
- T = new(src.loc)
- T.imbue = "emp"
- imbued_from = R
- break
- if(R.word1==wordblood && R.word2==wordsee && R.word3==worddestr) //conceal
- T = new(src.loc)
- T.imbue = "conceal"
- imbued_from = R
- break
- if(R.word1==wordhell && R.word2==worddestr && R.word3==wordother) //armor
- T = new(src.loc)
- T.imbue = "armor"
- imbued_from = R
- break
- if(R.word1==wordblood && R.word2==wordsee && R.word3==wordhide) //reveal
- T = new(src.loc)
- T.imbue = "revealrunes"
- imbued_from = R
- break
- if(R.word1==wordhide && R.word2==wordother && R.word3==wordsee) //deafen
- T = new(src.loc)
- T.imbue = "deafen"
- imbued_from = R
- break
- if(R.word1==worddestr && R.word2==wordsee && R.word3==wordother) //blind
- T = new(src.loc)
- T.imbue = "blind"
- imbued_from = R
- break
- if(R.word1==wordself && R.word2==wordother && R.word3==wordtech) //communicat
- T = new(src.loc)
- T.imbue = "communicate"
- imbued_from = R
- break
- if(R.word1==wordjoin && R.word2==wordhide && R.word3==wordtech) //communicat
- T = new(src.loc)
- T.imbue = "runestun"
- imbued_from = R
- break
- if (imbued_from)
- for (var/mob/V in viewers(src))
- V.show_message("The runes turn into dust, which then forms into an arcane image on the paper.", 3)
- usr.say("H'drak v[pick("'","`")]loso, mir'kanas verbot!")
- qdel(imbued_from)
- qdel(newtalisman)
- else
- return fizzle()
-
-
-///Communicate: Static communication rune. Somewhat pointless with free communications with tomes.
-
-
-/obj/effect/rune/proc/communicate()
- var/input = stripped_input(usr, "Please enter a message to tell to the other acolytes.", "Voice of Blood", "")
- if(!input)
- if(istype(src))
- fizzle()
- return 0
- else
- return 0
- cultist_commune(usr , 1, 1, input)
- return 1
-
-
-///Sacrifice: Gibs a target as an offering. Gives tome words as a reward and if the target has a mind, spawns a soul shard with their shade contained within.
-
-
-/obj/effect/rune/proc/sacrifice()
- var/list/mob/living/carbon/human/cultsinrange = list()
- var/list/mob/living/carbon/human/victims = list()
- for(var/mob/living/carbon/human/V in src.loc)//Checks for non-cultist humans to sacrifice
- if(ishuman(V))
- if(!(iscultist(V)))
- victims += V//Checks for cult status and mob type
- for(var/obj/item/I in src.loc)//Checks for MMIs/brains/Intellicards
- if(istype(I,/obj/item/organ/internal/brain))
- var/obj/item/organ/internal/brain/B = I
- victims += B.brainmob
- else if(istype(I,/obj/item/device/mmi))
- var/obj/item/device/mmi/B = I
- victims += B.brainmob
- else if(istype(I,/obj/item/device/aicard))
- for(var/mob/living/silicon/ai/A in I)
- victims += A
- for(var/mob/living/carbon/C in orange(1,src))
- if(iscultist(C) && !C.stat)
- cultsinrange += C
- C.say("Barhah hra zar[pick("'","`")]garis!")
- if(cultsinrange.len >= 3) break //we only need to check for three alive cultists, loop breaks so their aren't extra cultists getting word rewards
- for(var/mob/H in victims)
- if (ticker.mode.name == "cult")
- if(H.mind == ticker.mode:sacrifice_target)
- if(cultsinrange.len >= 3)
- sacrificed += H.mind
- stone_or_gib(H)
- for(var/mob/living/carbon/C in cultsinrange)
- C << "The Geometer of Blood accepts this sacrifice, your objective is now complete."
- C << "He is pleased!"
- sac_grant_word(C)
- sac_grant_word(C)
- sac_grant_word(C) //Little reward for completing the objective
- else
- usr << "Your target's earthly bonds are too strong. You need more cultists to succeed in this ritual."
- else
- if(cultsinrange.len >= 3)
- if(H.stat !=2)
- for(var/mob/living/carbon/C in cultsinrange)
- C << "The Geometer of Blood accepts this sacrifice."
- sac_grant_word(C)
- stone_or_gib(H)
- else
- if(prob(60))
- usr << "The Geometer of blood accepts this sacrifice."
- sac_grant_word(usr)
- else
- usr << "The Geometer of blood accepts this sacrifice."
- usr << "However, a mere dead body is not enough to satisfy Him."
- stone_or_gib(H)
- else
- if(H.stat !=2)
- usr << "The victim is still alive, you will need more cultists chanting for the sacrifice to succeed."
- else
- if(prob(60))
- usr << "The Geometer of blood accepts this sacrifice."
- sac_grant_word(usr)
- else
- usr << "The Geometer of blood accepts this sacrifice."
- usr << "However, a mere dead body is not enough to satisfy Him."
- stone_or_gib(H)
- else
- if(cultsinrange.len >= 3)
- if(H.stat !=2)
- for(var/mob/living/carbon/C in cultsinrange)
- C << "The Geometer of Blood accepts this sacrifice."
- sac_grant_word(C)
- stone_or_gib(H)
- else
- if(prob(60))
- usr << "The Geometer of blood accepts this sacrifice."
- sac_grant_word(usr)
- else
- usr << "The Geometer of blood accepts this sacrifice."
- usr << "However, a mere dead body is not enough to satisfy Him."
- stone_or_gib(H)
- else
- if(H.stat !=2)
- usr << "The victim is still alive, you will need more cultists chanting for the sacrifice to succeed."
- else
- if(prob(60))
- usr << "The Geometer of blood accepts this sacrifice."
- sac_grant_word(usr)
- else
- usr << "The Geometer of blood accepts this sacrifice."
- usr << "However, a mere dead body is not enough to satisfy Him."
- stone_or_gib(H)
- for(var/mob/living/carbon/monkey/M in src.loc)
- if (ticker.mode.name == "cult")
- if(M.mind == ticker.mode:sacrifice_target)
- if(cultsinrange.len >= 3)
- sacrificed += M.mind
- for(var/mob/living/carbon/C in cultsinrange)
- C << "The Geometer of Blood accepts this sacrifice, your objective is now complete."
- C << "He is pleased!"
- sac_grant_word(C)
- sac_grant_word(C)
- sac_grant_word(C) //Little reward for completing the objective
- else
- usr << "Your target's earthly bonds are too strong. You need more cultists to succeed in this ritual."
+ var/cultists_in_range = 0
+ for(var/mob/living/L in range(1, src))
+ if(iscultist(L))
+ var/mob/living/carbon/human/H = L
+ if(!istype(H))
+ if(istype(L, /mob/living/simple_animal/construct))
+ if(invocation)
+ L.say(invocation)
+ cultists_in_range++
continue
- else
- if(prob(30))
- usr << "The Geometer of Blood accepts your meager sacrifice."
- sac_grant_word(usr)
- else
- usr << "The Geometer of blood accepts this sacrifice."
- usr << "However, a mere monkey is not enough to satisfy Him."
+ if(L.stat || (H.disabilities & MUTE) || H.silent)
+ continue
+ if(invocation)
+ L.say(invocation)
+ cultists_in_range++
+ if(cultists_in_range >= req_cultists)
+ return 1
else
- usr << "The Geometer of Blood accepts your meager sacrifice."
- if(prob(30))
- ticker.mode.grant_runeword(usr)
- stone_or_gib(M)
- for(var/mob/victim in src.loc) //TO-DO: Move the shite above into the mob's own sac_act - see /mob/living/simple_animal/pet/dog/corgi/sac_act for an example
- victim.sac_act(src, victim) //Sacrifice procs are now seperate per mob, this allows us to allow sacrifice on as many mob types as we want without making an already clunky system worse
+ return 0
-/obj/effect/rune/proc/sac_grant_word(mob/living/C) //The proc that which chooses a word rewarded for a successful sacrifice, sacrifices always give a currently unknown word if the normal checks pass
- if(C.mind.cult_words.len != ticker.mode.allwords.len) // No point running if they already know everything
- var/convert_word
- var/pick_list = ticker.mode.allwords - C.mind.cult_words
- convert_word = pick(pick_list)
- ticker.mode.grant_runeword(C, convert_word)
+/obj/effect/rune/proc/invoke(var/mob/living/user)
+ //This proc contains the effects of the rune as well as things that happen afterwards. If you want it to spawn an object and then delete itself, have both here.
-/obj/effect/rune/proc/stone_or_gib(mob/T)
- var/obj/item/device/soulstone/stone = new /obj/item/device/soulstone(get_turf(src))
- if(!stone.transfer_soul("FORCE", T, usr)) //if it fails to add soul
- qdel(stone)
+/obj/effect/rune/proc/fail_invoke(var/mob/living/user)
+ //This proc contains the effects of a rune if it is not invoked correctly, through either invalid wording or not enough cultists. By default, it's just a basic fizzle.
+ visible_message("The markings pulse with a small flash of red light, then fall dark.")
+
+/obj/effect/rune/proc/structure_check(var/rpylons, var/rforges, var/rarchives, var/raltars)
+ var/pylons = 0
+ var/forges = 0
+ var/archives = 0
+ var/altars = 0
+ for(var/obj/structure/cult/pylon in orange(3,src))
+ pylons++
+ for(var/obj/structure/cult/forge in orange(3,src))
+ forges++
+ for(var/obj/structure/cult/tome in orange(3,src))
+ archives++
+ for(var/obj/structure/cult/talisman in orange(3,src))
+ altars++
+ if(pylons >= rpylons && forges >= rforges && archives >= rarchives && altars >= raltars)
+ return 1
+ return 0
+
+
+//Malformed Rune: This forms if a rune is not drawn correctly. Invoking it does nothing but hurt the user.
+/obj/effect/rune/malformed
+ cultist_name = "malformed rune"
+ cultist_desc = "A senseless rune written in gibberish. No good can come from invoking this."
+ invocation = "Ra'sha yoka!"
+ grammar = "N/A"
+
+/obj/effect/rune/malformed/New()
+ ..()
+ icon_state = "[rand(1,6)]"
+ color = rgb(rand(0,255), rand(0,255), rand(0,255))
+
+/obj/effect/rune/malformed/invoke(mob/living/user)
+ user << "You feel your life force draining. The Geometer is displeased."
+ user.apply_damage(30, BRUTE)
+ qdel(src)
+
+/mob/proc/null_rod_check() //The null rod, if equipped, will protect the holder from the effects of most runes
+ var/obj/item/weapon/nullrod/N = locate() in src
+ if(N)
+ return 1
+ return 0
+
+var/list/teleport_runes = list()
+//Rite of Translocation: Warps the user to a random teleport rune with the same keyword.
+/obj/effect/rune/teleport
+ cultist_name = "Teleport"
+ cultist_desc = "Warps the user to a random rune of the same keyword."
+ invocation = "Sas'so c'arta forbici!"
+ icon_state = "2"
+ color = rgb(0, 0, 255)
+ grammar = "ire ego"
+ req_keyword = 1
+
+/obj/effect/rune/teleport/New()
+ ..()
+ teleport_runes.Add(src)
+
+/obj/effect/rune/teleport/Destroy()
+ teleport_runes.Remove(src)
+ ..()
+
+/obj/effect/rune/teleport/invoke(mob/living/user)
+ var/list/potential_runes = list()
+ for(var/obj/effect/rune/teleport/T in teleport_runes)
+ if(T.keyword == src.keyword && T != src)
+ potential_runes.Add(T)
+
+ if(!potential_runes.len)
+ user << "There are no runes with the same keyword!"
+ fail_invoke()
+ log_game("Teleport rune failed - no candidates with matching keyword")
+ return
+
+ var/obj/effect/rune/selected_rune = pick(potential_runes)
+ if(user.buckled)
+ user.buckled.unbuckle_mob()
+ user.visible_message("[user] vanishes in a flash of red light!", \
+ "Your vision blurs, and you suddenly appear somewhere else.")
+ user.forceMove(get_turf(selected_rune))
+
+
+var/list/teleport_other_runes = list()
+//Rite of Forced Translocation: Warps the target to a random teleport rune with the same keyword.
+/obj/effect/rune/teleport_other
+ cultist_name = "Teleport Other"
+ cultist_desc = "Warps the target to a random rune of the same keyword."
+ invocation = "Sas'so c'arta forbica!"
+ icon_state = "1"
+ color = rgb(200, 0, 0)
+ grammar = "ire jatkaa"
+ req_keyword = 1
+
+/obj/effect/rune/teleport_other/New()
+ ..()
+ teleport_other_runes.Add(src)
+
+/obj/effect/rune/teleport_other/Destroy()
+ teleport_other_runes.Remove(src)
+ ..()
+
+/obj/effect/rune/teleport_other/invoke(mob/living/user)
+ var/list/potential_runes = list()
+ for(var/obj/effect/rune/teleport_other/T in teleport_other_runes)
+ if(T.keyword == src.keyword && T != src)
+ potential_runes.Add(T)
+
+ if(!potential_runes.len)
+ user << "There are no runes with the same keyword!"
+ fail_invoke()
+ log_game("Teleport Other rune failed - no candidates with matching keyword")
+ return
+
+ var/obj/effect/rune/selected_rune = pick(potential_runes)
+ var/mob/living/target
+
+ var/list/targets = list()
+ for(var/mob/living/L in get_turf(src))
+ if(L != user)
+ targets.Add(L)
+ if(!targets.len)
+ user << "There are no targets standing on the rune!"
+ fail_invoke()
+ log_game("Teleport Other rune failed - no targets on rune")
+ return
+ if(targets.len > 1)
+ target = input(user, "Choose a person to teleport.", "Rite of Forced Translocation") as null|anything in targets - user
+ if(!target)
+ fail_invoke()
+ return
+ else
+ target = targets[targets.len]
+ if(target.buckled)
+ target.buckled.unbuckle_mob()
+ target.visible_message("[target] vanishes in a flash of red light!", \
+ "Your vision blurs, and you suddenly appear somewhere else.")
+ target.forceMove(get_turf(selected_rune))
+
+
+//Rite of Knowledge: Creates an arcane tome at the rune's location and destroys the rune.
+/obj/effect/rune/summon_tome
+ cultist_name = "Summon Tome"
+ cultist_desc = "Pulls an arcane tome from the archives of the Geometer."
+ invocation = "N'ath reth sh'yro eth d'raggathnor!"
+ icon_state = "5"
+ color = rgb(0, 0, 255)
+ grammar = "karazet nahlizet ego"
+
+/obj/effect/rune/summon_tome/invoke(mob/living/user)
+ visible_message("A frayed tome materializes on the surface of [src], which dissolves into nothing.")
+ new /obj/item/weapon/tome(get_turf(src))
+ qdel(src)
+
+
+//Rite of Enlightenment: Converts a normal crewmember to the cult. Faster for every cultist nearby.
+/obj/effect/rune/convert
+ cultist_name = "Convert"
+ cultist_desc = "Converts a normal crewmember on top of it to the cult. Does not work on loyalty-implanted crew."
+ invocation = "Mah'weyh pleggh at e'ntrath!"
+ icon_state = "3"
+ color = rgb(255, 0, 0)
+ grammar = "certum nahlizet ego"
+ req_cultists = 2
+
+/obj/effect/rune/convert/invoke(mob/living/user)
+ var/list/convertees = list()
+ var/turf/T = get_turf(src)
+ for(var/mob/living/M in T.contents)
+ if(!iscultist(M) && !isloyal(M))
+ convertees.Add(M)
+ if(!convertees.len)
+ fail_invoke()
+ log_game("Convert rune failed - no eligible convertees")
+ return
+ var/mob/living/new_cultist = pick(convertees)
+ if(!is_convertable_to_cult(new_cultist.mind) || new_cultist.null_rod_check())
+ user << "Something is shielding [new_cultist]'s mind!"
+ fail_invoke()
+ log_game("Convert rune failed - convertee could not be converted")
+ if(is_sacrifice_target(new_cultist.mind))
+ for(var/mob/living/M in orange(1,src))
+ if(iscultist(M))
+ M << "\"I desire this one for myself. SACRIFICE THEM!\""
+ return
+ new_cultist.visible_message("[new_cultist] writhes in pain as the markings below them glow a bloody red!", \
+ "AAAAAAAAAAAAAA-")
+ ticker.mode.add_cultist(new_cultist.mind)
+ new_cultist.mind.special_role = "Cultist"
+ new_cultist << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
+ and something evil takes root."
+ new_cultist << "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back.\
+ "
+
+
+//Rite of Tribute: Sacrifices a crew member to Nar-Sie. Places them into a soul shard if they're in their body.
+/obj/effect/rune/sacrifice
+ cultist_name = "Sacrifice"
+ cultist_desc = "Sacrifices a crew member to the Geometer. May place them into a soul shard if their spirit remains in their body."
+ icon_state = "3"
+ invocation = "Ih wah'kd in teh'tin!"
+ color = rgb(255, 255, 255)
+ grammar = "veri nahlizet certum"
+ var/rune_in_use = 0
+
+/obj/effect/rune/sacrifice/New()
+ ..()
+ icon_state = "[rand(1,6)]"
+
+/obj/effect/rune/sacrifice/invoke(mob/living/user)
+ if(rune_in_use)
+ return
+ rune_in_use = 1
+ var/turf/T = get_turf(src)
+ var/list/possible_targets = list()
+ for(var/mob/living/M in T.contents)
+ if(!iscultist(M))
+ possible_targets.Add(M)
+ var/mob/offering
+ if(possible_targets.len > 1) //If there's more than one target, allow choice
+ offering = input(user, "Choose an offering to sacrifice.", "Unholy Tribute") as null|anything in possible_targets
+ else if(possible_targets.len) //Otherwise, if there's a target at all, pick the only one
+ offering = possible_targets[possible_targets.len]
+ if(!offering)
+ rune_in_use = 0
+ return
+ if(offering.null_rod_check())
+ user << "Something is blocking the Geometer's magic!"
+ log_game("Sacrifice rune failed - target has null rod")
+ fail_invoke()
+ rune_in_use = 0
+ return
+ if(((ishuman(offering) || isrobot(offering)) && offering.stat != DEAD) || is_sacrifice_target(offering.mind)) //Requires three people to sacrifice living targets or the round's target
+ var/cultists_nearby = 1
+ for(var/mob/living/M in orange(1,src))
+ if(iscultist(M) && M != user)
+ cultists_nearby++
+ M.say(invocation)
+ if(cultists_nearby < 3)
+ user << "You require three acolytes to sacrifice greater targets!"
+ fail_invoke()
+ log_game("Sacrifice rune failed - not enough acolytes and target is living")
+ rune_in_use = 0
+ return
+ visible_message("[src] pulses blood red!")
+ color = rgb(255, 0, 0)
+ spawn(5)
+ color = initial(color)
+ sac(offering)
+
+/obj/effect/rune/sacrifice/proc/sac(mob/living/T)
+ var/sacrifice_fulfilled
if(T)
+ if(istype(T, /mob/living/simple_animal/pet/dog/corgi))
+ for(var/mob/living/carbon/C in orange(1,src))
+ if(iscultist(C))
+ C << "Even dark gods from another plane have standards, sicko."
+ if(C.reagents)
+ C.reagents.add_reagent("hell_water", 2)
+ if(T.mind)
+ sacrificed.Add(T.mind)
+ if(is_sacrifice_target(T.mind))
+ sacrifice_fulfilled = 1
+ for(var/mob/living/M in orange(1,src))
+ if(iscultist(M))
+ if(sacrifice_fulfilled)
+ M << "\"Yes! This is the one I desire! You have done well.\""
+ else
+ if(ishuman(T) || isrobot(T))
+ M << "\"I accept this sacrifice.\""
+ else
+ M << "\"I accept this meager sacrifice.\""
+ if(T.mind)
+ var/obj/item/device/soulstone/stone = new /obj/item/device/soulstone(get_turf(src))
+ if(!stone.transfer_soul("FORCE", T, usr)) //If it cannot be added
+ qdel(stone)
+ if(!T)
+ rune_in_use = 0
+ return
if(isrobot(T))
- T.dust()//To prevent the MMI from remaining
+ playsound(T, 'sound/magic/Disable_Tech.ogg', 100, 1)
+ T.dust() //To prevent the MMI from remaining
else
+ playsound(T, 'sound/magic/Disintegrate.ogg', 100, 1)
T.gib()
+ rune_in_use = 0
-///Reveal: Reverses the Veil rune's effect, revealing all hidden runes.
+//Ritual of Dimensional Rending: Calls forth the avatar of Nar-Sie upon the station.
+/obj/effect/rune/narsie
+ cultist_name = "Call Forth The Geometer"
+ cultist_desc = "Tears apart dimensional barriers, calling forth the avatar of the Geometer."
+ invocation = "Tok-lyr rqa'nap g'olt-ulotf!"
+ req_cultists = 9
+ icon = 'icons/effects/96x96.dmi'
+ icon_state = "rune_large"
+ pixel_x = -32 //So the big ol' 96x96 sprite shows up right
+ pixel_y = -32
+ grammar = "veri certum ego"
+ var/used
-
-/obj/effect/rune/proc/revealrunes(obj/W)
- var/go=0
- var/rad
- var/S=0
- if(istype(W,/obj/effect/rune))
- rad = 6
- go = 1
- if (istype(W,/obj/item/weapon/paper/talisman))
- rad = 4
- go = 1
- if (istype(W,/obj/item/weapon/nullrod))
- rad = 1
- go = 1
- if(go)
- for(var/obj/effect/rune/R in orange(rad,src))
- if(R!=src)
- R.invisibility=0
- S=1
- if(S)
- if(istype(W,/obj/item/weapon/nullrod))
- usr << "Arcane markings suddenly glow from underneath a thin layer of dust!"
- return
- if(istype(W,/obj/effect/rune))
- usr.say("Nikt[pick("'","`")]o barada kla'atu!")
- for (var/mob/V in viewers(src))
- V.show_message("The rune turns into red dust, reveaing the surrounding runes.", 3)
- qdel(src)
- return
- if(istype(W,/obj/item/weapon/paper/talisman))
- usr.whisper("Nikt[pick("'","`")]o barada kla'atu!")
- usr << "Your talisman turns into red dust, revealing the surrounding runes."
- for (var/mob/V in orange(1,usr.loc))
- if(V!=usr)
- V.show_message("Red dust emanates from [usr]'s hands for a moment.", 3)
- return
+/obj/effect/rune/narsie/invoke(mob/living/user)
+ if(used)
return
- if(istype(W,/obj/effect/rune))
- return fizzle()
- if(istype(W,/obj/item/weapon/paper/talisman))
- call(/obj/effect/rune/proc/fizzle)()
- return
-
-
-///Wall: Makes the rune dense and uncrossable. You can invoke it again to make it normal again. Deals 2 brute damage when used.
-
-
-/obj/effect/rune/proc/wall()
- usr.say("Khari[pick("'","`")]d! Eske'te tannin!")
- src.density = !src.density
- var/mob/living/user = usr
- user.take_organ_damage(2, 0)
- if(src.density)
- usr << "Your blood flows into the rune, and you feel that the very space over the rune thickens."
- else
- usr << "Your blood flows into the rune, and you feel as the rune releases its grasp on space."
- return
-
-
-///Free Cultist: If the cultist is not walking free, makes it so.
-
-
-/obj/effect/rune/proc/freedom() //MURICA ;_;7
- var/mob/living/user = usr
- var/list/mob/living/cultists = new
- for(var/datum/mind/H in ticker.mode.cult)
- if (istype(H.current,/mob/living/carbon))
- cultists+=H.current
- var/list/mob/living/users = new
- for(var/mob/living/C in orange(1,src))
- if(iscultist(C) && !C.stat)
- users+=C
- if(users.len>=1)
- var/mob/living/carbon/cultist = input("Choose the one who you want to free", "Followers of Geometer") as null|anything in (cultists - users)
- if(!cultist)
- return fizzle(user)
- if (cultist == user) //just to be sure.
+ if(ticker.mode.name == "cult")
+ var/datum/game_mode/cult/cult_mode = ticker.mode
+ if(!("eldergod" in cult_mode.cult_objectives))
+ message_admins("[usr.real_name]([user.ckey]) tried to summon Nar-Sie when the objective was wrong")
+ for(var/mob/living/M in orange(1,src))
+ if(iscultist(M))
+ M << "\"YOUR SOUL BURNS WITH YOUR ARROGANCE!!!\""
+ if(M.reagents)
+ M.reagents.add_reagent("hell_water", 10)
+ M.Weaken(5)
+ fail_invoke()
+ log_game("Summon Nar-Sie rune failed - improper objective")
return
- if(!(cultist.buckled || \
- cultist.handcuffed || \
- istype(cultist.wear_mask, /obj/item/clothing/mask/muzzle) || \
- (istype(cultist.loc, /obj/structure/closet)&&cultist.loc:welded) || \
- (istype(cultist.loc, /obj/structure/closet/secure_closet)&&cultist.loc:locked) || \
- (istype(cultist.loc, /obj/machinery/dna_scannernew)&&cultist.loc:locked) \
- ))
- user << "The [cultist] is already free."
- return
- if(cultist.buckled)
- cultist.buckled.unbuckle_mob()
- if (cultist.handcuffed)
- cultist.handcuffed.loc = cultist.loc
- cultist.handcuffed = null
- cultist.update_inv_handcuffed()
- if (cultist.legcuffed)
- cultist.legcuffed.loc = cultist.loc
- cultist.legcuffed = null
- cultist.update_inv_legcuffed()
- if (istype(cultist.wear_mask, /obj/item/clothing/mask/muzzle))
- cultist.unEquip(cultist.wear_mask)
- if(istype(cultist.loc, /obj/structure/closet)&&cultist.loc:welded)
- cultist.loc:welded = 0
- if(istype(cultist.loc, /obj/structure/closet/secure_closet)&&cultist.loc:locked)
- cultist.loc:locked = 0
- if(istype(cultist.loc, /obj/machinery/dna_scannernew)&&cultist.loc:locked)
- cultist.loc:locked = 0
- for(var/mob/living/C in users)
- user.take_overall_damage(15, 0)
- C.say("Khari[pick("'","`")]d! Gual'te nikka!")
- qdel(src)
- return fizzle(user)
-
-
-///Summon Cultist: Requires 3 cultists, summons a cultist to the rune's location and does 25 brute to all users.
-
-
-/obj/effect/rune/proc/cultsummon()
- var/mob/living/user = usr
- var/list/mob/living/carbon/cultists = new
- for(var/datum/mind/H in ticker.mode.cult)
- if (istype(H.current,/mob/living/carbon))
- cultists+=H.current
- var/list/mob/living/users = new
- for(var/mob/living/C in orange(1,src))
- if(iscultist(C) && !C.stat)
- users+=C
- if(users.len>=3)
- var/mob/living/carbon/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - user)
- if(!cultist)
- return fizzle(user)
- if(cultist == user) //just to be sure.
- return
- if(cultist.buckled || cultist.handcuffed || (!isturf(cultist.loc) && !istype(cultist.loc, /obj/structure/closet)))
- user << "You cannot summon the [cultist], for his shackles of blood are strong"
- return fizzle(user)
- cultist.loc = src.loc
- cultist.Weaken(5)
- cultist.regenerate_icons()
- for(var/mob/living/C in orange(1,src))
- if(iscultist(C) && !C.stat)
- C.say("N'ath reth sh'yro eth d[pick("'","`")]rekkathnor!")
- C.take_overall_damage(25, 0)
- user.visible_message("Rune disappears with a flash of red light, and in its place now a body lies.", \
- "You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a body.", \
- "You hear a pop and smell ozone.")
- qdel(src)
- return fizzle(user)
-
-
-///Deafen: Makes all nearby non-cultists deaf.
-
-
-/obj/effect/rune/proc/deafen()
- if(istype(src,/obj/effect/rune))
- var/affected = 0
- for(var/mob/living/carbon/C in range(7,src))
- if (iscultist(C))
- continue
- var/obj/item/weapon/nullrod/N = locate() in C
- if(N)
- continue
- C.adjustEarDamage(0, 50)
- C.show_message("The world around you suddenly becomes quiet.", 3)
- affected++
- if(prob(1) && ishuman(C))
- C.dna.add_mutation(DEAFMUT)
- if(affected)
- usr.say("Sti[pick("'","`")] kaliedir!")
- usr << "The world becomes quiet as the deafening rune dissipates into fine dust."
- qdel(src)
else
- return fizzle()
+ if(cult_mode.sacrifice_target && !(cult_mode.sacrifice_target in sacrificed))
+ for(var/mob/living/M in orange(1,src))
+ if(iscultist(M))
+ M << "The sacrifice is not complete. The portal lacks the power to open!"
+ fail_invoke()
+ log_game("Summon Nar-Sie rune failed - sacrifice not complete")
+ return
+ if(!cult_mode.eldergod)
+ for(var/mob/living/M in orange(1,src))
+ if(iscultist(M))
+ M << "The avatar of Nar-Sie is already on this plane!"
+ log_game("Summon Nar-Sie rune failed - already summoned")
+ return
+ //BEGIN THE SUMMONING
+ used = 1
+ world << 'sound/effects/dimensional_rend.ogg'
+ world << "Rip... Rrrip...RRRRRRRRRR--"
+ sleep(40)
+ new /obj/singularity/narsie/large(get_turf(user)) //Causes Nar-Sie to spawn even if the rune has been removed
+ cult_mode.eldergod = 0
else
- var/affected = 0
- for(var/mob/living/carbon/C in range(7,usr))
- if (iscultist(C))
- continue
- var/obj/item/weapon/nullrod/N = locate() in C
- if(N)
- continue
- C.adjustEarDamage(0, 30)
- //talismans is weaker.
- C.show_message("The world around you suddenly becomes quiet.", 3)
- affected++
- if(affected)
- usr.whisper("Sti[pick("'","`")] kaliedir!")
- usr << "Your talisman turns into gray dust, deafening everyone around."
- for (var/mob/V in orange(1,src))
- if(!(iscultist(V)))
- V.show_message("Dust flows from [usr]'s hands for a moment, and the world suddenly becomes quiet..", 3)
- return
+ fail_invoke()
+ log_game("Summon Nar-Sie rune failed - gametype is not cult")
+ return
-///Blind: Makes all non-cultists nearby blind. Combine with Deafen to make the entire shuttle go into a panic and laugh as they bumble around.
+//Rite of Resurrection: Requires two corpses. Revives one and gibs the other.
+/obj/effect/rune/raise_dead
+ cultist_name = "Raise Dead"
+ cultist_desc = "Requires two corpses. The one placed upon the rune is brought to life, the other is turned to ash."
+ invocation = null //Depends on the name of the user - see below
+ icon_state = "1"
+ color = rgb(255, 0, 0)
+ grammar = "nahlizet certum veri"
+
+/obj/effect/rune/raise_dead/invoke(mob/living/user)
+ var/turf/T = get_turf(src)
+ var/mob/living/mob_to_sacrifice
+ var/mob/living/mob_to_revive
+ var/list/potential_sacrifice_mobs = list()
+ var/list/potential_revive_mobs = list()
+ for(var/mob/living/M in orange(1,src))
+ if(!(M in T.contents) && M.stat == DEAD)
+ potential_sacrifice_mobs.Add(M)
+ if(!potential_sacrifice_mobs.len)
+ user << "There is no eligible sacrifices nearby!"
+ log_game("Raise Dead rune failed - no catalyst corpse")
+ return
+ mob_to_sacrifice = input(user, "Choose a corpse to sacrifice.", "Corpse to Sacrifice") as null|anything in potential_sacrifice_mobs
+ for(var/mob/living/M in T.contents)
+ if(M.stat == DEAD)
+ potential_revive_mobs.Add(M)
+ if(!potential_revive_mobs.len)
+ user << "There is no eligible revival target on the rune!"
+ log_game("Raise Dead rune failed - no corpse to revived")
+ return
+ mob_to_revive = input(user, "Choose a corpse to revive.", "Corpse to Revive") as null|anything in potential_revive_mobs
+
+ //Begin revival
+ if(!in_range(mob_to_sacrifice,src))
+ user << "The sacrificial target has been moved!"
+ fail_invoke()
+ log_game("Raise Dead rune failed - catalyst corpse moved")
+ return
+ if(!(mob_to_revive in T.contents))
+ user << "The corpse to revived has been moved!"
+ fail_invoke()
+ log_game("Raise Dead rune failed - revival target moved")
+ return
+ if(mob_to_sacrifice.stat != DEAD)
+ user << "The sacrifical target must be dead!"
+ fail_invoke()
+ log_game("Raise Dead rune failed - catalyst corpse is not dead")
+ return
+ if(user.name == "Herbert West")
+ user.say("To life, to life, I bring them!")
+ else
+ user.say("Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!")
+ mob_to_sacrifice.visible_message("[mob_to_sacrifice] disintegrates into black mist. The mist lingers, and then flows into [mob_to_revive]!")
+ mob_to_sacrifice.dust()
+ sleep(20)
+ if(!mob_to_revive || mob_to_revive.stat != DEAD)
+ visible_message("The black mist rises and dissipates.")
+ return
+ mob_to_revive << "\"PASNAR SAVRAE YAM'TOTH. Arise.\""
+ mob_to_revive.visible_message("[mob_to_revive] draws in a huge breath, red light shining from their eyes.", \
+ "You awaken suddenly from the void. You're alive!")
+ mob_to_revive.revive() //This does remove disabilities and such, but the rune might actually see some use because of it!
+
+/obj/effect/rune/raise_dead/fail_invoke()
+ for(var/mob/living/M in orange(1,src))
+ if(M.stat == DEAD)
+ M.visible_message("[M] twitches.")
-/obj/effect/rune/proc/blind()
- if(istype(src,/obj/effect/rune))
- var/affected = 0
- for(var/mob/living/carbon/C in viewers(src))
- if (iscultist(C))
- continue
- var/obj/item/weapon/nullrod/N = locate() in C
- if(N)
- continue
+//Rite of Obscurity: Turns all runes within a 3-tile radius invisible.
+/obj/effect/rune/hide_runes
+ cultist_name = "Veil Runes"
+ cultist_desc = "Turns nearby runes invisible. They can be revealed by using the Reveal Runes rune."
+ invocation = "Kla'atu barada nikt'o!"
+ icon_state = "1"
+ color = rgb(0,0,255)
+ grammar = "geeri karazet nahlizet"
+
+/obj/effect/rune/hide_runes/invoke(mob/living/user)
+ visible_message("[src] darkens to black and vanishes.")
+ for(var/obj/effect/rune/R in orange(3,src))
+ R.visible_message("[R] fades away.")
+ R.invisibility = INVISIBILITY_OBSERVER
+ R.alpha = 100 //To help ghosts distinguish hidden runes
+ for(var/mob/dead/observer/O in orange(3,src))
+ if(!O.invisibility)
+ O << "You suddenly feel as if you've vanished..."
+ O.invisibility = INVISIBILITY_OBSERVER
+ qdel(src)
+
+
+//Rite of True Sight: Turns ghosts and obscured runes visible
+/obj/effect/rune/true_sight
+ cultist_name = "Reveal Runes"
+ cultist_desc = "Reveals all invisible objects nearby, from spirits to runes."
+ invocation = "Nikt'o barada kla'atu!"
+ icon_state = "4"
+ color = rgb(255, 255, 255)
+ grammar = "karazet geeri nahlizet"
+
+/obj/effect/rune/true_sight/invoke()
+ visible_message("[src] explodes in a flash of blinding light!")
+ for(var/mob/dead/observer/O in orange(3,src))
+ O << "You suddenly feel very obvious..."
+ O.invisibility = 0
+ for(var/obj/effect/rune/R in orange(3,src))
+ R.invisibility = 0
+ R.alpha = initial(R.alpha)
+ qdel(src)
+
+
+//Rite of False Truths: Makes runes appear like crayon ones
+/obj/effect/rune/make_runes_fake
+ cultist_name = "Disguise Runes"
+ cultist_desc = "Causes all nearby runes (including itself) to resemble those drawn in crayon."
+ invocation = "By'o isit!"
+ icon_state = "4"
+ color = rgb(0, 150, 0)
+ grammar = "geeri nahlizet jatkaa"
+
+/obj/effect/rune/make_runes_fake/invoke(mob/living/user)
+ visible_message("[src] flares brightly, then slowly dulls and appears mundane.")
+ for(var/obj/effect/rune/R in range(3,src))
+ R.desc = "A rune drawn in crayon."
+
+
+//Rite of Disruption: Emits an EMP blast.
+/obj/effect/rune/emp
+ cultist_name = "Electromagnetic Disruption"
+ cultist_desc = "Emits a large electromagnetic pulse, hindering electronics and disabling silicons."
+ invocation = "Ta'gh fara'qha fel d'amar det!"
+ icon_state = "5"
+ color = rgb(255, 0, 0)
+ grammar = "mgar karazet balaq"
+
+/obj/effect/rune/emp/invoke(mob/living/user)
+ visible_message("[src] wavers for a moment before vanishing.")
+ for(var/mob/living/carbon/C in orange(1,src))
+ C << "You feel a minute vibration pass through you!"
+ playsound(get_turf(src), 'sound/items/Welder2.ogg', 25, 1)
+ empulse(src, 4, 8) //A bit less than an EMP grenade
+ qdel(src)
+
+
+//Rite of Astral Communion: Separates one's spirit from their body. They will take damage while it is active.
+/obj/effect/rune/astral
+ cultist_name = "Astral Communion"
+ cultist_desc = "Severs the link between one's spirit and body. This effect is taxing and one's physical body will take damage while this is active."
+ invocation = "Fwe'sh mah erl nyag r'ya!"
+ icon_state = "6"
+ color = rgb(0, 0, 255)
+ var/rune_in_use = 0 //One at a time, please!
+ var/mob/living/affecting = null
+ grammar = "veri ire ego"
+
+/obj/effect/rune/astral/examine(mob/user)
+ ..()
+ if(affecting)
+ user << "A translucent field encases [user] above the rune!"
+
+/obj/effect/rune/astral/invoke(mob/living/user)
+ if(rune_in_use)
+ user << "[src] cannot support more than one body!"
+ fail_invoke()
+ log_game("Astral Communion rune failed - more than one user")
+ return
+ var/turf/T = get_turf(src)
+ if(!user in T.contents)
+ user << "You must be standing on top of [src]!"
+ fail_invoke()
+ log_game("Astral Communion rune failed - user not standing on rune")
+ return
+ rune_in_use = 1
+ affecting = user
+ user.color = src.color
+ user.visible_message("[user] freezes statue-still, their eyes glowing blue.", \
+ "You see what lies beyond. All is revealed. While this is a wondrous experience, your physical form will waste away in this state. Hurry...")
+ user.ghostize(1)
+ while(user)
+ if(!affecting)
+ visible_message("[src] pulses gently before falling dark.")
+ affecting = null //In case it's assigned to a number or something
+ rune_in_use = 0
+ return
+ affecting.apply_damage(1, BRUTE)
+ if(!(user in T.contents))
+ user.visible_message("A spectral tendril wraps around [user] and pulls them away!")
+ src.Beam(user,icon_state="b_beam",icon='icons/effects/beam.dmi',time=1)
+ user.forceMove(get_turf(src)) //NO ESCAPE :^)
+ if(user.key)
+ user.visible_message("[user] slowly relaxes, the glow in their eyes dimming.", \
+ "You are re-united with your physical form. [src] releases its hold over you.")
+ user.color = initial(user.color)
+ user.Weaken(3)
+ rune_in_use = 0
+ affecting = null
+ return
+ if(user.stat == UNCONSCIOUS)
+ if(prob(10))
+ var/mob/dead/observer/G = user.get_ghost()
+ if(G)
+ G << "You feel the link between you and your body weakening... you must hurry!"
+ if(user.stat == DEAD)
+ user.color = initial(user.color)
+ rune_in_use = 0
+ affecting = null
+ var/mob/dead/observer/G = user.get_ghost()
+ if(G)
+ G << "You suddenly feel your physical form pass on. [src]'s exertion has killed you!"
+ return
+ sleep(10)
+ rune_in_use = 0
+
+
+//Rite of the Corporeal Shield: When invoked, becomes solid and cannot be passed. Invoke again to undo.
+/obj/effect/rune/wall
+ cultist_name = "Form Shield"
+ cultist_desc = "When invoked, makes the rune block passage. Can be invoked again to reverse this."
+ invocation = "Khari'd! Eske'te tannin!"
+ icon_state = "1"
+ color = rgb(255, 0, 0)
+ grammar = "mgar ire ego"
+
+/obj/effect/rune/wall/examine(mob/user)
+ ..()
+ if(density)
+ user << "There is a barely perceptible shimmering of the air above [src]."
+
+/obj/effect/rune/wall/invoke(mob/living/user)
+ density = !density
+ user.visible_message("[user] places their hands on [src], and [density ? "the air above it begins to shimmer" : "the shimmer above it fades"].", \
+ "You channel your life energy into [src], [density ? "preventing" : "allowing"] passage above it.")
+ if(iscarbon(user))
+ var/mob/living/carbon/C = user
+ C.apply_damage(2, BRUTE, pick("l_arm", "r_arm"))
+
+
+//Rite of the Unheard Whisper: Deafens all non-cultists nearby.
+/obj/effect/rune/deafen
+ cultist_name = "Deafen"
+ cultist_desc = "Causes all non-followers nearby to lose their hearing."
+ invocation = "Sti kaliedir!"
+ grammar = "geeri jatkaa karazet"
+ color = rgb(0, 255, 0)
+ icon_state = "4"
+
+/obj/effect/rune/deafen/invoke(mob/living/user)
+ visible_message("[src] blurs for a moment before fading away.")
+ for(var/mob/living/carbon/C in range(7,src))
+ if(!iscultist(C) && !C.null_rod_check())
+ C << "The world around you goes quiet."
+ C.adjustEarDamage(0,50)
+ qdel(src)
+
+
+//Rite of the Unseen Glance: Blinds all non-cultists nearby.
+/obj/effect/rune/blind
+ cultist_name = "Blind"
+ cultist_desc = "Causes all non-followers nearby to lose their sight."
+ invocation = "Sti kaliesin!"
+ icon_state = "4"
+ color = rgb(0, 0, 255)
+ grammar = "mgar jatkaa karazet"
+
+/obj/effect/rune/blind/invoke(mob/living/user)
+ visible_message("[src] emits a blinding red flash!")
+ for(var/mob/living/carbon/C in viewers(src))
+ if(!iscultist(C) && !C.null_rod_check())
+ C << "You can't see!"
+ C.flash_eyes(1, 1)
C.eye_blurry += 50
C.eye_blind += 20
- if(prob(5))
- C.disabilities |= NEARSIGHT
- if(prob(10))
- C.disabilities |= BLIND
- C.show_message("Suddenly you see red flash that blinds you.", 3)
- affected++
- if(affected)
- usr.say("Sti[pick("'","`")] kaliesin!")
- usr << "The rune flashes, blinding those who not follow the Nar-Sie, and dissipates into fine dust."
- qdel(src)
- else
- return fizzle()
- else
- var/affected = 0
- for(var/mob/living/carbon/C in view(2,usr))
- if (iscultist(C))
- continue
- var/obj/item/weapon/nullrod/N = locate() in C
- if(N)
- continue
- C.eye_blurry += 30
- C.eye_blind += 10
- //talismans is weaker.
- affected++
- C.show_message("You feel a sharp pain in your eyes, and the world disappears into darkness..", 3)
- if(affected)
- usr.whisper("Sti[pick("'","`")] kaliesin!")
- usr << "Your talisman turns into gray dust, blinding those who not follow the Nar-Sie."
- return
+ qdel(src)
-///Blood Boil: Every non-cultist nearby will take 51 burn and 51 brute damage. 5% chance for them to gib as well. Users will take 15 brute. 10% chance for the rune to blow up.
+//Rite of Disorientation: Stuns all non-cultists nearby for a brief time
+/obj/effect/rune/stun
+ cultist_name = "Stun"
+ cultist_desc = "Stuns all nearby non-followers for a brief time."
+ invocation = "Fuu ma'jin!"
+ icon_state = "2"
+ color = rgb(100, 0, 100)
+ grammar = "certum geeri balaq"
+
+/obj/effect/rune/stun/invoke(mob/living/user)
+ visible_message("[src] explodes in a bright flash!")
+ for(var/mob/living/M in viewers(src))
+ if(!iscultist(M) && !M.null_rod_check())
+ M << "You are disoriented by [src]!"
+ M.Weaken(3)
+ M.Stun(3)
+ M.flash_eyes(1,1)
+ qdel(src)
-/obj/effect/rune/proc/bloodboil() //cultists need at least one DANGEROUS rune. Even if they're all stealthy.
- var/culcount = 0
- for(var/mob/living/carbon/C in orange(1,src))
- if(iscultist(C) && !C.stat)
- culcount++
- if(culcount>=3)
- for(var/mob/living/carbon/M in viewers(usr))
- if(iscultist(M))
- continue
- var/obj/item/weapon/nullrod/N = locate() in M
- if(N)
- continue
- M.take_overall_damage(51,51)
- M << "Your blood boils!"
- for(var/obj/effect/rune/R in view(src))
- if(prob(10))
- explosion(R.loc, -1, 0, 1, 5)
- for(var/mob/living/carbon/human/C in orange(1,src))
- if(iscultist(C) && !C.stat)
- C.say("Dedo ol[pick("'","`")]btoh!")
- C.take_overall_damage(15, 0)
- qdel(src)
- else
- return fizzle()
- return
+//Rite of Joined Souls: Summons a single cultist. Requires 2 cultists.
+/obj/effect/rune/summon
+ cultist_name = "Summon Cultist"
+ cultist_desc = "Summons a single cultist to the rune."
+ invocation = "N'ath reth sh'yro eth d'rekkathnor!"
+ req_cultists = 2
+ icon_state = "5"
+ color = rgb(0, 255, 0)
+ grammar = "certum jatkaa ego"
-
-///Stun: Everyone nearby would be stunned for a -very- short time. If used in a talisman, it stuns and mutes a single target.
-
-
-/obj/effect/rune/proc/runestun(mob/living/T)
- if(istype(src,/obj/effect/rune)) ///When invoked as rune, flash and stun everyone around.
- usr.say("Fuu ma[pick("'","`")]jin!")
- for(var/mob/living/L in viewers(src))
-
- if(iscarbon(L))
- var/mob/living/carbon/C = L
- flick("e_flash", C.flash)
- C.stuttering = 1
- C.Weaken(1)
- C.Stun(1)
- C.show_message("The rune explodes in a bright flash.", 3)
-
- else if(issilicon(L))
- var/mob/living/silicon/S = L
- S.Weaken(5)
- S.show_message("!@(%* BZZZZZT !@(%!)$", 3)
- qdel(src)
- else ///When invoked as talisman, stun and mute the target mob.
- usr.say("Dream sign ''Evil sealing talisman'[pick("'","`")]!")
- var/obj/item/weapon/nullrod/N = locate() in T
- if(N)
- for(var/mob/O in viewers(T, null))
- O.show_message(text("[] invokes a talisman at [], but they are unaffected!", usr, T), 1)
- else
- for(var/mob/O in viewers(T, null))
- O.show_message(text("[] invokes a talisman at []", usr, T), 1)
-
- if(issilicon(T))
- T.Weaken(10)
-
- else if(iscarbon(T))
- var/mob/living/carbon/C = T
- flick("e_flash", C.flash)
- C.silent += 15
- C.Weaken(10)
- C.Stun(10)
+/obj/effect/rune/summon/invoke(mob/living/user)
+ var/list/cultists = list()
+ for(var/datum/mind/M in ticker.mode.cult)
+ cultists.Add(M.current)
+ var/mob/living/cultist_to_summon = input("Who do you wish to call to [src]?", "Followers of the Geometer") as null|anything in (cultists - user)
+ if(!cultist_to_summon)
+ user << "You require a summoning target!"
+ fail_invoke()
+ log_game("Summon Cultist rune failed - no target")
return
+ if(!iscultist(cultist_to_summon))
+ user << "[cultist_to_summon] is not a follower of the Geometer!"
+ fail_invoke()
+ log_game("Summon Cultist rune failed - no target")
+ return
+ if(cultist_to_summon.buckled)
+ cultist_to_summon.buckled.unbuckle_mob()
+ cultist_to_summon.visible_message("[cultist_to_summon] suddenly disappears in a flash of red light!", \
+ "Overwhelming vertigo consumes you as you are hurled through the air!")
+ visible_message("A foggy shape materializes atop [src] and solidifes into [cultist_to_summon]!")
+ for(var/mob/living/carbon/C in orange(1,src))
+ if(iscultist(C))
+ C.apply_damage(10, BRUTE, "head")
+ cultist_to_summon.loc = get_turf(src)
+ qdel(src)
-///Armor: The user will be armed with cultist garb, a trophy rack, and a high-damage sword. If items are in these slots, they will not be equipped and simply deleted.
+//Rite of Binding: Turns a nearby rune and a paper on top of the rune to a talisman, if both are valid.
+/obj/effect/rune/imbue
+ cultist_name = "Bind Talisman"
+ cultist_desc = "Transforms papers and valid runes into talismans."
+ invocation = "H'drak v'loso, mir'kanas verbot!"
+ icon_state = "3"
+ color = rgb(0, 0, 255)
+ grammar = "veri balaq certum"
-
-/obj/effect/rune/proc/armor()
- var/list/armors = list("zealot")
- var/armorworn
- var/mob/living/carbon/human/user = usr
- if(istype(user.wear_suit, /obj/item/clothing/suit/wizrobe) && istype(user.head, /obj/item/clothing/head/wizard))
- armors += "summoner"
- if(istype(user.wear_suit, /obj/item/clothing/suit/space) && istype(user.head, /obj/item/clothing/head/helmet/space))
- armors += "traveler"
- if(istype(user.wear_suit, /obj/item/clothing/suit/space/captain) && istype(user.head, /obj/item/clothing/head/helmet/space/captain))
- armors += "marauder"
- if(istype(user.wear_suit, /obj/item/clothing/suit/armor/reactive))
- armors += "trickster"
- if(istype(user.wear_suit, /obj/item/clothing/suit/toggle/labcoat/cmo))
- armors += "physician"
- if(istype(src,/obj/effect/rune))
- armorworn = input ("Choose your attire.") in armors
+/obj/effect/rune/imbue/invoke(mob/living/user)
+ var/turf/T = get_turf(src)
+ var/list/papers_on_rune = list()
+ for(var/obj/item/weapon/paper/P in T)
+ if(!P.info)
+ papers_on_rune.Add(P)
+ if(!papers_on_rune.len)
+ user << "There must be a blank paper on top of [src]!"
+ fail_invoke()
+ log_game("Talisman Imbue rune failed - no blank papers on rune")
+ return
+ var/obj/item/weapon/paper/paper_to_imbue = pick(papers_on_rune)
+ var/list/nearby_runes = list()
+ for(var/obj/effect/rune/R in orange(1,src))
+ nearby_runes.Add(R)
+ if(!nearby_runes.len)
+ user << "There are no runes near [src]!"
+ fail_invoke()
+ log_game("Talisman Imbue rune failed - no nearby runes")
+ return
+ var/obj/effect/rune/picked_rune = pick(nearby_runes)
+ var/list/split_rune_type = text2list("[picked_rune.type]", "/")
+ var/imbue_type = split_rune_type[split_rune_type.len]
+ var/talisman_type = text2path("/obj/item/weapon/paper/talisman/[imbue_type]")
+ if(ispath(talisman_type))
+ var/obj/item/weapon/paper/talisman/TA = new talisman_type(get_turf(src))
+ if(istype(picked_rune, /obj/effect/rune/teleport))
+ var/obj/effect/rune/teleport/TR = picked_rune
+ var/obj/item/weapon/paper/talisman/teleport/TT = TA
+ TT.keyword = TR.keyword
else
- armorworn = "zealot"
- if (armorworn == "zealot")
- usr.say("N'ath reth sh'yro eth d[pick("'","`")]raggathnor!")
- user.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(user), slot_head)
- user.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), slot_wear_suit)
- user.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult(user), slot_shoes)
- user.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/cultpack(user), slot_back)
- user.put_in_hands(new /obj/item/weapon/melee/cultblade(user))
- usr.visible_message("\red The rune disappears with a flash of red light, and a set of armor appears on [usr]...", \
- "\red You are blinded by the flash of red light! After you're able to see again, you see that you are now wearing a set of armor.")
- if (armorworn == "summoner" || armorworn == "trickster" || armorworn == "physician")
- usr.say("Uln Shogg Hafh[pick("'","`")]drn!")
- user << "\red You quietly prick your finger and make a pact with the geometer of blood to acquire more power."
- user.take_overall_damage(rand(5,20))
- del(user.head)
- del(user.wear_suit)
- user.equip_to_slot_or_del(new /obj/item/clothing/head/magus(user), slot_head)
- user.equip_to_slot_or_del(new /obj/item/clothing/suit/magusred(user), slot_wear_suit)
- user.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult(user), slot_shoes)
- user.spellremove(user)
- usr.visible_message("\red The rune disappears with a flash of red light, and a set of robes appears on [usr]...", \
- "\red You are blinded by the flash of red light! After you're able to see again, you see that you are now wearing a set of robes.")
- if (armorworn == "summoner")
- user.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone/cult(user)
- user.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser/cult(user)
- if (armorworn == "trickster")
- user.put_in_hands(new /obj/item/weapon/gun/magic/wand/door(user))
- user.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink/cult(user)
- if (armorworn == "physician")
- user.put_in_hands(new /obj/item/weapon/gun/magic/wand/resurrection(user))
- if (armorworn == "traveler" || armorworn == "marauder")
- usr.say("Tharanak n[pick("'","`")]ghft!")
- del(user.head)
- del(user.wear_suit)
- user.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/cult(user), slot_head)
- user.equip_to_slot_or_del(new /obj/item/clothing/suit/space/cult(user), slot_wear_suit)
- user.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult(user), slot_shoes)
- user.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/cultpack(user), slot_back)
- user.put_in_hands(new /obj/item/weapon/melee/cultblade(user))
- user.spellremove(user)
- usr.visible_message("\red The rune disappears with a flash of red light, and an armored space suit appears on [usr]...", \
- "\red You are blinded by the flash of red light! After you're able to see again, you see that you are now wearing an armored space suit.")
- if (armorworn == "marauder")
- user.spellremove(user)
- user.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/creature/cult(user)
- del(src)
- return
-
-///Summon Shell: Summons a construct shell if there's four plasteel sheets on top of the rune
+ user << "The chosen rune was not a valid target!"
+ fail_invoke()
+ log_game("Talisman Imbue rune failed - chosen rune invalid")
+ return
+ visible_message("[picked_rune] crumbles to dust, and bloody images form themselves on [paper_to_imbue].")
+ qdel(paper_to_imbue)
+ qdel(picked_rune)
-/obj/effect/rune/proc/summon_shell() // Summons a construct shell
- for(var/obj/item/stack/sheet/plasteel/PS in src.loc) //I could probably combine the amounts but I'm too lazy to compensate for others' lazyness
- if(PS.amount >= 4) // may need increasing?
- usr.say("Eth ra p'ni[pick("'","`")]dedo ol!") //I have no idea if these are written in a proper made up language or just Urist smacking his face on the keyboard
- new /obj/structure/constructshell(src.loc)
-//? PS.remove_amount(4) //TO-DO: Write a proc for removing sheets from a stack and deleting when stack is empty... why doesnt this exist yet??
- PS.amount -= 4
- if(PS.amount <= 0)
- qdel(PS)
- qdel(src)
- return 1
- return fizzle()
+//Rite of Fabrication: Creates a construct shell out of 5 metal sheets.
+/obj/effect/rune/construct_shell
+ cultist_name = "Fabricate Shell"
+ cultist_desc = "Turns five plasteel sheets into an empty construct shell, suitable for containing a soul shard."
+ invocation = "Ethra p'ni dedol!"
+ icon_state = "5"
+ color = rgb(150, 150, 150)
+ grammar = "ire veri balaq"
+
+/obj/effect/rune/construct_shell/invoke(mob/living/user)
+ var/turf/T = get_turf(src)
+ for(var/obj/item/stack/sheet/S in T)
+ if(istype(S, /obj/item/stack/sheet/plasteel))
+ var/obj/item/stack/sheet/plasteel/M = S
+ if(M.amount >= 5)
+ new /obj/structure/constructshell(T)
+ M.visible_message("[M] bends and twists into a new form!")
+ M.amount -= 5
+ if(M.amount <= 0)
+ qdel(M)
+ qdel(src)
+ return
+ else
+ user << "There must be at least five sheets of plasteel on [src]!"
+ fail_invoke()
+ log_game("Construct Shell rune failed - not enough plasteel sheets")
+ return
+
+
+//Rite of Arming: Creates cult robes, a trophy rack, and a cult sword on the rune.
+/obj/effect/rune/armor
+ cultist_name = "Summon Arnaments"
+ cultist_desc = "Equips the user with robes, shoes, a backpack, and a longsword. Items that cannot be equipped will not be summoned."
+ invocation = "N'ath reth sh'yro eth draggathnor!"
+ icon_state = "4"
+ color = rgb(255, 0, 0)
+ grammar = "veri mgar jatkaa"
+
+/obj/effect/rune/armor/invoke(mob/living/user)
+ visible_message("With the sound of clanging metal, [src] crumbles to dust!")
+ user.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(user), slot_head)
+ user.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), slot_wear_suit)
+ user.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult/alt(user), slot_shoes)
+ user.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/cultpack(user), slot_back)
+ user.put_in_hands(new /obj/item/weapon/melee/cultblade(user))
+ qdel(src)
+
+
+//Rite of Leeching: Deals brute damage to the target and heals the same amount to the invoker.
+/obj/effect/rune/leeching
+ cultist_name = "Drain Life"
+ cultist_desc = "Drains the life of the target on the rune, restoring it to the user."
+ invocation = "Yu'gular faras desdae. Havas mithum javara. Umathar uf'kal thenar!" //that's a mouthful
+ icon_state = "2"
+ color = rgb(255, 0, 0)
+ grammar = "ire nahlizet ego"
+
+/obj/effect/rune/leeching/invoke(mob/living/user)
+ var/turf/T = get_turf(src)
+ var/list/potential_targets = list()
+ for(var/mob/living/carbon/M in T)
+ if(M.stat != DEAD && M != user)
+ potential_targets.Add(M)
+ if(!potential_targets.len)
+ user << "There must be a valid target on the rune!"
+ fail_invoke()
+ log_game("Leeching rune failed - no valid targets")
+ return
+ var/mob/living/carbon/target = pick(potential_targets)
+ var/drained_amount = rand(5,25)
+ target.apply_damage(drained_amount, BRUTE, "chest")
+ user.adjustBruteLoss(-drained_amount)
+ target << "You feel extremely weak."
+ user.visible_message("Blood flows from the rune into [user]!", \
+ "[target]'s blood flows into you, healing your wounds and revitalizing your spirit.")
+
+
+//Rite of Boiling Blood: Deals extremely high amounts of damage to non-cultists nearby
+/obj/effect/rune/blood_boil
+ cultist_name = "Boil Blood"
+ cultist_desc = "Boils the blood of non-believers who can see the rune, dealing extreme amounts of damage."
+ invocation = "Dedo ol'btoh!"
+ icon_state = "4"
+ color = rgb(255, 0, 0)
+ req_cultists = 3
+ grammar = "mgar karazet nahlizet"
+
+/obj/effect/rune/blood_boil/invoke(mob/living/user)
+ visible_message("[src] briefly bubbles before exploding!")
+ for(var/mob/living/carbon/C in viewers(src))
+ if(!iscultist(C))
+ if(C.null_rod_check())
+ C << "The null rod suddenly burns hotly before returning to normal!"
+ continue
+ C << "Agonizing heat overwhelms you!"
+ C.take_overall_damage(51,51)
+ for(var/mob/living/carbon/M in orange(1,src))
+ if(iscultist(M))
+ M.apply_damage(15, BRUTE, pick("l_arm", "r_arm"))
+ M << "[src] saps your strength!"
+ explosion(get_turf(src), -1, 0, 1, 5)
+ qdel(src)
+
+
+//Rite of Spectral Manifestation: Summons a ghost on top of the rune as a cultist human with no items. User must stand on the rune at all times, and takes damage for each summoned ghost.
+/obj/effect/rune/manifest
+ cultist_name = "Manifest Spirit"
+ cultist_desc = "Manifests a spirit as a servant of the Geometer. The invoker must not move from atop the rune, and will take damage for each summoned spirit."
+ invocation = "Gal'h'rfikk harfrandid mud'gib!" //how the fuck do you pronounce this
+ icon_state = "6"
+ color = rgb(255, 0, 0)
+ grammar = "nahlizet karazet ire"
+
+/obj/effect/rune/manifest/invoke(mob/living/user)
+ if(!(user in get_turf(src)))
+ user << "You must be standing on [src]!"
+ fail_invoke()
+ log_game("Manifest rune failed - user not standing on rune")
+ return
+ var/list/ghosts_on_rune = list()
+ for(var/mob/dead/observer/O in get_turf(src))
+ if(O.client)
+ ghosts_on_rune.Add(O)
+ if(!ghosts_on_rune.len)
+ user << "There are no spirits near [src]!"
+ fail_invoke()
+ log_game("Manifest rune failed - no nearby ghosts")
+ return
+ var/mob/dead/observer/ghost_to_spawn = pick(ghosts_on_rune)
+ var/mob/living/carbon/human/new_human = new(get_turf(src))
+ new_human.real_name = ghost_to_spawn.real_name
+ new_human.alpha = 150 //Makes them translucent
+ visible_message("A cloud of red mist forms above [src], and from within steps... a man.")
+ user << "Your blood begins flowing into [src]. You must remain in place and conscious to maintain the forms of those summoned. This will hurt you slowly but surely..."
+ new_human.key = ghost_to_spawn.key
+ ticker.mode.add_cultist(new_human.mind)
+ new_human << "You are a servant of the Geometer. You have been made semi-corporeal by the cult, and you are to serve them at all costs."
+
+ while(user in get_turf(src))
+ if(user.stat)
+ break
+ user.apply_damage(1, BRUTE)
+ sleep(30)
+
+ if(new_human)
+ new_human.visible_message("[new_human] suddenly dissolves into bones and ashes.", \
+ "Your link to the world fades. Your form breaks apart.")
+ for(var/obj/I in new_human)
+ new_human.unEquip(I)
+ new_human.dust()
diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm
index 76e97bc7371..bebcf0f2bdc 100644
--- a/code/game/gamemodes/cult/talisman.dm
+++ b/code/game/gamemodes/cult/talisman.dm
@@ -1,125 +1,288 @@
+/*
+
+Talismans are portable versions of runes that resemble blank sheets of paper. They may have different effects than their parent runes and are created by using a Rite of Binding with a paper on top and
+a compatible rune somewhere nearby. A list of compatible runes can found below.
+
+Basic Runes:
+Rite of Translocation
+Rite of Knowledge
+Rite of Obscurity
+Rite of True Sight
+Rite of False Truths
+Rite of Disruption
+Rite of Disorientation
+
+*/
+
/obj/item/weapon/paper/talisman
- icon_state = "paper_talisman"
- var/imbue = null
- var/uses = 0
+ var/cultist_name = "talisman"
+ var/cultist_desc = "A basic talisman. It serves no purpose."
+ var/invocation = "Naise meam!"
+ var/uses = 1
+ var/health_cost = 0 //The amount of health taken from the user when invoking the talisman
- attack_self(mob/living/user)
- if(iscultist(user))
- var/delete = 1
- switch(imbue)
- if("newtome")
- call(/obj/effect/rune/proc/tomesummon)()
- if("armor")
- call(/obj/effect/rune/proc/armor)()
- if("emp")
- call(/obj/effect/rune/proc/emp)(usr.loc,3)
- if("conceal")
- call(/obj/effect/rune/proc/obscure)(2)
- if("revealrunes")
- call(/obj/effect/rune/proc/revealrunes)(src)
- if("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri")
- call(/obj/effect/rune/proc/teleport)(imbue)
- if("communicate")
- //If the user cancels the talisman this var will be set to 0
- delete = call(/obj/effect/rune/proc/communicate)()
- if("deafen")
- call(/obj/effect/rune/proc/deafen)()
- if("blind")
- call(/obj/effect/rune/proc/blind)()
- if("runestun")
- user << "To use this talisman, attack your target directly."
- return
- if("supply")
- supply()
-// user.take_organ_damage(5, 0)
- if(src && src.imbue!="supply" && src.imbue!="runestun")
- if(delete)
- user.drop_item(src)
- qdel(src)
- return
- else
- user << "You see strange symbols on the paper. Are they supposed to mean something?"
- return
+/obj/item/weapon/paper/talisman/examine(mob/user)
+ ..()
+ if(iscultist(user) || user.stat == DEAD)
+ user << "Name: [cultist_name]"
+ user << "Effect: [cultist_desc]"
+ user << "Uses Remaining: [uses]"
-
- attack(mob/living/carbon/T, mob/living/user)
- if(iscultist(user))
- if(imbue == "runestun")
- user.take_organ_damage(10, 0)
- call(/obj/effect/rune/proc/runestun)(T)
- user.drop_item(src)
- qdel(src)
- else
- ..() ///If its some other talisman, use the generic attack code, is this supposed to work this way?
- else
- ..()
-
-
- proc/supply(key)
- if (!src.uses)
- qdel(src)
- return
-
- var/dat = "There are [src.uses] bloody runes on the parchment. "
- dat += "Please choose the chant to be imbued into the fabric of reality. "
- dat += ""
- dat += "N'ath reth sh'yro eth d'raggathnor! - Allows you to summon a new arcane tome. "
- dat += "Sas'so c'arta forbici! - Allows you to move to a rune with the same last word. "
- dat += "Ta'gh fara'qha fel d'amar det! - Allows you to destroy technology in a short range. "
- dat += "Kla'atu barada nikt'o! - Allows you to conceal the runes you placed on the floor. "
- dat += "O bidai nabora se'sma! - Allows you to coordinate with others of your cult. "
- dat += "Fuu ma'jin - Allows you to stun a person by attacking them with the talisman. "
- dat += "Kal om neth - Summons a soul stone "
- dat += "Da A'ig Osk - Summons a construct shell for use with captured souls. It is too large to carry on your person. "
- usr << browse(dat, "window=id_com;size=350x200")
+/obj/item/weapon/paper/talisman/attack_self(mob/living/user)
+ if(!iscultist(user))
+ user << "There are strange, illegible symbols drawn on [src]. Maybe some sort of blueprint?"
return
+ if(invocation)
+ user.whisper(invocation)
+ src.invoke(user)
+ uses--
+ if(uses <= 0)
+ user.drop_item()
+ qdel(src)
+
+/obj/item/weapon/paper/talisman/proc/invoke(mob/living/user)
+ if(health_cost && iscarbon(user))
+ var/mob/living/carbon/C = user
+ C.apply_damage(health_cost, BRUTE, pick("l_arm", "r_arm"))
+
+//Malformed Talisman: If something goes wrong.
+/obj/item/weapon/paper/talisman/malformed
+ cultist_name = "malformed talisman"
+ cultist_desc = "A talisman with gibberish scrawlings. No good can come from invoking this."
+ invocation = "Ra'sha yoka!"
+
+/obj/item/weapon/paper/talisman/malformed/invoke(mob/living/user)
+ user << "You feel a pain in your head. The Geometer is displeased."
+ if(iscarbon(user))
+ var/mob/living/carbon/C = user
+ C.apply_damage(10, BRUTE, "head")
- Topic(href, href_list)
- if(!src) return
- if (usr.stat || usr.restrained() || !in_range(src, usr)) return
+//Supply Talisman: Has a few unique effects. Granted only to starter cultists.
+/obj/item/weapon/paper/talisman/supply
+ cultist_name = "Supply Talisman"
+ cultist_desc = "A multi-use talisman that can create various objects. Intended to increase the cult's strength early on."
+ invocation = null
+ uses = 3
- if (href_list["rune"])
+/obj/item/weapon/paper/talisman/supply/invoke(mob/living/user)
+ var/dat = "There are [uses] bloody runes on the parchment. "
+ dat += "Please choose the chant to be imbued into the fabric of reality. "
+ dat += ""
+ dat += "N'ath reth sh'yro eth d'raggathnor! - Allows you to summon an arcane tome. "
+ dat += "Sas'so c'arta forbici! - Allows you to move to a Rite of Dislocation with the keyword of \"veri\". "
+ dat += "Ta'gh fara'qha fel d'amar det! - Allows you to destroy technology in a short range. "
+ dat += "Kla'atu barada nikt'o! - Allows you to conceal nearby runes. "
+ dat += "Nikt'o barada kla'atu! - Allows you to reveal nearby runes. "
+ dat += "Fuu ma'jin! - Allows you to stun a person by attacking them with the talisman. "
+ dat += "Kal'om neth! - Summons a soul stone, used to capure the spirits of dead or dying humans. "
+ dat += "Daa'ig osk! - Summons a construct shell for use with captured souls. It is too large to carry on your person. "
+ var/datum/browser/popup = new(user, "talisman", "", 800, 600)
+ popup.set_content(dat)
+ popup.open()
+ uses++ //To prevent uses being consumed just by opening it
+ return 1
+
+/obj/item/weapon/paper/talisman/supply/Topic(href, href_list)
+ if(src)
+ if(usr.stat || usr.restrained() || !in_range(src, usr))
+ return
+ if(href_list["rune"])
switch(href_list["rune"])
if("newtome")
- var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(usr)
+ var/obj/item/weapon/paper/talisman/summon_tome/T = new(usr)
usr.put_in_hands(T)
- T.imbue = "newtome"
if("teleport")
- var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(usr)
+ var/obj/item/weapon/paper/talisman/teleport/T = new(usr)
+ T.keyword = "veri"
usr.put_in_hands(T)
- T.imbue = "[pick("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri", "orkan", "allaq")]"
- T.info = "[T.imbue]"
if("emp")
- var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(usr)
+ var/obj/item/weapon/paper/talisman/emp/T = new(usr)
usr.put_in_hands(T)
- T.imbue = "emp"
if("conceal")
- var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(usr)
+ var/obj/item/weapon/paper/talisman/hide_runes/T = new(usr)
usr.put_in_hands(T)
- T.imbue = "conceal"
- if("communicate")
- var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(usr)
+ if("reveal")
+ var/obj/item/weapon/paper/talisman/true_sight/T = new(usr)
usr.put_in_hands(T)
- T.imbue = "communicate"
if("runestun")
- var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(usr)
+ var/obj/item/weapon/paper/talisman/stun/T = new(usr)
usr.put_in_hands(T)
- T.imbue = "runestun"
- if("armor")
- var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(usr)
- usr.put_in_hands(T)
- T.imbue = "armor"
if("soulstone")
- var/obj/item/device/soulstone/T = new /obj/item/device/soulstone(usr)
+ var/obj/item/device/soulstone/T = new(usr)
usr.put_in_hands(T)
if("construct")
new /obj/structure/constructshell(get_turf(usr))
src.uses--
- supply()
+ if(src.uses <= 0)
+ if(iscarbon(usr))
+ var/mob/living/carbon/C = usr
+ C.drop_item()
+ visible_message("[src] crumbles to dust.")
+ qdel(src)
+ return
+ else
return
-/obj/item/weapon/paper/talisman/supply
- imbue = "supply"
- uses = 3
+//Rite of Translocation: Same as rune
+/obj/item/weapon/paper/talisman/teleport
+ cultist_name = "Talisman of Teleportation"
+ cultist_desc = "A single-use talisman that will teleport a user to a random rune of the same keyword."
+ invocation = "Sas'so c'arta forbici!"
+ health_cost = 5
+ var/keyword = "ire"
+
+/obj/item/weapon/paper/talisman/teleport/invoke(mob/living/user)
+ var/list/possible_runes = list()
+ for(var/obj/effect/rune/teleport/R in teleport_runes)
+ if(R.keyword == src.keyword)
+ possible_runes.Add(R)
+ if(!possible_runes.len)
+ user << "There are no Teleport runes with the same keyword!"
+ log_game("Teleportation talisman failed - no teleport runes of the same keyword")
+ uses++ //To prevent deletion
+ return
+ var/chosen_rune = pick(possible_runes)
+ user.visible_message("Dust flows from [user]'s hand, and they disappear in a flash of red light!", \
+ "You speak the words of the talisman and find yourself somewhere else!")
+ if(user.buckled)
+ user.buckled.unbuckle_mob()
+ user.loc = get_turf(chosen_rune)
+
+/obj/item/weapon/paper/talisman/teleport/New()
+ ..()
+ spawn(1) //To give the keyword time to change from the imbue rune
+ info += keyword
+
+/obj/item/weapon/paper/talisman/teleport/examine(mob/user)
+ ..()
+ if(iscultist(user) && keyword)
+ user << "Keyword: [keyword]"
+
+
+//Rite of Knowledge: Same as rune, but has two uses
+/obj/item/weapon/paper/talisman/summon_tome
+ cultist_name = "Talisman of Tome Summoning"
+ cultist_desc = "A two-use talisman that will call untranslated tomes from the archives of the Geometer."
+ invocation = "N'ath reth sh'yro eth d'raggathnor!"
+ health_cost = 1
+
+/obj/item/weapon/paper/talisman/summon_tome/invoke(mob/living/user)
+ user.visible_message("Dust flows from [user]'s hand for a moment.", \
+ "You speak the words of the talisman!")
+ var/obj/item/weapon/tome/T = new(get_turf(user))
+ if(user.put_in_hands(T))
+ user.visible_message("A tome appears in [user]'s hand!", \
+ "An arcane tome materializes in your free hand.")
+ else
+ user.visible_message("A tome appears at [user]'s feet!", \
+ "An arcane tome materialzies at your feet.")
+
+//Rite of Obscurity: Same as rune, but less range
+/obj/item/weapon/paper/talisman/hide_runes
+ cultist_name = "Talisman of Veiling"
+ cultist_desc = "A talisman that will make all runes within a small radius invisible."
+ invocation = "Kla'atu barada nikt'o!"
+ health_cost = 1
+
+/obj/item/weapon/paper/talisman/hide_runes/invoke(mob/living/user)
+ user.visible_message("Dust flows from [user]'s hand.", \
+ "You speak the words of the talisman, veiling nearby runes.")
+ for(var/obj/effect/rune/R in orange(3,user))
+ R.visible_message("[R] fades away.")
+ R.invisibility = INVISIBILITY_OBSERVER
+
+
+//Rite of True Sight: Same as rune, but doesn't work on ghosts
+/obj/item/weapon/paper/talisman/true_sight
+ cultist_name = "Talisman of Revealing"
+ cultist_desc = "A talisman that reveals nearby invisible runes."
+ invocation = "Nikt'o barada kla'atu!"
+ health_cost = 1
+
+/obj/item/weapon/paper/talisman/true_sight/invoke(mob/living/user)
+ user.visible_message("A flash of light shines from [user]'s hand!", \
+ "You speak the words of the talisman, revealing nearby runes.")
+ for(var/obj/effect/rune/R in orange(3,user))
+ R.invisibility = 0
+
+
+//Rite of False Truths: Same as rune
+/obj/item/weapon/paper/talisman/make_runes_fake
+ cultist_name = "Talisman of Disguising"
+ cultist_desc = "A talisman that will make nearby runes appear fake."
+ invocation = "By'o isit!"
+ health_cost = 3
+
+/obj/item/weapon/paper/talisman/make_runes_fake/invoke(mob/living/user)
+ user.visible_message("Dust flows from [user]s hand.", \
+ "You speak the words of the talisman, making nearby runes appear fake.")
+ for(var/obj/effect/rune/R in orange(3,user))
+ R.desc = "A rune drawn in crayon."
+
+
+//Rite of Disruption: Same as rune, halved radius
+/obj/item/weapon/paper/talisman/emp
+ cultist_name = "Talisman of Electromagnets"
+ cultist_desc = "A talisman that will cause a moderately-sized electromagnetic pulse."
+ invocation = "Ta'gh fara'qha fel d'amar det!"
+ health_cost = 5
+
+/obj/item/weapon/paper/talisman/emp/invoke(mob/living/user)
+ user.visible_message("[user]'s hand flashes a bright blue!", \
+ "You speak the words of the talisman, emitting an EMP blast.")
+ empulse(src, 4, 8)
+
+
+//Rite of Disorientation: Stuns and mutes a single target for quite some time
+/obj/item/weapon/paper/talisman/stun
+ cultist_name = "Talisman of Stunning"
+ cultist_desc = "A talisman that will stun and mute a single target. To use, attack target directly."
+ invocation = "Fuu ma'jin!"
+ health_cost = 10 //A lot of health because of how powerful this is
+
+/obj/item/weapon/paper/talisman/stun/attack_self(mob/living/user)
+ user << "To use this talisman, attack the target directly."
+ return
+
+/obj/item/weapon/paper/talisman/stun/attack(mob/living/target, mob/living/user)
+ if(iscultist(user))
+ user.whisper(invocation)
+ user.visible_message("[user] holds up [src], which explodes in a flash of red light!", \
+ "You stun [target] with the talisman!")
+ var/obj/item/weapon/nullrod/N = locate() in target
+ if(N)
+ target.visible_message("[target]'s null rod absorbs the talisman's power!", \
+ "Your null rod absorbs the blinding light!")
+ else
+ target.Weaken(10)
+ target.Stun(10)
+ target.flash_eyes(1,1)
+ if(issilicon(target))
+ var/mob/living/silicon/S = target
+ S.emp_act(1)
+ if(iscarbon(target))
+ var/mob/living/carbon/C = target
+ C.silent += 10
+ user.drop_item()
+ qdel(src)
+ return
+ ..()
+
+
+//Rite of Arming: Equips cultist armor on the user, where available
+/obj/item/weapon/paper/talisman/armor
+ cultist_name = "Talisman of Arming"
+ cultist_desc = "A talisman that will equip the invoker with cultist equipment where available."
+ invocation = "N'ath reth sh'yro eth draggathnor!"
+ health_cost = 3
+
+/obj/item/weapon/paper/talisman/armor/invoke(mob/living/user)
+ user.visible_message("Otherworldy objects suddenly appear on [user]!", \
+ "You speak the words of the talisman, arming yourself!")
+ user.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(user), slot_head)
+ user.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), slot_wear_suit)
+ user.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult/alt(user), slot_shoes)
+ user.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/cultpack(user), slot_back)
+ user.put_in_hands(new /obj/item/weapon/melee/cultblade(user))
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 8986580d810..ec1b2cb906b 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -28,7 +28,6 @@
var/required_enemies = 0
var/recommended_enemies = 0
var/antag_flag = null //preferences flag such as BE_WIZARD that need to be turned on for players to be antag
- var/datum/mind/sacrifice_target = null
var/mob/living/living_antag_player = null
var/list/datum/game_mode/replacementmode = null
var/round_converted = 0 //0: round not converted, 1: round going to convert, 2: round converted
@@ -114,7 +113,7 @@
if(G.reroll_friendly)
usable_modes += G
else
- del(G)
+ qdel(G)
if(!usable_modes)
message_admins("Convert_roundtype failed due to no valid modes to convert to. Please report this error to the Coders.")
@@ -471,17 +470,19 @@
if(M.client && M.client.holder)
M << msg
-/datum/game_mode/proc/printplayer(datum/mind/ply)
+/datum/game_mode/proc/printplayer(datum/mind/ply, fleecheck)
var/text = " [ply.key] was [ply.name] the [ply.assigned_role] and"
if(ply.current)
if(ply.current.stat == DEAD)
- text += " died"
+ text += " died"
else
- text += " survived"
+ text += " survived"
+ if(fleecheck && ply.current.z > ZLEVEL_STATION)
+ text += " while fleeing the station"
if(ply.current.real_name != ply.name)
text += " as [ply.current.real_name]"
else
- text += " had their body destroyed"
+ text += " had their body destroyed"
return text
/datum/game_mode/proc/printobjectives(datum/mind/ply)
@@ -489,9 +490,9 @@
var/count = 1
for(var/datum/objective/objective in ply.objectives)
if(objective.check_completion())
- text += " Objective #[count]: [objective.explanation_text] Success!"
+ text += " Objective #[count]: [objective.explanation_text] Success!"
else
- text += " Objective #[count]: [objective.explanation_text] Fail."
+ text += " Objective #[count]: [objective.explanation_text] Fail."
count++
return text
diff --git a/code/game/gamemodes/gang/dominator.dm b/code/game/gamemodes/gang/dominator.dm
index 898f558d087..62e911426dc 100644
--- a/code/game/gamemodes/gang/dominator.dm
+++ b/code/game/gamemodes/gang/dominator.dm
@@ -4,7 +4,7 @@
icon = 'icons/obj/machines/dominator.dmi'
icon_state = "dominator"
density = 1
- anchored = 1.0
+ anchored = 1
layer = 3.6
var/maxhealth = 200
var/health = 200
@@ -109,7 +109,7 @@
/obj/machinery/dominator/Destroy()
if(operating != -1)
set_broken()
- ..()
+ return ..()
/obj/machinery/dominator/emp_act(severity)
healthcheck(100)
@@ -120,11 +120,11 @@
qdel(src)
return
switch(severity)
- if(1.0)
+ if(1)
qdel(src)
- if(2.0)
+ if(2)
healthcheck(120)
- if(3.0)
+ if(3)
healthcheck(30)
return
diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm
index a0373cc04dc..c641b5f6392 100644
--- a/code/game/gamemodes/gang/gang.dm
+++ b/code/game/gamemodes/gang/gang.dm
@@ -106,6 +106,7 @@ var/list/gang_colors_pool = list("red","orange","yellow","green","blue","purple"
var/obj/item/device/gangtool/gangtool = new(mob)
var/obj/item/weapon/pen/gang/T = new(mob)
var/obj/item/toy/crayon/spraycan/gang/SC = new(mob,gang)
+ var/obj/item/clothing/glasses/hud/security/chameleon/C = new(mob,gang)
var/list/slots = list (
"backpack" = slot_in_backpack,
@@ -139,8 +140,14 @@ var/list/gang_colors_pool = list("red","orange","yellow","green","blue","purple"
. += 1
else
mob << "The territory spraycan in your [where3] can be used to claim areas of the station for your gang. The more territory your gang controls, the more influence you get. All gangsters can use these, so distribute them to grow your influence faster."
- mob.update_icons()
+ var/where4 = mob.equip_in_one_of_slots(C, slots)
+ if (!where4)
+ mob << "Your Syndicate benefactors were unfortunately unable to get you a chameleon security HUD."
+ . += 1
+ else
+ mob << "The chameleon security HUD in your [where4] will help you keep track of who is loyalty-implanted, and unable to be recruited."
+ mob.update_icons()
return .
@@ -241,39 +248,20 @@ var/list/gang_colors_pool = list("red","orange","yellow","green","blue","purple"
/datum/game_mode/proc/auto_declare_completion_gang(datum/gang/winner)
if(gangs.len)
if(!winner)
- world << "The station was [station_was_nuked ? "destroyed!" : "evacuated before a gang could claim it! The station wins!"] "
+ world << "The station was [station_was_nuked ? "destroyed!" : "evacuated before a gang could claim it! The station wins!"] "
else
- world << "The [winner.name] Gang successfully performed a hostile takeover of the station! "
+ world << "The [winner.name] Gang successfully performed a hostile takeover of the station! "
for(var/datum/gang/G in gangs)
- world << " The [G.name] Gang was [winner==G ? "victorious" : "defeated"] with [round((G.territory.len/start_state.num_territories)*100, 1)]% control of the station!"
- world << " The [G.name] Gang Bosses were:"
- gang_membership_report(G.bosses)
- world << " The [G.name] Gangsters were:"
- gang_membership_report(G.gangsters)
- world << " "
-
-
-
-/datum/game_mode/proc/gang_membership_report(list/membership)
- var/text = ""
- for(var/datum/mind/gang_mind in membership)
- text += " [gang_mind.key] was [gang_mind.name] ("
- if(gang_mind.current)
- if(gang_mind.current.stat == DEAD || isbrain(gang_mind.current))
- text += "died"
- else if(gang_mind.current.z > ZLEVEL_STATION)
- text += "fled the station"
- else
- text += "survived"
- if(gang_mind.current.real_name != gang_mind.name)
- text += " as [gang_mind.current.real_name]"
- else
- text += "body destroyed"
- text += ")"
-
- world << text
-
+ var/text = "The [G.name] Gang was [winner==G ? "victorious" : "defeated"] with [round((G.territory.len/start_state.num_territories)*100, 1)]% control of the station!"
+ text += " The [G.name] Gang Bosses were:"
+ for(var/datum/mind/boss in G.bosses)
+ text += printplayer(boss, 1)
+ text += " The [G.name] Gangsters were:"
+ for(var/datum/mind/gangster in G.gangsters)
+ text += printplayer(gangster, 1)
+ text += " "
+ world << text
//////////////////////////////////////////////////////////
//Handles influence, territories, and the victory checks//
diff --git a/code/game/gamemodes/gang/recaller.dm b/code/game/gamemodes/gang/recaller.dm
index c09b45d70cd..cc334c45c4b 100644
--- a/code/game/gamemodes/gang/recaller.dm
+++ b/code/game/gamemodes/gang/recaller.dm
@@ -5,7 +5,7 @@
icon_state = "gangtool-white"
item_state = "walkietalkie"
throwforce = 0
- w_class = 1.0
+ w_class = 1
throw_speed = 3
throw_range = 7
flags = CONDUCT
diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm
index 8f90c400ae9..9a9bf304e4c 100644
--- a/code/game/gamemodes/malfunction/Malf_Modules.dm
+++ b/code/game/gamemodes/malfunction/Malf_Modules.dm
@@ -19,7 +19,7 @@
/datum/AI_Module/large/fireproof_core
- module_name = "Core upgrade"
+ module_name = "Core Upgrade"
mod_pick_name = "coreup"
description = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent."
cost = 50
@@ -36,7 +36,7 @@
src << "Core fireproofed."
/datum/AI_Module/large/upgrade_turrets
- module_name = "AI Turret upgrade"
+ module_name = "AI Turret Upgrade"
mod_pick_name = "turret"
description = "Improves the power and health of all AI turrets. This effect is permanent."
cost = 50
@@ -120,30 +120,35 @@
minor_announce("Automatic system reboot complete. Have a secure day.","Network reset:")
-/datum/AI_Module/large/disable_rcd
- module_name = "RCD disable"
+/datum/AI_Module/large/destroy_rcd
+ module_name = "Destroy RCDs"
mod_pick_name = "rcd"
- description = "Send a specialised pulse to break all RCD devices on the station."
- cost = 50
+ description = "Send a specialised pulse to detonate all hand-held and exosuit Rapid Cconstruction Devices on the station."
+ cost = 25
+ one_time = 1
power_type = /mob/living/silicon/ai/proc/disable_rcd
/mob/living/silicon/ai/proc/disable_rcd()
set category = "Malfunction"
- set name = "Disable RCDs"
+ set name = "Destroy RCDs"
+ set desc = "Detonate all RCDs on the station, while sparing onboard cyborg RCDs."
- if(!canUseTopic())
+ if(!canUseTopic() || malf_cooldown)
return
- for(var/datum/AI_Module/large/disable_rcd/rcdmod in current_modules)
- if(rcdmod.uses > 0)
- rcdmod.uses --
- for(var/obj/item/weapon/rcd/rcd in world)
- rcd.disabled = 1
- for(var/obj/item/mecha_parts/mecha_equipment/rcd/rcd in world)
- rcd.disabled = 1
- src << "Out of uses."
+ for(var/obj/item/RCD in rcd_list)
+ if(!istype(RCD, /obj/item/weapon/rcd/borg)) //Ensures that cyborg RCDs are spared.
+ RCD.audible_message("[RCD] begins to vibrate and buzz loudly!","[RCD] begins vibrating violently!")
+ spawn(50) //5 seconds to get rid of it!
+ if(RCD) //Make sure it still exists (In case of chain-reaction)
+ explosion(RCD, 0, 0, 3, 1, flame_range = 1)
+ qdel(RCD)
+
+ src << "RCD detonation pulse emitted."
+ malf_cooldown = 1
+ spawn(100)
+ malf_cooldown = 0
/datum/AI_Module/large/mecha_domination
module_name = "Viral Mech Domination"
@@ -217,7 +222,7 @@
/datum/AI_Module/small/overload_machine
- module_name = "Machine overload"
+ module_name = "Machine Overload"
mod_pick_name = "overload"
description = "Overloads an electrical machine, causing a small explosion. 2 uses."
uses = 2
@@ -246,7 +251,7 @@
else src << "That's not a machine."
/datum/AI_Module/small/override_machine
- module_name = "Machine override"
+ module_name = "Machine Override"
mod_pick_name = "override"
description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. 4 uses."
uses = 4
diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm
index 3b453e491cc..0cbded335b7 100644
--- a/code/game/gamemodes/malfunction/malfunction.dm
+++ b/code/game/gamemodes/malfunction/malfunction.dm
@@ -285,21 +285,13 @@
/datum/game_mode/proc/auto_declare_completion_malfunction()
if( malf_ai.len || istype(ticker.mode,/datum/game_mode/malfunction) )
var/text = " The malfunctioning AIs were:"
-
for(var/datum/mind/malf in malf_ai)
-
- text += " [malf.key] was [malf.name] ("
+ text += printplayer(malf, 1)
if(malf.current)
- if(malf.current.stat == DEAD)
- text += "deactivated"
- else
- text += "operational"
- if(malf.current.real_name != malf.name)
- text += " as [malf.current.real_name]"
- else
- text += "hardware destroyed"
- text += ")"
- text += " "
-
+ var/module_text_temp = " Purchased modules: " //Added at the end
+ var/mob/living/silicon/ai/AI = malf.current
+ for(var/datum/AI_Module/mod in AI.current_modules)
+ module_text_temp += mod.module_name + " "
+ text += module_text_temp
world << text
return 1
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index f6dd06738a5..2ddf8698ca5 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -121,7 +121,7 @@
/obj/effect/meteor/Destroy()
walk(src,0) //this cancels the walk_towards() proc
- ..()
+ return ..()
/obj/effect/meteor/New()
..()
@@ -165,8 +165,7 @@
/obj/effect/meteor/proc/make_debris()
for(var/throws = dropamt, throws > 0, throws--)
- var/obj/item/O = new meteordrop(get_turf(src))
- O.throw_at(dest, 5, 10)
+ new meteordrop(get_turf(src))
/obj/effect/meteor/proc/meteor_effect(sound=1)
if(sound)
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index ceb70737d79..939cce46b06 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -278,36 +278,18 @@
/datum/game_mode/proc/auto_declare_completion_nuclear()
if( syndicates.len || (ticker && istype(ticker.mode,/datum/game_mode/nuclear)) )
var/text = " The syndicate operatives were:"
-
var/purchases = ""
var/TC_uses = 0
-
for(var/datum/mind/syndicate in syndicates)
-
- text += " [syndicate.key] was [syndicate.name] ("
- if(syndicate.current)
- if(syndicate.current.stat == DEAD)
- text += "died"
- else
- text += "survived"
- if(syndicate.current.real_name != syndicate.name)
- text += " as [syndicate.current.real_name]"
- else
- text += "body destroyed"
- text += ")"
-
+ text += printplayer(syndicate)
for(var/obj/item/device/uplink/H in world_uplinks)
if(H && H.uplink_owner && H.uplink_owner==syndicate.key)
TC_uses += H.used_TC
purchases += H.purchase_log
-
text += " "
-
text += "(Syndicates used [TC_uses] TC) [purchases]"
-
if(TC_uses==0 && station_was_nuked && !are_operatives_dead())
text += ""
-
world << text
return 1
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 7e14fb75726..864a934117f 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -1,8 +1,7 @@
-#define NUKESTATE_INTACT 6
-#define NUKESTATE_OPEN 5
-#define NUKESTATE_OPEN_TRAP 4
-#define NUKESTATE_WIRES_TIED 3
-#define NUKESTATE_CUT_LINES 2
+#define NUKESTATE_INTACT 5
+#define NUKESTATE_UNSCREWED 4
+#define NUKESTATE_PANEL_REMOVED 3
+#define NUKESTATE_WELDED 2
#define NUKESTATE_CORE_EXPOSED 1
#define NUKESTATE_CORE_REMOVED 0
@@ -33,21 +32,20 @@ var/bomb_set
var/obj/item/nuke_core/core = null
var/deconstruction_state = NUKESTATE_INTACT
var/image/lights = null
- var/image/panel = null
var/image/interior = null
- var/image/glow = null
/obj/machinery/nuclearbomb/New()
..()
nuke_list += src
core = new /obj/item/nuke_core(src)
+ SSobj.processing -= core
update_icon()
previous_level = get_security_level()
/obj/machinery/nuclearbomb/selfdestruct
name = "station self-destruct terminal"
desc = "For when it all gets too much to bear. Do not taunt."
- icon = 'icons/obj/machines/bignuke.dmi'
+ icon = 'icons/obj/machines/nuke_terminal.dmi'
icon_state = "nuclearbomb_base"
anchored = 1 //stops it being moved
layer = 4
@@ -65,67 +63,69 @@ var/bomb_set
if(NUKESTATE_INTACT)
if(istype(I, /obj/item/weapon/screwdriver/nuke))
playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1)
- user << "You start removing the front panel's screws..."
- if(do_after(user, 100,target=src))
- deconstruction_state = NUKESTATE_OPEN
- user << "You remove the screws and the front panel slides open."
+ user << "You start removing [src]'s front panel's screws..."
+ if(do_after(user, 60,target=src))
+ deconstruction_state = NUKESTATE_UNSCREWED
+ user << "You remove the screws from [src]'s front panel."
update_icon()
return
- if(NUKESTATE_OPEN,NUKESTATE_OPEN_TRAP)
- if((deconstruction_state == NUKESTATE_OPEN) && istype(I, /obj/item/weapon/wirecutters))
- playsound(loc, 'sound/effects/sparks4.ogg', 100, 1)
- playsound(loc, 'sound/effects/EMPulse.ogg', 100, 1)
- user << "You must have cut the wrong wire!"
- for(var/mob/living/L in range(5,src))
- L.irradiate(200)
- deconstruction_state = NUKESTATE_OPEN_TRAP //cant cut wires no more
- else
- if(istype(I, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/S = I
- user << "You start tying the wires..."
- if(do_after(user,30,target=src))
- if(S.use(15))
- user << "You tie the wires with some cable, clearing the insides of [src]."
- deconstruction_state = NUKESTATE_WIRES_TIED
- update_icon()
- else
- user << "You need more cable to do that."
- else
- user << "You can't do anything with this tangle of cables in the way."
- return
- if(NUKESTATE_WIRES_TIED)
- if(istype(I, /obj/item/weapon/pen))
- user << "You start drawing cut lines..."
+ if(NUKESTATE_UNSCREWED)
+ if(istype(I, /obj/item/weapon/crowbar))
+ user << "You start removing [src]'s front panel..."
+ playsound(loc, 'sound/items/Crowbar.ogg', 100, 1)
if(do_after(user,30,target=src))
- user << "You draw cut lines inside [src]."
- deconstruction_state = NUKESTATE_CUT_LINES
+ user << "You remove [src]'s front panel."
+ deconstruction_state = NUKESTATE_PANEL_REMOVED
update_icon()
return
- if(NUKESTATE_CUT_LINES)
+ if(NUKESTATE_PANEL_REMOVED)
if(istype(I, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/welder = I
playsound(loc, 'sound/items/Welder.ogg', 100, 1)
- user << "You start cutting into [src]'s warhead..."
+ user << "You start cutting [src]'s inner plate..."
if(welder.remove_fuel(1,user))
- if(do_after(user,50,target=src))
- playsound(loc, 'sound/items/Deconstruct.ogg', 100, 1)
- user << "You cut into [src]'s warhead. You can see the core's green glow."
- deconstruction_state = NUKESTATE_CORE_EXPOSED
+ if(do_after(user,80,target=src))
+ user << "You cut [src]'s inner plate."
+ deconstruction_state = NUKESTATE_WELDED
update_icon()
- SSobj.processing += core
return
+ if(NUKESTATE_WELDED)
+ if(istype(I, /obj/item/weapon/crowbar))
+ user << "You start prying off [src]'s inner plate..."
+ playsound(loc, 'sound/items/Crowbar.ogg', 100, 1)
+ if(do_after(user,50,target=src))
+ user << "You pry off [src]'s inner plate. You can see the core's green glow!"
+ deconstruction_state = NUKESTATE_CORE_EXPOSED
+ update_icon()
+ SSobj.processing += core
if(NUKESTATE_CORE_EXPOSED)
if(istype(I, /obj/item/nuke_core_container))
var/obj/item/nuke_core_container/core_box = I
user << "You start loading the plutonium core into [core_box]..."
if(do_after(user,50,target=src))
- if(core_box.load(core,src))
+ if(core_box.load(core, user))
user << "You load the plutonium core into [core_box]."
deconstruction_state = NUKESTATE_CORE_REMOVED
update_icon()
+ core = null
else
user << "You fail to load the plutonium core into [core_box]. [core_box] has already been used!"
return
+ if(istype(I, /obj/item/stack/sheet/metal))
+ var/obj/item/stack/sheet/metal/M = I
+ if(M.amount >= 20)
+ user << "You begin repairing [src]'s inner metal plate..."
+ if(do_after(user, 100, target=src))
+ if(M.use(20))
+ user << "You repair [src]'s inner metal plate. The radiation is contained."
+ deconstruction_state = NUKESTATE_PANEL_REMOVED
+ SSobj.processing -= core
+ update_icon()
+ else
+ user << "You need more metal to do that!"
+ else
+ user << "You need more metal to do that!"
+ return
else
..()
@@ -143,6 +143,7 @@ var/bomb_set
if(deconstruction_state == NUKESTATE_INTACT)
switch(get_nuke_state())
if(NUKE_OFF_LOCKED, NUKE_OFF_UNLOCKED)
+ icon_state = "nuclearbomb_base"
update_icon_interior()
update_icon_lights()
if(NUKE_ON_TIMING)
@@ -152,51 +153,39 @@ var/bomb_set
overlays.Cut()
icon_state = "nuclearbomb_exploding"
else
+ icon_state = "nuclearbomb_base"
update_icon_interior()
update_icon_lights()
/obj/machinery/nuclearbomb/proc/update_icon_interior()
overlays -= interior
- overlays -= glow
switch(deconstruction_state)
- if(NUKESTATE_OPEN_TRAP,NUKESTATE_OPEN)
- glow = null
+ if(NUKESTATE_UNSCREWED)
+ interior = image(icon,"panel-unscrewed")
+ if(NUKESTATE_PANEL_REMOVED)
interior = image(icon,"panel-removed")
- if(NUKESTATE_CORE_REMOVED,NUKESTATE_CUT_LINES,NUKESTATE_WIRES_TIED)
- glow = null
- interior = image(icon,"wires-sorted")
+ if(NUKESTATE_WELDED)
+ interior = image(icon,"plate-welded")
if(NUKESTATE_CORE_EXPOSED)
- glow = image(icon,"core-exposed")
- interior = image(icon,"wires-sorted")
+ interior = image(icon,"plate-removed")
+ if(NUKESTATE_CORE_REMOVED)
+ interior = image(icon,"core-removed")
if(NUKESTATE_INTACT)
- glow = null
- interior = image(icon,"panel-overlay")
+ interior = null
overlays += interior
- overlays += glow
/obj/machinery/nuclearbomb/proc/update_icon_lights()
overlays -= lights
- overlays -= panel
- panel = null
switch(get_nuke_state())
if(NUKE_OFF_LOCKED)
- lights = image(icon,"lights-off")
- if(deconstruction_state != NUKESTATE_INTACT)
- panel = image(icon,"panel-removed-blue")
+ lights = null
if(NUKE_OFF_UNLOCKED)
lights = image(icon,"lights-safety")
- if(deconstruction_state != NUKESTATE_INTACT)
- panel = image(icon,"panel-removed-blue")
if(NUKE_ON_TIMING)
lights = image(icon,"lights-timing")
- if(deconstruction_state != NUKESTATE_INTACT)
- panel = image(icon,"panel-removed-timing")
if(NUKE_ON_EXPLODING)
lights = image(icon,"lights-exploding")
- if(deconstruction_state != NUKESTATE_INTACT)
- panel = image(icon,"panel-removed-exploding")
overlays += lights
- overlays += panel
/obj/machinery/nuclearbomb/process()
if (timing > 0)
@@ -327,7 +316,7 @@ var/bomb_set
return
/obj/machinery/nuclearbomb/blob_act()
- if (timing == -1.0)
+ if (timing == -1)
return
else
return ..()
@@ -391,7 +380,7 @@ This is here to make the tiles around the station mininuke change when it's arme
/obj/machinery/nuclearbomb/selfdestruct/proc/SetTurfs()
if(loc == initial(loc))
for(var/turf/simulated/floor/bluegrid/T in orange(src, 1))
- T.icon_state = (timing ? "rcircuitanim" : "gcircuit")
+ T.icon_state = (timing ? "rcircuitanim" : "bcircuit")
/obj/machinery/nuclearbomb/selfdestruct/set_anchor()
return
@@ -407,7 +396,7 @@ This is here to make the tiles around the station mininuke change when it's arme
icon = 'icons/obj/items.dmi'
icon_state = "nucleardisk"
item_state = "card-id"
- w_class = 1.0
+ w_class = 1
/obj/item/weapon/disk/nuclear/New()
..()
diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm
index 2d145a525d4..e3ce3bf5ea1 100644
--- a/code/game/gamemodes/nuclear/pinpointer.dm
+++ b/code/game/gamemodes/nuclear/pinpointer.dm
@@ -4,7 +4,7 @@
icon_state = "pinoff"
flags = CONDUCT
slot_flags = SLOT_BELT
- w_class = 2.0
+ w_class = 2
item_state = "electronic"
throw_speed = 3
throw_range = 7
@@ -14,7 +14,7 @@
/obj/item/weapon/pinpointer/Destroy()
active = 0
- ..()
+ return ..()
/obj/item/weapon/pinpointer/attack_self()
if(!active)
@@ -147,11 +147,11 @@
var/DNAstring = input("Input DNA string to search for." , "Please Enter String." , "")
if(!DNAstring)
return
- for(var/mob/living/carbon/M in mob_list)
- if(!M.dna)
+ for(var/mob/living/carbon/C in mob_list)
+ if(!C.dna)
continue
- if(M.dna.unique_enzymes == DNAstring)
- target = M
+ if(C.dna.unique_enzymes == DNAstring)
+ target = C
break
return attack_self()
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index dd3b338b299..cb4d5ace22f 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -33,11 +33,26 @@
update_explanation_text()
return target
-/datum/objective/proc/find_target_by_role(role, role_type=0)//Option sets either to check assigned role or special role. Default to assigned.
+/datum/objective/proc/find_target_by_role(role, role_type=0, invert=0)//Option sets either to check assigned role or special role. Default to assigned., invert inverts the check, eg: "Don't choose a Ling"
for(var/datum/mind/possible_target in ticker.minds)
- if((possible_target != owner) && ishuman(possible_target.current) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role) )
- target = possible_target
- break
+ if((possible_target != owner) && ishuman(possible_target.current))
+ var/is_role = 0
+ if(role_type)
+ if(possible_target.special_role == role)
+ is_role++
+ else
+ if(possible_target.assigned_role == role)
+ is_role++
+
+ if(invert)
+ if(is_role)
+ continue
+ target = possible_target
+ break
+ else if(is_role)
+ target = possible_target
+ break
+
update_explanation_text()
/datum/objective/proc/update_explanation_text()
@@ -50,9 +65,10 @@
dangerrating = 10
martyr_compatible = 1
-/datum/objective/assassinate/find_target_by_role(role, role_type=0)
- target_role_type = role_type
- ..(role, role_type)
+/datum/objective/assassinate/find_target_by_role(role, role_type=0, invert=0)
+ if(!invert)
+ target_role_type = role_type
+ ..()
return target
/datum/objective/assassinate/check_completion()
@@ -70,14 +86,14 @@
explanation_text = "Free Objective"
-
/datum/objective/mutiny
var/target_role_type=0
martyr_compatible = 1
-/datum/objective/mutiny/find_target_by_role(role, role_type=0)
- target_role_type = role_type
- ..(role, role_type)
+/datum/objective/mutiny/find_target_by_role(role, role_type=0,invert=0)
+ if(!invert)
+ target_role_type = role_type
+ ..()
return target
/datum/objective/mutiny/check_completion()
@@ -104,9 +120,10 @@
dangerrating = 5
martyr_compatible = 1
-/datum/objective/maroon/find_target_by_role(role, role_type=0)
- target_role_type = role_type
- ..(role, role_type)
+/datum/objective/maroon/find_target_by_role(role, role_type=0, invert=0)
+ if(!invert)
+ target_role_type = role_type
+ ..()
return target
/datum/objective/maroon/check_completion()
@@ -129,9 +146,10 @@
var/target_role_type=0
dangerrating = 20
-/datum/objective/debrain/find_target_by_role(role, role_type=0)
- target_role_type = role_type
- ..(role, role_type)
+/datum/objective/debrain/find_target_by_role(role, role_type=0, invert=0)
+ if(!invert)
+ target_role_type = role_type
+ ..()
return target
/datum/objective/debrain/check_completion()
@@ -162,9 +180,10 @@
dangerrating = 10
martyr_compatible = 1
-/datum/objective/protect/find_target_by_role(role, role_type=0)
- target_role_type = role_type
- ..(role, role_type)
+/datum/objective/protect/find_target_by_role(role, role_type=0, invert=0)
+ if(!invert)
+ target_role_type = role_type
+ ..()
return target
/datum/objective/protect/check_completion()
@@ -205,9 +224,8 @@
for(var/mob/living/player in player_list)
if(player.mind && player.mind != owner)
if(player.stat != DEAD)
- switch(player.type)
- if(/mob/living/silicon/ai, /mob/living/silicon/pai)
- continue
+ if(istype(player, /mob/living/silicon)) //Borgs are technically dead anyways
+ continue
if(get_area(player) == A)
if(!player.mind.special_role && !istype(get_turf(player.mind.current), /turf/simulated/floor/plasteel/shuttle/red))
return 0
@@ -229,9 +247,8 @@
for(var/mob/living/player in player_list) //Make sure nobody else is onboard
if(player.mind && player.mind != owner)
if(player.stat != DEAD)
- switch(player.type)
- if(/mob/living/silicon/ai, /mob/living/silicon/pai)
- continue
+ if(istype(player, /mob/living/silicon))
+ continue
if(get_area(player) == A)
if(player.real_name != owner.current.real_name && !istype(get_turf(player.mind.current), /turf/simulated/floor/plasteel/shuttle/red))
return 0
@@ -239,9 +256,8 @@
for(var/mob/living/player in player_list) //Make sure at least one of you is onboard
if(player.mind && player.mind != owner)
if(player.stat != DEAD)
- switch(player.type)
- if(/mob/living/silicon/ai, /mob/living/silicon/pai)
- continue
+ if(istype(player, /mob/living/silicon))
+ continue
if(get_area(player) == A)
if(player.real_name == owner.current.real_name && !istype(get_turf(player.mind.current), /turf/simulated/floor/plasteel/shuttle/red))
return 1
@@ -591,7 +607,7 @@ var/global/list/possible_items_special = list()
return target_amount
/datum/objective/absorb/check_completion()
- if(owner && owner.changeling && owner.changeling.absorbed_dna && (owner.changeling.absorbedcount >= target_amount))
+ if(owner && owner.changeling && owner.changeling.stored_profiles && (owner.changeling.absorbedcount >= target_amount))
return 1
else
return 0
@@ -640,3 +656,175 @@ var/global/list/possible_items_special = list()
return 0
+
+////////////////////////////////
+// Changeling team objectives //
+////////////////////////////////
+
+/datum/objective/changeling_team_objective //Abstract type
+ martyr_compatible = 0 //Suicide is not teamwork!
+ explanation_text = "Changeling Friendship!"
+ var/min_lings = 3 //Minimum amount of lings for this team objective to be possible
+ var/escape_objective_compatible = FALSE
+
+
+//Impersonate department
+//Picks as many people as it can from a department (Security,Engineer,Medical,Science)
+//and tasks the lings with killing and replacing them
+/datum/objective/changeling_team_objective/impersonate_department
+ explanation_text = "Ensure X derpartment are killed, impersonated, and replaced by Changelings"
+ var/command_staff_only = FALSE //if this is true, it picks command staff instead
+ var/list/department_minds = list()
+ var/list/department_real_names = list()
+ var/department_string = ""
+
+
+/datum/objective/changeling_team_objective/impersonate_department/proc/get_department_staff()
+ department_minds = list()
+ department_real_names = list()
+
+ var/list/departments = list("Head of Security","Research Director","Chief Engineer","Chief Medical Officer")
+ var/department_head = pick(departments)
+ switch(department_head)
+ if("Head of Security")
+ department_string = "security"
+ if("Research Director")
+ department_string = "science"
+ if("Chief Engineer")
+ department_string = "engineering"
+ if("Chief Medical Officer")
+ department_string = "medical"
+
+ var/ling_count = ticker.mode.changelings
+
+ for(var/datum/mind/M in ticker.minds)
+ if(M in ticker.mode.changelings)
+ continue
+ if(department_head in get_department_heads(M.assigned_role))
+ if(ling_count)
+ ling_count--
+ department_minds += M
+ department_real_names += M.current.real_name
+ else
+ break
+
+ if(!department_minds.len)
+ log_game("[type] has failed to find department staff, and has removed itself. the round will continue normally")
+ owner.objectives -= src
+ qdel(src)
+ return
+
+
+/datum/objective/changeling_team_objective/impersonate_department/proc/get_heads()
+ department_minds = list()
+ department_real_names = list()
+
+ //Needed heads is between min_lings and the maximum possible amount of command roles
+ //So at the time of writing, rand(3,6), it's also capped by the amount of lings there are
+ //Because you can't fill 6 head roles with 3 lings
+
+ var/needed_heads = rand(min_lings,command_positions.len)
+ needed_heads = min(ticker.mode.changelings.len,needed_heads)
+
+ var/list/heads = ticker.mode.get_living_heads()
+ for(var/datum/mind/head in heads)
+ if(head in ticker.mode.changelings) //Looking at you HoP.
+ continue
+ if(needed_heads)
+ department_minds += head
+ department_real_names += head.current.real_name
+ needed_heads--
+ else
+ break
+
+ if(!department_minds.len)
+ log_game("[type] has failed to find department heads, and has removed itself. the round will continue normally")
+ owner.objectives -= src
+ qdel(src)
+ return
+
+
+/datum/objective/changeling_team_objective/impersonate_department/New(var/text)
+ ..()
+ if(command_staff_only)
+ get_heads()
+ else
+ get_department_staff()
+
+ update_explanation_text()
+
+
+/datum/objective/changeling_team_objective/impersonate_department/update_explanation_text()
+ ..()
+ if(!department_real_names.len || !department_minds.len)
+ explanation_text = "Free Objective"
+ return //Something fucked up, give them a win
+
+ if(command_staff_only)
+ explanation_text = "Ensure changelings impersonate and escape as the following heads of staff: "
+ else
+ explanation_text = "Ensure changelings impersonate and escape as the following members of \the [department_string] department: "
+
+ var/first = 1
+ for(var/datum/mind/M in department_minds)
+ var/string = "[M.name] the [M.assigned_role]"
+ if(!first)
+ string = ", [M.name] the [M.assigned_role]"
+ else
+ first--
+ explanation_text += string
+
+ if(command_staff_only)
+ explanation_text += ", while the real heads are dead. This is a team objective."
+ else
+ explanation_text += ", while the real members are dead. This is a team objective."
+
+
+/datum/objective/changeling_team_objective/impersonate_department/check_completion()
+ if(!department_real_names.len || !department_minds.len)
+ return 1 //Something fucked up, give them a win
+
+ var/list/check_names = department_real_names.Copy()
+
+ //Check each department member's mind to see if any of them made it to centcomm alive, if they did it's an automatic fail
+ for(var/datum/mind/M in department_minds)
+ if(M in ticker.mode.changelings) //Lings aren't picked for this, but let's be safe
+ continue
+
+ if(M.current)
+ var/turf/mloc = get_turf(M.current)
+ if(mloc.onCentcom() && (M.current.stat != DEAD))
+ return 0 //A Non-ling living target got to centcomm, fail
+
+ //Check each staff member has been replaced, by cross referencing changeling minds, changeling current dna, the staff minds and their original DNA names
+ var/success = 0
+ changelings:
+ for(var/datum/mind/changeling in ticker.mode.changelings)
+ if(success >= department_minds.len) //We did it, stop here!
+ return 1
+ if(ishuman(changeling.current))
+ var/mob/living/carbon/human/H = changeling.current
+ var/turf/cloc = get_turf(changeling.current)
+ if(cloc && cloc.onCentcom() && (changeling.current.stat != DEAD)) //Living changeling on centcomm....
+ for(var/name in check_names) //Is he (disguised as) one of the staff?
+ if(H.dna.real_name == name)
+ check_names -= name //This staff member is accounted for, remove them, so the team don't succeed by escape as 7 of the same engineer
+ success++ //A living changeling staff member made it to centcomm
+ continue changelings
+
+ if(success >= department_minds.len)
+ return 1
+ return 0
+
+
+
+
+//A subtype of impersonate_derpartment
+//This subtype always picks as many command staff as it can (HoS,HoP,Cap,CE,CMO,RD)
+//and tasks the lings with killing and replacing them
+/datum/objective/changeling_team_objective/impersonate_department/impersonate_heads
+ explanation_text = "Have X or more heads of staff escape on the shuttle disguised as heads, while the real heads are dead"
+ command_staff_only = TRUE
+
+
+
diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm
index f2b121456ff..882accb90c0 100644
--- a/code/game/gamemodes/revolution/revolution.dm
+++ b/code/game/gamemodes/revolution/revolution.dm
@@ -126,8 +126,9 @@
mob.dna.remove_mutation(CLOWNMUT)
- var/obj/item/device/flash/T = new(mob)
+ var/obj/item/device/assembly/flash/T = new(mob)
var/obj/item/toy/crayon/spraycan/R = new(mob)
+ var/obj/item/clothing/glasses/hud/security/chameleon/C = new(mob)
var/list/slots = list (
"backpack" = slot_in_backpack,
@@ -137,10 +138,16 @@
"right hand" = slot_r_hand,
)
var/where = mob.equip_in_one_of_slots(T, slots)
+ var/where2 = mob.equip_in_one_of_slots(C, slots)
mob.equip_in_one_of_slots(R,slots)
mob.update_icons()
+ if (!where2)
+ mob << "The Syndicate were unfortunately unable to get you a chameleon security HUD."
+ else
+ mob << "The chameleon security HUD in your [where2] will help you keep track of who is loyalty-implanted, and unable to be recruited."
+
if (!where)
mob << "The Syndicate were unfortunately unable to get you a flash."
else
@@ -314,16 +321,15 @@
/datum/game_mode/revolution/declare_completion()
if(finished == 1)
feedback_set_details("round_end_result","win - heads killed")
- world << "The heads of staff were killed or exiled! The revolutionaries win!"
+ world << "The heads of staff were killed or exiled! The revolutionaries win!"
else if(finished == 2)
feedback_set_details("round_end_result","loss - rev heads killed")
- world << "The heads of staff managed to stop the revolution!"
+ world << "The heads of staff managed to stop the revolution!"
..()
return 1
/datum/game_mode/proc/auto_declare_completion_revolution()
var/list/targets = list()
-
if(head_revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution))
var/num_revs = 0
var/num_survivors = 0
@@ -333,78 +339,28 @@
if(survivor.mind)
if((survivor.mind in head_revolutionaries) || (survivor.mind in revolutionaries))
num_revs++
-
if(num_survivors)
world << "[TAB]Command's Approval Rating: [100 - round((num_revs/num_survivors)*100, 0.1)]%" // % of loyal crew
-
var/text = " The head revolutionaries were:"
-
for(var/datum/mind/headrev in head_revolutionaries)
- text += " [headrev.key] was [headrev.name] ("
- if(headrev.current)
- if(headrev.current.stat == DEAD)
- text += "died"
- else if(headrev.current.z > ZLEVEL_STATION)
- text += "fled the station"
- else
- text += "survived the revolution"
- if(headrev.current.real_name != headrev.name)
- text += " as [headrev.current.real_name]"
- else
- text += "body destroyed"
- text += ")"
-
- for(var/datum/objective/mutiny/objective in headrev.objectives)
- targets |= objective.target
+ text += printplayer(headrev, 1)
text += " "
-
world << text
if(revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution))
var/text = " The revolutionaries were:"
-
for(var/datum/mind/rev in revolutionaries)
- text += " [rev.key] was [rev.name] ("
- if(rev.current)
- if(rev.current.stat == DEAD || isbrain(rev.current))
- text += "died"
- else if(rev.current.z > ZLEVEL_STATION)
- text += "fled the station"
- else
- text += "survived the revolution"
- if(rev.current.real_name != rev.name)
- text += " as [rev.current.real_name]"
- else
- text += "body destroyed"
- text += ")"
+ text += printplayer(rev, 1)
text += " "
-
world << text
-
if( head_revolutionaries.len || revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution) )
var/text = " The heads of staff were:"
-
var/list/heads = get_all_heads()
for(var/datum/mind/head in heads)
var/target = (head in targets)
if(target)
- text += ""
- text += " [head.key] was [head.name] ("
- if(head.current)
- if(head.current.stat == DEAD || isbrain(head.current))
- text += "died"
- else if(head.current.z > ZLEVEL_STATION)
- text += "fled the station"
- else
- text += "survived the revolution"
- if(head.current.real_name != head.name)
- text += " as [head.current.real_name]"
- else
- text += "body destroyed"
- text += ")"
- if(target)
- text += ""
+ text += "Target"
+ text += printplayer(head, 1)
text += " "
-
world << text
diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm
index c55ada2a766..f07cfcee824 100644
--- a/code/game/gamemodes/sandbox/h_sandbox.dm
+++ b/code/game/gamemodes/sandbox/h_sandbox.dm
@@ -212,7 +212,7 @@ var/hsboxspawn = 1
if("hsbrcd")
if(!hsboxspawn) return
- new/obj/item/weapon/rcd{matter=30;canRwall=1}(usr.loc)
+ new/obj/item/weapon/rcd/combat(usr.loc)
//
// New sandbox airlock maker
diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm
index 2e5721b5fe7..e2a6af4e114 100644
--- a/code/game/gamemodes/setupgame.dm
+++ b/code/game/gamemodes/setupgame.dm
@@ -1,4 +1,4 @@
-/datum/subsystem/ticker/proc/setupGenetics()
+/datum/subsystem/objects/proc/setupGenetics()
var/list/avnums = new /list(DNA_STRUC_ENZYMES_BLOCKS)
for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++)
avnums[i] = i
diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm
index 37223bac1d2..39b72b87b2c 100644
--- a/code/game/gamemodes/shadowling/shadowling.dm
+++ b/code/game/gamemodes/shadowling/shadowling.dm
@@ -1,6 +1,7 @@
#define LIGHT_DAM_THRESHOLD 4
#define LIGHT_HEAL_THRESHOLD 2
-#define LIGHT_DAMAGE_TAKEN 10
+#define LIGHT_DAMAGE_TAKEN 7
+
/*
SHADOWLING: A gamemode based on previously-run events
@@ -14,7 +15,7 @@ The game will end under two conditions:
Shadowling strengths:
- The dark
- - Hard vacuum (They are not affected by it)
+ - Hard vacuum (They are not affected by it, but are affected by starlight!)
- Their thralls who are not harmed by the light
- Stealth
@@ -22,8 +23,7 @@ Shadowling weaknesses:
- The light
- Fire
- Enemy numbers
- - Lasers (Lasers are concentrated light and do more damage)
- - Flashbangs (High stun and high burn damage; if the light stuns humans, you bet your ass it'll hurt the shadowling very much!)
+ - Burn-based weapons and items (flashbangs, lasers, etc.)
Shadowlings start off disguised as normal crew members, and they only have two abilities: Hatch and Enthrall.
They can still enthrall and perhaps complete their objectives in this form.
@@ -76,7 +76,7 @@ Made by Xhuis
/datum/game_mode/shadowling/announce()
world << "The current game mode is - Shadowling!"
- world << "There are alien shadowlings on the station. Crew: Kill the shadowlings before they can eat or enthrall the crew. Shadowlings: Enthrall the crew while remaining in hiding."
+ world << "There are alien shadowlings on the station. Crew: Kill the shadowlings before they can enthrall the crew. Shadowlings: Enthrall the crew while remaining in hiding."
/datum/game_mode/shadowling/pre_setup()
if(config.protect_roles_from_antagonist)
@@ -104,7 +104,7 @@ Made by Xhuis
log_game("[shadow.key] (ckey) has been selected as a Shadowling.")
sleep(10)
shadow.current << " "
- shadow.current << "You are a shadowling!"
+ shadow.current << "You are a shadowling!"
greet_shadow(shadow)
finalize_shadowling(shadow)
process_shadow_objectives(shadow)
@@ -113,9 +113,9 @@ Made by Xhuis
return
/datum/game_mode/proc/greet_shadow(datum/mind/shadow)
- shadow.current << "Currently, you are disguised as an employee aboard [world.name]."
+ shadow.current << "Currently, you are disguised as an employee aboard [station_name()]]."
shadow.current << "In your limited state, you have three abilities: Enthrall, Hatch, and Hivemind Commune."
- shadow.current << "Any other shadowlings are you allies. You must assist them as they shall assist you."
+ shadow.current << "Any other shadowlings are your allies. You must assist them as they shall assist you."
shadow.current << "If you are new to shadowling, or want to read about abilities, check the wiki page at https://tgstation13.org/wiki/Shadowling "
@@ -166,10 +166,8 @@ Made by Xhuis
thralls.Remove(thrall_mind)
thrall_mind.current.attack_log += "\[[time_stamp()]\] Dethralled"
thrall_mind.special_role = null
- thrall_mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_shadowling_hivemind)
- thrall_mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_glare)
- thrall_mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk)
- thrall_mind.remove_spell(/obj/effect/proc_holder/spell/targeted/thrall_vision)
+ for(var/obj/effect/proc_holder/spell/S in thrall_mind.spell_list)
+ thrall_mind.remove_spell(S)
if(kill && ishuman(thrall_mind.current)) //If dethrallization surgery fails, kill the mob as well as dethralling them
var/mob/living/carbon/human/H = thrall_mind.current
H.visible_message("[H] jerks violently and falls still.", \
@@ -186,6 +184,30 @@ Made by Xhuis
under their command...")
return 1
+/datum/game_mode/proc/remove_shadowling(datum/mind/ling_mind)
+ if(!istype(ling_mind) || !(ling_mind in shadows)) return 0
+ update_shadow_icons_removed(ling_mind)
+ shadows.Remove(ling_mind)
+ ling_mind.current.attack_log += "\[[time_stamp()]\] Deshadowlinged"
+ ling_mind.special_role = null
+ for(var/obj/effect/proc_holder/spell/S in ling_mind.spell_list)
+ ling_mind.remove_spell(S)
+ var/mob/living/M = ling_mind.current
+ if(issilicon(M))
+ M.audible_message("[M] lets out a short blip.", \
+ "You have been turned into a robot! You are no longer a shadowling! Though you try, you cannot remember anything about your time as one...")
+ else
+ M.visible_message("[M] screams and contorts!", \
+ "THE LIGHT-- YOUR MIND-- BURNS--")
+ spawn(30)
+ if(!M || qdeleted(M))
+ return
+ M.visible_message("[M] suddenly bloats and explodes!", \
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA----")
+ playsound(M, 'sound/magic/Disintegrate.ogg', 100, 1)
+ M.gib()
+
+
/datum/game_mode/shadowling/proc/check_shadow_victory()
var/success = 0 //Did they win?
if(shadow_objectives.Find("enthrall"))
@@ -195,13 +217,13 @@ Made by Xhuis
/datum/game_mode/shadowling/declare_completion()
if(check_shadow_victory() && SSshuttle.emergency.mode >= SHUTTLE_ESCAPE) //Doesn't end instantly - this is hacky and I don't know of a better way ~X
- world << "The shadowlings have ascended and taken over the station!"
+ world << "The shadowlings have ascended and taken over the station!"
else if(shadowling_dead && !check_shadow_victory()) //If the shadowlings have ascended, they can not lose the round
- world << "The shadowlings have been killed by the crew!"
+ world << "The shadowlings have been killed by the crew!"
else if(!check_shadow_victory() && SSshuttle.emergency.mode >= SHUTTLE_ESCAPE)
- world << "The crew escaped the station before the shadowlings could ascend!"
+ world << "The crew escaped the station before the shadowlings could ascend!"
else
- world << "The shadowlings have failed!"
+ world << "The shadowlings have failed!"
..()
return 1
@@ -232,8 +254,8 @@ Made by Xhuis
id = "shadowling"
say_mod = "chitters"
specflags = list(NOBREATH,NOBLOOD,RADIMMUNE,NOGUNS) //Can't use guns due to muzzle flash
- burnmod = 2 //2x burn damage lel
- heatmod = 2
+ burnmod = 1.5 //1.5x burn damage, 2x is excessive
+ heatmod = 1.5
/datum/species/shadow/ling/spec_life(mob/living/carbon/human/H)
if(!H.weakeyes) H.weakeyes = 1 //Makes them more vulnerable to flashes and flashbangs
@@ -244,7 +266,7 @@ Made by Xhuis
light_amount = T.get_lumcount()
if(light_amount > LIGHT_DAM_THRESHOLD && !H.incorporeal_move) //Can survive in very small light levels. Also doesn't take damage while incorporeal, for shadow walk purposes
H.take_overall_damage(0, LIGHT_DAMAGE_TAKEN)
- H << "The light burns you!"
+ H << "The light burns you!" //Message spam to say "GET THE FUCK OUT"
H << 'sound/weapons/sear.ogg'
else if (light_amount < LIGHT_HEAL_THRESHOLD)
H.heal_overall_damage(5,5)
@@ -254,6 +276,29 @@ Made by Xhuis
H.SetWeakened(0)
H.SetStunned(0)
+/datum/species/shadow/ling/lesser //Empowered thralls. Obvious, but powerful
+ name = "Lesser Shadowling"
+ id = "l_shadowling"
+ say_mod = "chitters"
+ specflags = list(NOBREATH,NOBLOOD,RADIMMUNE)
+ burnmod = 1.1
+ heatmod = 1.1
+
+/datum/species/shadow/ling/lesser/spec_life(mob/living/carbon/human/H)
+ if(!H.weakeyes) H.weakeyes = 1
+ var/light_amount = 0
+ H.nutrition = NUTRITION_LEVEL_WELL_FED //i aint never get hongry
+ if(isturf(H.loc))
+ var/turf/T = H.loc
+ light_amount = T.get_lumcount()
+ if(light_amount > LIGHT_DAM_THRESHOLD && !H.incorporeal_move)
+ H.take_overall_damage(0, LIGHT_DAMAGE_TAKEN/2)
+ else if (light_amount < LIGHT_HEAL_THRESHOLD)
+ H.heal_overall_damage(2,2)
+ H.adjustToxLoss(-5)
+ H.adjustBrainLoss(-25)
+ H.adjustCloneLoss(-1)
+
/datum/game_mode/proc/update_shadow_icons_added(datum/mind/shadow_mind)
var/datum/atom_hud/antag/shadow_hud = huds[ANTAG_HUD_SHADOW]
shadow_hud.join_hud(shadow_mind.current)
diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm
index 9a8b8ab9482..fbcc07e8296 100644
--- a/code/game/gamemodes/shadowling/shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm
@@ -1,6 +1,9 @@
+#define EMPOWERED_THRALL_LIMIT 5
+
/obj/effect/proc_holder/spell/proc/shadowling_check(var/mob/living/carbon/human/H)
if(!H || !istype(H)) return
if(H.dna.species.id == "shadowling" && is_shadow(H)) return 1
+ if(H.dna.species.id == "l_shadowling" && is_thrall(H)) return 1
if(!is_shadow_or_thrall(usr)) usr << "You can't wrap your head around how to do this."
else if(is_thrall(usr)) usr << "You aren't powerful enough to do this."
else if(is_shadow(usr)) usr << "Your telepathic ability is suppressed. Hatch or regenerate first."
@@ -87,7 +90,7 @@
for(var/obj/machinery/computer/C in T.contents)
C.SetLuminosity(0)
C.visible_message("[C] grows dim, its screen barely readable.")
- for(var/obj/effect/glowshroom/G in orange(2, usr)) //Very small radius
+ for(var/obj/effect/glowshroom/G in orange(7, usr)) //High radius because glowshroom spam wrecks shadowlings
G.visible_message("[G] withers away!")
qdel(G)
for(var/mob/living/H in T.contents)
@@ -171,7 +174,7 @@
/obj/effect/proc_holder/spell/targeted/enthrall/cast(list/targets)
var/mob/living/carbon/human/user = usr
listclearnulls(ticker.mode.thralls)
- if(!shadowling_check(usr)) return
+ if(!(usr.mind in ticker.mode.shadows)) return
if(user.dna.species.id != "shadowling")
if(ticker.mode.thralls.len >= 5)
user << "With your telepathic abilities suppressed, your human form will not allow you to enthrall any others. Hatch first."
@@ -229,7 +232,7 @@
for(var/obj/item/weapon/implant/loyalty/L in target)
if(L && L.implanted)
qdel(L)
- target << "Your unwavering loyalty to Nanotrasen unexpectedly falters, dims, dies. You feel a sense of liberation which is quickly stifled by terror."
+ target << "Your unwavering loyalty to Nanotrasen unexpectedly falters, dims, dies."
if(3)
usr << "You begin rearranging [target]'s memories."
usr.visible_message("[usr]'s eyes flare brightly.")
@@ -294,7 +297,7 @@
user.equip_to_slot_or_del(new /obj/item/clothing/gloves/shadowling(usr), slot_gloves)
user.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/shadowling(usr), slot_wear_mask)
user.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/shadowling(usr), slot_glasses)
- hardset_dna(user, null, null, null, null, /datum/species/shadow/ling)
+ user.set_species(/datum/species/shadow/ling)
/obj/effect/proc_holder/spell/targeted/collective_mind //Lets a shadowling bring together their thralls' strength, granting new abilities and a headcount
@@ -331,27 +334,28 @@
user << "Your concentration has been broken. The mental hooks you have sent out now retract into your mind."
return
- if(thralls >= 3 && !blind_smoke_acquired)
+ if(thralls >= 3 && !screech_acquired)
+ screech_acquired = 1
+ user << "The power of your thralls has granted you the Sonic Screech ability. This ability will shatter nearby windows and deafen enemies, plus stunning silicon lifeforms."
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/unearthly_screech(null))
+
+ if(thralls >= 5 && !blind_smoke_acquired)
blind_smoke_acquired = 1
user << "The power of your thralls has granted you the Blinding Smoke ability. It will create a choking cloud that will blind any non-thralls who enter. \
"
- user.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/blindness_smoke
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/blindness_smoke(null))
- if(thralls >= 5 && !drainLifeAcquired)
+ if(thralls >= 7 && !drainLifeAcquired)
drainLifeAcquired = 1
user << "The power of your thralls has granted you the Drain Life ability. You can now drain the health of nearby humans to heal yourself."
- user.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/drain_life
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/drain_life(null))
- if(thralls >= 7 && !screech_acquired)
- screech_acquired = 1
- user << "The power of your thralls has granted you the Sonic Screech ability. This ability will shatter nearby windows and deafen enemies, plus stunning silicon lifeforms."
- user.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/unearthly_screech
if(thralls >= 9 && !reviveThrallAcquired)
reviveThrallAcquired = 1
user << "The power of your thralls has granted you the Black Recuperation ability. This will, after a short time, bring a dead thrall completely back to life \
with no bodily defects."
- user.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/revive_thrall
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/revive_thrall(null))
if(thralls < victory_threshold)
user << "You do not have the power to ascend. You require [victory_threshold] thralls, but only [thralls] living thralls are present."
@@ -489,7 +493,7 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
nearbyTargets = list()
for(var/turf/T in targets)
for(var/mob/living/carbon/M in T.contents)
- if(M == src) continue
+ if(M == usr) continue
targetsDrained++
nearbyTargets.Add(M)
if(!targetsDrained)
@@ -511,52 +515,148 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
/obj/effect/proc_holder/spell/targeted/revive_thrall //Completely revives a dead thrall
name = "Black Recuperation"
- desc = "Brings a dead thrall back to life."
+ desc = "Revives or empowers a thrall."
panel = "Shadowling Abilities"
range = 1
- charge_max = 3000
+ charge_max = 600
clothes_req = 0
include_user = 0
action_icon_state = "revive_thrall"
- var/list/thralls_in_world = list()
/obj/effect/proc_holder/spell/targeted/revive_thrall/cast(list/targets)
if(!shadowling_check(usr))
charge_counter = charge_max
return
for(var/mob/living/carbon/human/thrallToRevive in targets)
- if(!is_thrall(thrallToRevive))
- usr << "[thrallToRevive] is not a thrall."
+ var/choice = alert(usr,"Empower a living thrall or revive a dead one?",,"Empower","Revive","Cancel")
+ switch(choice)
+ if("Empower")
+ if(!is_thrall(thrallToRevive))
+ usr << "[thrallToRevive] is not a thrall."
+ charge_counter = charge_max
+ return
+ if(thrallToRevive.stat != CONSCIOUS)
+ usr << "[thrallToRevive] must be conscious to become empowered."
+ charge_counter = charge_max
+ return
+ var/empowered_thralls = 0
+ for(var/datum/mind/M in ticker.mode.thralls)
+ if(!ishuman(M.current))
+ return
+ var/mob/living/carbon/human/H = M.current
+ if(H.dna.species.id == "l_shadowling")
+ empowered_thralls++
+ if(empowered_thralls >= EMPOWERED_THRALL_LIMIT)
+ usr << "You cannot spare this much energy. There are too many empowered thralls."
+ charge_counter = charge_max
+ return
+ usr.visible_message("[usr] places their hands over [thrallToRevive]'s face, red light shining from beneath.", \
+ "You place your hands on [thrallToRevive]'s face and begin gathering energy...")
+ thrallToRevive << "[usr] places their hands over your face. You feel energy gathering. Stand still..."
+ if(!do_mob(usr, thrallToRevive, 80))
+ usr << "Your concentration snaps. The flow of energy ebbs."
+ charge_counter = charge_max
+ return
+ usr << "You release a massive surge of power into [thrallToRevive]!"
+ usr.visible_message("Red lightning surges into [thrallToRevive]'s face!")
+ playsound(thrallToRevive, 'sound/weapons/Egloves.ogg', 50, 1)
+ playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
+ usr.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1)
+ thrallToRevive.Weaken(5)
+ thrallToRevive.visible_message("[thrallToRevive] collapses, their skin and face distorting!", \
+ "AAAAAAAAAAAAAAAAAAAGH-")
+ sleep(20)
+ thrallToRevive.visible_message("[thrallToRevive] slowly rises, no longer recognizable as human.", \
+ "You feel new power flow into you. You have been gifted by your masters. You now closely resemble them. You are empowered in \
+ darkness but wither slowly in light. In addition, Lesser Glare and Guise have been upgraded into their true forms.")
+ thrallToRevive.set_species(/datum/species/shadow/ling/lesser)
+ thrallToRevive.mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_glare)
+ thrallToRevive.mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk)
+ thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare(null))
+ thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk(null))
+ if("Revive")
+ if(!is_thrall(thrallToRevive))
+ usr << "[thrallToRevive] is not a thrall."
+ charge_counter = charge_max
+ return
+ if(thrallToRevive.stat != DEAD)
+ usr << "[thrallToRevive] is not dead."
+ charge_counter = charge_max
+ return
+ usr.visible_message("[usr] kneels over [thrallToRevive], placing their hands on \his chest.", \
+ "You crouch over the body of your thrall and begin gathering energy...")
+ thrallToRevive.notify_ghost_cloning("Your masters are resuscitating you! Re-enter your corpse if you wish to be brought to life.")
+ if(!do_mob(usr, thrallToRevive, 30))
+ usr << "Your concentration snaps. The flow of energy ebbs."
+ charge_counter = charge_max
+ return
+ usr << "You release a massive surge of power into [thrallToRevive]!"
+ usr.visible_message("Red lightning surges from [usr]'s hands into [thrallToRevive]'s chest!")
+ playsound(thrallToRevive, 'sound/weapons/Egloves.ogg', 50, 1)
+ playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
+ usr.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1)
+ sleep(10)
+ thrallToRevive.revive()
+ thrallToRevive.visible_message("[thrallToRevive] heaves in breath, dim red light shining in their eyes.", \
+ "You have returned. One of your masters has brought you from the darkness beyond.")
+ thrallToRevive.Weaken(4)
+ thrallToRevive.emote("gasp")
+ playsound(thrallToRevive, "bodyfall", 50, 1)
+ else
+ charge_counter = charge_max
+ return
+
+
+/obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle
+ name = "Destroy Engines"
+ desc = "Extends the time of the emergency shuttle's arrival by ten to fifteen minutes."
+ panel = "Shadowling Abilities"
+ range = 1
+ clothes_req = 0
+ charge_max = 600
+ action_icon_state = "extend_shuttle"
+
+/obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle/cast(list/targets, mob/living/carbon/human/U = usr)
+ if(!shadowling_check(usr))
+ charge_counter = charge_max
+ return
+ for(var/mob/living/carbon/human/target in targets)
+ if(target.stat)
charge_counter = charge_max
return
- if(thrallToRevive.stat != DEAD)
- usr << "[thrallToRevive] is not dead."
+ if(!is_thrall(target))
+ usr << "[target] must be a thrall."
charge_counter = charge_max
return
- usr.visible_message("[usr] kneels over [thrallToRevive], placing their hands on \his chest.", \
- "You crouch over the body of your thrall and begin gathering energy...")
- thrallToRevive.notify_ghost_cloning("Your masters are resuscitating you! Re-enter your corpse if you wish to be brought to life.")
- if(!do_mob(usr, thrallToRevive, 30))
- usr << "Your concentration snaps. The flow of energy ebbs."
- charge_counter= charge_max
+ if(SSshuttle.emergency.mode != SHUTTLE_CALL)
+ usr << "The shuttle must be inbound only to the station."
+ charge_counter = charge_max
return
- usr << "You release a massive surge of power into [thrallToRevive]!"
- usr.visible_message("Red lightning surges from [usr]'s hands into [thrallToRevive]'s chest!")
- playsound(thrallToRevive, 'sound/weapons/Egloves.ogg', 50, 1)
- playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
- sleep(10)
- thrallToRevive.revive()
- thrallToRevive.visible_message("[thrallToRevive] draws in a huge breath, blinding violet light shining from their eyes.", \
- "You have returned. One of your masters has brought you from the darkness beyond.")
- thrallToRevive.Weaken(4)
- thrallToRevive.emote("gasp")
- playsound(thrallToRevive, "bodyfall", 50, 1)
+ var/mob/living/carbon/human/M = target
+ U.visible_message("[U]'s eyes flash a bright red!", \
+ "You begin to draw [M]'s life force.")
+ M.visible_message("[M]'s face falls slack, their jaw slightly distending.", \
+ "You are suddenly transported... far, far away...")
+ if(!do_after(U, 50, target = M))
+ M << "You are snapped back to reality, your haze dissipating!"
+ U << "You have been interrupted. The draw has failed."
+ return
+ U << "You project [M]'s life force toward the approaching shuttle, extending its arrival duration!"
+ M.visible_message("[M]'s eyes suddenly flare red. They proceed to collapse on the floor, not breathing.", \
+ "...speeding by... ...pretty blue glow... ...touch it... ...no glow now... ...no light... ...nothing at all...")
+ M.death()
+ if(SSshuttle.emergency.mode == SHUTTLE_CALL)
+ var/more_minutes = 9000
+ var/timer = SSshuttle.emergency.timeLeft()
+ timer += more_minutes
+ priority_announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 15 minutes..", "System Failure", 'sound/misc/notice1.ogg')
+ SSshuttle.emergency.setTimer(timer)
// THRALL ABILITIES BEYOND THIS POINT //
-/obj/effect/proc_holder/spell/targeted/lesser_glare //Thrall version of Glare - same effects but for 3 seconds
+/obj/effect/proc_holder/spell/targeted/lesser_glare //Thrall version of Glare - same effects but for 5 seconds
name = "Lesser Glare"
desc = "Stuns and mutes a target for a short duration."
panel = "Thrall Abilities"
@@ -583,8 +683,8 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
target << "Your gaze is forcibly drawn into [usr]'s eyes, and you are starstruck by the heavenly lights..."
else //Only alludes to the shadowling if the target is close by
target << "Red lights suddenly dance in your vision, and you are starstruck by their heavenly beauty..."
- target.Stun(3) //Roughly 30% as long as the normal one
- M.silent += 3
+ target.Stun(5) //Roughly 50% as long as the normal one
+ M.silent += 5
/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk //Thrall version of Shadow Walk, only works in darkness, doesn't grant phasing, but gives near-invisibility
@@ -599,15 +699,8 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk/cast(list/targets)
for(var/mob/living/user in targets)
- var/lumcount = 0
- var/turf/T = user.loc
- lumcount = T.get_lumcount()
- if(lumcount > LIGHT_DAM_THRESHOLD)
- user << "It's too bright to do that!"
- charge_counter = charge_max
- return
user.visible_message("[user] suddenly fades away!", "You veil yourself in darkness, making you harder to see.")
- user.alpha = 20
+ user.alpha = 10
sleep(40)
user.visible_message("[user] appears from nowhere!", "Your shadowy guise slips away.")
user.alpha = initial(user.alpha)
@@ -621,7 +714,7 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
range = -1
include_user = 1
clothes_req = 0
- action_icon_state = "collective_mind"
+ action_icon_state = "darksight"
var/active = 0
/obj/effect/proc_holder/spell/targeted/thrall_vision/cast(list/targets)
@@ -684,11 +777,11 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
return
for(var/mob/living/boom in targets)
- if(is_shadow_or_thrall(boom))
+ if(is_shadow(boom)) //Used to not work on thralls. Now it does so you can PUNISH THEM LIKE THE WRATHFUL GOD YOU ARE.
usr << "Making an ally explode seems unwise."
charge_counter = charge_max
return
- usr.visible_message("[usr]'s markings flare as they gesture at [boom]!", \
+ usr.visible_message("[usr]'s markings flare as they gesture at [boom]!", \
"You direct a lance of telekinetic energy into [boom].")
playMagSound()
sleep(4)
@@ -789,8 +882,7 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
for(var/turf/T in targets)
for(var/mob/living/carbon/human/target in T.contents)
if(is_shadow_or_thrall(target))
- if(target == usr) //No message for the user, of course
- continue
+ continue
target << "You are struck by a bolt of lightning!"
playsound(target, 'sound/magic/LightningShock.ogg', 50, 1)
target.Weaken(8)
@@ -831,7 +923,7 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
/obj/effect/proc_holder/spell/targeted/ascendant_transmit/cast(list/targets)
for(var/mob/living/user in targets)
- var/text = stripped_input(user, "What do you want to say to everything on and near [world.name]?.", "Transmit to World", "")
+ var/text = stripped_input(user, "What do you want to say to everything on and near [station_name()]?.", "Transmit to World", "")
if(!text)
return
world << "\"[text]\""
diff --git a/code/game/gamemodes/shadowling/shadowling_items.dm b/code/game/gamemodes/shadowling/shadowling_items.dm
index 83ef7109156..b90e78b4bdf 100644
--- a/code/game/gamemodes/shadowling/shadowling_items.dm
+++ b/code/game/gamemodes/shadowling/shadowling_items.dm
@@ -1,6 +1,6 @@
/obj/item/clothing/under/shadowling
name = "blackened flesh"
- desc = "Black, chitonous skin."
+ desc = "Black, chitinous skin."
item_state = "golem"
origin_tech = null
icon_state = "golem"
@@ -11,7 +11,7 @@
/obj/item/clothing/suit/space/shadowling
name = "chitin shell"
- desc = "Dark, semi-transparent shell. Protects against vacuum, but not against the light of the stars." //Still takes damage from spacewalking but is immune to space itself
+ desc = "A dark, semi-transparent shell. Protects against vacuum, but not against the light of the stars." //Still takes damage from spacewalking but is immune to space itself
icon_state = "golem"
item_state = "golem"
body_parts_covered = FULL_BODY //Shadowlings are immune to space
@@ -60,9 +60,13 @@
desc = "A helmet-like enclosure of the head."
icon_state = "golem"
item_state = null
+ cold_protection = HEAD
+ min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
+ heat_protection = HEAD
+ max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT
origin_tech = null
unacidable = 1
- flags = ABSTRACT | NODROP
+ flags = ABSTRACT | NODROP | STOPSPRESSUREDMAGE
/obj/item/clothing/glasses/night/shadowling
@@ -73,11 +77,33 @@
item_state = null
origin_tech = null
vision_flags = SEE_MOBS
- darkness_view = 3
+ darkness_view = 1
invis_view = 2
flash_protect = -1
unacidable = 1
flags = ABSTRACT | NODROP
+ action_button_name = "Shift Nerves"
+ action_button_is_hands_free = 1
+ var/max_darkness_view = 8
+ var/min_darkness_view = 0
+
+/obj/item/clothing/glasses/night/shadowling/attack_self(mob/user)
+ if(!ishuman(user))
+ return
+ var/mob/living/carbon/human/H = user
+ if(H.dna.species.id != "shadowling")
+ user << "You aren't sure how to do this..."
+ return
+ var/new_dark_view
+ new_dark_view = (input(user, "Enter the radius of tiles to see with night vision.", "Night Vision", "[new_dark_view]") as num)
+ new_dark_view = Clamp(new_dark_view,min_darkness_view,max_darkness_view)
+ switch(new_dark_view)
+ if(0)
+ user << "Your night vision capabilities fade away for the time being."
+ else
+ user << "You shift your night vision capabilities to see [new_dark_view] tiles away."
+ darkness_view = new_dark_view
+ return
/obj/structure/shadow_vortex
@@ -114,4 +140,4 @@
finder << "You locate a small, pulsing black tumor in [owner]'s head!"
owner << "A small part of your head pulses with agony as the light impacts it!"
-// TODO: replace dethrall surgery with this + organ manipulation, somehow.
\ No newline at end of file
+// TODO: replace dethrall surgery with this + organ manipulation, somehow.
diff --git a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
index 0a047b152a8..3ab3d435b03 100644
--- a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
@@ -84,7 +84,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/shadowling(H), slot_gloves)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/shadowling(H), slot_wear_mask)
H.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/shadowling(H), slot_glasses)
- hardset_dna(H, null, null, null, null, /datum/species/shadow/ling) //can't be a shadowling without being a shadowling
+ H.set_species(/datum/species/shadow/ling) //can't be a shadowling without being a shadowling
sleep(10)
H << "Your powers are awoken. You may now live to your fullest extent. Remember your goal. Cooperate with your thralls and allies."
@@ -95,6 +95,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/flashfreeze(null))
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/collective_mind(null))
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_regenarmor(null))
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle(null))
@@ -136,7 +137,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
sleep(90)
H.visible_message("[H]'s body begins to violently stretch and contort.", \
- "You begin to rend apart the final barries to godhood.")
+ "You begin to rend apart the final barriers to godhood.")
sleep(40)
H << "Yes!"
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index e45a673a364..7d2d552ebd3 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -108,7 +108,7 @@
var/is_hijacker = prob(10)
var/martyr_chance = prob(20)
var/objective_count = is_hijacker //Hijacking counts towards number of objectives
- if(!exchange_blue && traitors.len >= 5) //Set up an exchange if there are enough traitors
+ if(!exchange_blue && traitors.len >= 8) //Set up an exchange if there are enough traitors
if(!exchange_red)
exchange_red = traitor
else
diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm
index c053983d4c0..97a531cfaa8 100644
--- a/code/game/gamemodes/wizard/artefact.dm
+++ b/code/game/gamemodes/wizard/artefact.dm
@@ -22,9 +22,9 @@
/obj/item/weapon/veilrender/attack_self(mob/user)
if(charges > 0)
- new /obj/effect/rend(get_turf(usr), spawn_type, spawn_amt, rend_desc, spawn_fast)
+ new /obj/effect/rend(get_turf(user), spawn_type, spawn_amt, rend_desc, spawn_fast)
charges--
- user.visible_message("[src] hums with power as [usr] deals a blow to [activate_descriptor] itself!")
+ user.visible_message("[src] hums with power as [user] deals a blow to [activate_descriptor] itself!")
else
user << "The unearthly energies that powered the blade are now dormant."
@@ -35,7 +35,7 @@
icon_state = "rift"
density = 1
unacidable = 1
- anchored = 1.0
+ anchored = 1
var/spawn_path = /mob/living/simple_animal/cow //defaulty cows to prevent unintentional narsies
var/spawn_amt_left = 20
var/spawn_fast = 0
@@ -59,7 +59,7 @@
/obj/effect/rend/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/nullrod))
- user.visible_message("[usr] seals \the [src] with \the [I].")
+ user.visible_message("[user] seals \the [src] with \the [I].")
qdel(src)
return
..()
@@ -97,7 +97,7 @@
/obj/item/weapon/scrying/attack_self(mob/user)
user << "You can see...everything!"
- visible_message("[usr] stares into [src], their eyes glazing over.")
+ visible_message("[user] stares into [src], their eyes glazing over.")
user.ghostize(1)
return
@@ -118,7 +118,7 @@
unlimited = 1
/obj/item/device/necromantic_stone/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
- if(!istype(M, /mob/living/carbon/human))
+ if(!istype(M))
return ..()
if(!istype(user) || !user.canUseTopic(M,1))
@@ -137,7 +137,7 @@
user << "This artifact can only affect three undead at a time!"
return
- hardset_dna(M, null, null, null, null, /datum/species/skeleton)
+ M.set_species(/datum/species/skeleton, icon_update=0)
M.revive()
spooky_scaries |= M
M << "You have been revived by [user.real_name]!"
@@ -204,7 +204,7 @@ var/global/list/multiverse = list()
/obj/item/weapon/multisword/Destroy()
multiverse.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/multisword/attack_self(mob/user)
if(user.mind.special_role == "apprentice")
@@ -261,13 +261,24 @@ var/global/list/multiverse = list()
/obj/item/weapon/multisword/proc/spawn_copy(var/client/C, var/turf/T)
var/mob/living/carbon/human/M = new/mob/living/carbon/human(T)
- C.prefs.copy_to(M)
+ C.prefs.copy_to(M, icon_updates=0)
M.key = C.key
M.mind.name = usr.real_name
M << "You are an alternate version of [usr.real_name] from another universe! Help them accomplish their goals at all costs."
M.real_name = usr.real_name
M.name = usr.real_name
M.faction = list("[usr.real_name]")
+ if(prob(50))
+ var/list/all_species = list()
+ for(var/speciestype in typesof(/datum/species) - /datum/species)
+ var/datum/species/S = new speciestype()
+ if(!S.dangerous_existence)
+ all_species += speciestype
+ M.set_species(pick(all_species), icon_update=0)
+ M.update_body()
+ M.update_hair()
+ M.update_mutcolor()
+ M.dna.update_dna_identity()
equip_copy(M)
if(evil)
@@ -440,14 +451,6 @@ var/global/list/multiverse = list()
else
return
- ready_dna(M)
- if(M.dna && prob(50))
- var/list/all_species = list()
- for(var/speciestype in typesof(/datum/species) - /datum/species)
- var/datum/species/S = new speciestype()
- if(!S.dangerous_existence)
- all_species += speciestype
- hardset_dna(M, null, null, null, null, pick(all_species))
M.update_icons()
M.update_augments()
@@ -476,7 +479,7 @@ var/global/list/multiverse = list()
/obj/item/voodoo/attackby(obj/item/I, mob/user, params)
if(target && cooldown < world.time)
- if(is_hot(I))
+ if(I.is_hot())
target << "You suddenly feel very hot"
target.bodytemperature += 50
GiveHint(target)
@@ -505,9 +508,19 @@ var/global/list/multiverse = list()
return src.loc == user
/obj/item/voodoo/attack_self(mob/user)
- if(!target)
+ if(!target && possible.len)
target = input(user, "Select your victim!", "Voodoo") as null|anything in possible
return
+
+ if(user.zone_sel.selecting == "chest")
+ if(link)
+ target = null
+ link.loc = get_turf(src)
+ user << "You remove the [link] from the doll."
+ link = null
+ update_targets()
+ return
+
if(target && cooldown < world.time)
switch(user.zone_sel.selecting)
if("mouth")
@@ -542,13 +555,6 @@ var/global/list/multiverse = list()
target.Dizzy(10)
target << "You suddenly feel as if your head was hit with a hammer!"
GiveHint(target,user)
- if("chest")
- if(link)
- target = null
- link.loc = get_turf(src)
- user << "You remove the [link] from the doll."
- link = null
- update_targets()
cooldown = world.time + cooldown_time
/obj/item/voodoo/proc/update_targets()
diff --git a/code/game/gamemodes/wizard/godhand.dm b/code/game/gamemodes/wizard/godhand.dm
index f0d57d5784d..ef90c160dfa 100644
--- a/code/game/gamemodes/wizard/godhand.dm
+++ b/code/game/gamemodes/wizard/godhand.dm
@@ -8,7 +8,7 @@
icon_state = "syndballoon"
item_state = null
flags = ABSTRACT | NODROP
- w_class = 5.0
+ w_class = 5
force = 0
throwforce = 0
throw_range = 0
diff --git a/code/game/gamemodes/wizard/raginmages.dm b/code/game/gamemodes/wizard/raginmages.dm
index d59f47796b5..d53f5fa2dba 100644
--- a/code/game/gamemodes/wizard/raginmages.dm
+++ b/code/game/gamemodes/wizard/raginmages.dm
@@ -130,7 +130,7 @@
var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned.
G_found.client.prefs.copy_to(new_character)
- ready_dna(new_character)
+ new_character.dna.update_dna_identity()
new_character.key = G_found.key
return new_character
diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm
index 0f3fe47fac3..e19a6ae1100 100644
--- a/code/game/gamemodes/wizard/soulstone.dm
+++ b/code/game/gamemodes/wizard/soulstone.dm
@@ -4,7 +4,7 @@
icon_state = "soulstone"
item_state = "electronic"
desc = "A fragment of the legendary treasure known simply as the 'Soul Stone'. The shard still flickers with a fraction of the full artefacts power."
- w_class = 1.0
+ w_class = 1
slot_flags = SLOT_BELT
origin_tech = "bluespace=4;materials=4"
var/imprinted = "empty"
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index eec319a8fba..3e5c1c56c12 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -19,7 +19,7 @@
return 0
return 1
/datum/spellbook_entry/proc/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book) //return 1 on success
- if(!S)
+ if(!S || qdeleted(S))
S = new spell_type()
//Check if we got the spell already
@@ -78,7 +78,7 @@
if(initial(S.name) == initial(aspell.name))
spell_levels = aspell.spell_level
user.mind.spell_list.Remove(aspell)
- del(S)
+ qdel(S)
return cost * (spell_levels+1)
return -1
/datum/spellbook_entry/proc/GetInfo()
@@ -119,6 +119,11 @@
spell_type = /obj/effect/proc_holder/spell/aoe_turf/repulse
log_name = "RP"
+/datum/spellbook_entry/timestop
+ name = "Time Stop"
+ spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop
+ log_name = "TS"
+
/datum/spellbook_entry/smoke
name = "Smoke"
spell_type = /obj/effect/proc_holder/spell/targeted/smoke
@@ -402,7 +407,7 @@
icon_state ="book"
throw_speed = 2
throw_range = 5
- w_class = 1.0
+ w_class = 1
var/uses = 5
var/temp = null
var/op = 1
@@ -419,7 +424,7 @@
entries |= E
categories |= E.category
else
- del(E)
+ qdel(E)
tab = categories[1]
/obj/item/weapon/spellbook/New()
diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm
index 6ed742e75a4..c500f390b6a 100644
--- a/code/game/gamemodes/wizard/wizard.dm
+++ b/code/game/gamemodes/wizard/wizard.dm
@@ -36,9 +36,9 @@
/datum/game_mode/wizard/post_setup()
for(var/datum/mind/wizard in wizards)
log_game("[wizard.key] (ckey) has been selected as a Wizard")
- forge_wizard_objectives(wizard)
//learn_basic_spells(wizard.current)
equip_wizard(wizard.current)
+ forge_wizard_objectives(wizard)
name_wizard(wizard.current)
greet_wizard(wizard)
if(use_huds)
diff --git a/code/game/jobs/job/assistant.dm b/code/game/jobs/job/assistant.dm
index 7733a3be546..9a1822fad7e 100644
--- a/code/game/jobs/job/assistant.dm
+++ b/code/game/jobs/job/assistant.dm
@@ -12,13 +12,7 @@ Assistant
selection_color = "#dddddd"
access = list() //See /datum/job/assistant/get_access()
minimal_access = list() //See /datum/job/assistant/get_access()
-
-/datum/job/assistant/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(H), slot_shoes)
- if (config.grey_assistants)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(H), slot_w_uniform)
- else
- H.equip_to_slot_or_del(new /obj/item/clothing/under/color/random(H), slot_w_uniform)
+ outfit = /datum/outfit/job/assistant
/datum/job/assistant/get_access()
if((config.jobs_have_maint_access & ASSISTANTS_HAVE_MAINT_ACCESS) || !config.jobs_have_minimal_access) //Config has assistant maint access set
@@ -32,4 +26,15 @@ Assistant
total_positions = config.assistant_cap
spawn_positions = config.assistant_cap
return 1
- return 0
\ No newline at end of file
+ return 0
+
+
+/datum/outfit/job/assistant
+ name = "Assistant"
+
+/datum/outfit/job/assistant/pre_equip(mob/living/carbon/human/H)
+ ..()
+ if (config.grey_assistants)
+ uniform = /obj/item/clothing/under/color/grey
+ else
+ uniform = /obj/item/clothing/under/color/random
diff --git a/code/game/jobs/job/captain.dm b/code/game/jobs/job/captain.dm
index 7d345e71a3b..57cc571b705 100644
--- a/code/game/jobs/job/captain.dm
+++ b/code/game/jobs/job/captain.dm
@@ -14,29 +14,37 @@ Captain
req_admin_notify = 1
minimal_player_age = 14
- default_id = /obj/item/weapon/card/id/gold
- default_pda = /obj/item/device/pda/captain
- default_headset = /obj/item/device/radio/headset/heads/captain
- default_backpack = /obj/item/weapon/storage/backpack/captain
- default_satchel = /obj/item/weapon/storage/backpack/satchel_cap
+ outfit = /datum/outfit/job/captain
access = list() //See get_access()
minimal_access = list() //See get_access()
-/datum/job/captain/equip_items(mob/living/carbon/human/H)
- var/obj/item/clothing/under/U = new /obj/item/clothing/under/rank/captain(H)
+/datum/job/captain/get_access()
+ return get_all_accesses()
+
+
+/datum/outfit/job/captain
+ name = "Captain"
+
+ id = /obj/item/weapon/card/id/gold
+ belt = /obj/item/device/pda/captain
+ ears = /obj/item/device/radio/headset/heads/captain
+ uniform = /obj/item/clothing/under/rank/captain
+ suit = /obj/item/clothing/suit/armor/vest/capcarapace
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ head = /obj/item/clothing/head/caphat
+ backpack_contents = list(/obj/item/weapon/storage/box/silver_ids=1,\
+ /obj/item/weapon/melee/classic_baton/telescopic=1)
+
+ backpack = /obj/item/weapon/storage/backpack/captain
+ satchel = /obj/item/weapon/storage/backpack/satchel_cap
+
+/datum/outfit/job/captain/post_equip(mob/living/carbon/human/H)
+ ..()
+
+ var/obj/item/clothing/under/U = H.w_uniform
U.attachTie(new /obj/item/clothing/tie/medal/gold/captain())
- H.equip_to_slot_or_del(U, slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/vest/capcarapace(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/brown(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/caphat(H), slot_head)
- H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses)
- //Equip ID box & telebaton
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/silver_ids(H.back), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/weapon/melee/classic_baton/telescopic(H), slot_in_backpack)
-
- //Implant him
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
L.imp_in = H
L.implanted = 1
@@ -44,9 +52,6 @@ Captain
minor_announce("Captain [H.real_name] on deck!")
-/datum/job/captain/get_access()
- return get_all_accesses()
-
/*
Head of Personnel
*/
@@ -63,9 +68,7 @@ Head of Personnel
req_admin_notify = 1
minimal_player_age = 10
- default_id = /obj/item/weapon/card/id/silver
- default_pda = /obj/item/device/pda/heads/hop
- default_headset = /obj/item/device/radio/headset/heads/hop
+ outfit = /datum/outfit/job/hop
access = list(access_security, access_sec_doors, access_court, access_weapons,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
@@ -81,13 +84,19 @@ Head of Personnel
access_hop, access_RC_announce, access_keycard_auth, access_gateway, access_mineral_storeroom)
-/datum/job/hop/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_personnel(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/brown(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/hopcap(H), slot_head)
+/datum/outfit/job/hop
+ name = "Head of Personnel"
- //Equip ID box & telebaton
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/ids(H.back), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/weapon/melee/classic_baton/telescopic(H), slot_in_backpack)
+ id = /obj/item/weapon/card/id/silver
+ belt = /obj/item/device/pda/heads/hop
+ ears = /obj/item/device/radio/headset/heads/hop
+ uniform = /obj/item/clothing/under/rank/head_of_personnel
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ head = /obj/item/clothing/head/hopcap
+ backpack_contents = list(/obj/item/weapon/storage/box/ids=1,\
+ /obj/item/weapon/melee/classic_baton/telescopic=1)
- announce_head(H, list("Supply", "Service")) //tell underlings (suuply/service) they have a head
+/datum/outfit/job/hop/post_equip(mob/living/carbon/human/H)
+ ..()
+
+ announce_head(H, list("Supply", "Service"))
diff --git a/code/game/jobs/job/cargo_service.dm b/code/game/jobs/job/cargo_service.dm
index 5fcb2be02bf..1eeca19eaa5 100644
--- a/code/game/jobs/job/cargo_service.dm
+++ b/code/game/jobs/job/cargo_service.dm
@@ -12,17 +12,20 @@ Quartermaster
supervisors = "the head of personnel"
selection_color = "#d7b088"
- default_pda = /obj/item/device/pda/quartermaster
- default_headset = /obj/item/device/radio/headset/headset_cargo
+ outfit = /datum/outfit/job/quartermaster
access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station, access_mineral_storeroom)
minimal_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station, access_mineral_storeroom)
-/datum/job/qm/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargo(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/brown(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses)
- H.equip_to_slot_or_del(new /obj/item/weapon/clipboard(H), slot_l_hand)
+/datum/outfit/job/quartermaster
+ name = "Quartermaster"
+
+ belt = /obj/item/device/pda/quartermaster
+ ears = /obj/item/device/radio/headset/headset_cargo
+ uniform = /obj/item/clothing/under/rank/cargo
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ glasses = /obj/item/clothing/glasses/sunglasses
+ l_hand = /obj/item/weapon/clipboard
/*
Cargo Technician
@@ -38,15 +41,18 @@ Cargo Technician
supervisors = "the quartermaster and the head of personnel"
selection_color = "#dcba97"
- default_pda = /obj/item/device/pda/cargo
- default_headset = /obj/item/device/radio/headset/headset_cargo
+ outfit = /datum/outfit/job/cargo_tech
access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station, access_mineral_storeroom)
minimal_access = list(access_maint_tunnels, access_cargo, access_cargo_bot, access_mailsorting, access_mineral_storeroom)
-/datum/job/cargo_tech/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargotech(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(H), slot_shoes)
+/datum/outfit/job/cargo_tech
+ name = "Cargo Technician"
+
+ belt = /obj/item/device/pda/cargo
+ ears = /obj/item/device/radio/headset/headset_cargo
+ uniform = /obj/item/clothing/under/rank/cargotech
+
/*
Shaft Miner
@@ -62,23 +68,25 @@ Shaft Miner
supervisors = "the quartermaster and the head of personnel"
selection_color = "#dcba97"
- default_pda = /obj/item/device/pda/shaftminer
- default_headset = /obj/item/device/radio/headset/headset_cargo
- default_backpack = /obj/item/weapon/storage/backpack/industrial
- default_satchel = /obj/item/weapon/storage/backpack/satchel_eng
- default_storagebox = /obj/item/weapon/storage/box/engineer
+ outfit = /datum/outfit/job/miner
access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station, access_mineral_storeroom)
minimal_access = list(access_mining, access_mining_station, access_mailsorting, access_mineral_storeroom)
-/datum/job/mining/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/miner(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(H), slot_shoes)
+/datum/outfit/job/miner
+ name = "Shaft Miner"
- H.equip_to_slot_or_del(new /obj/item/weapon/crowbar(H), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/bag/ore(H), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/weapon/mining_voucher(H), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/patch/styptic(H), slot_l_store)
+ belt = /obj/item/device/pda/shaftminer
+ ears = /obj/item/device/radio/headset/headset_cargo
+ uniform = /obj/item/clothing/under/rank/miner
+ l_pocket = /obj/item/weapon/reagent_containers/pill/patch/styptic
+ backpack_contents = list(/obj/item/weapon/crowbar=1,\
+ /obj/item/weapon/storage/bag/ore=1,\
+ /obj/item/weapon/mining_voucher=1)
+
+ backpack = /obj/item/weapon/storage/backpack/industrial
+ satchel = /obj/item/weapon/storage/backpack/satchel_eng
+ box = /obj/item/weapon/storage/box/engineer
/*
Bartender
@@ -94,21 +102,20 @@ Bartender
supervisors = "the head of personnel"
selection_color = "#bbe291"
- default_pda = /obj/item/device/pda/bar
- default_headset = /obj/item/device/radio/headset/headset_srv
+ outfit = /datum/outfit/job/bartender
access = list(access_hydroponics, access_bar, access_kitchen, access_morgue, access_weapons)
minimal_access = list(access_bar)
-/datum/job/bartender/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/vest(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/bartender(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack)
+/datum/outfit/job/bartender
+ name = "Bartender"
+
+ belt = /obj/item/device/pda/bar
+ ears = /obj/item/device/radio/headset/headset_srv
+ uniform = /obj/item/clothing/under/rank/bartender
+ suit = /obj/item/clothing/suit/armor/vest
+ backpack_contents = list(/obj/item/ammo_casing/shotgun/beanbag=4)
/*
Cook
@@ -123,26 +130,30 @@ Cook
spawn_positions = 1
supervisors = "the head of personnel"
selection_color = "#bbe291"
- var/global/cooks = 0 //Counts cooks amount
+ var/cooks = 0 //Counts cooks amount
- default_pda = /obj/item/device/pda/cook
- default_headset = /obj/item/device/radio/headset/headset_srv
+ outfit = /datum/outfit/job/cook
access = list(access_hydroponics, access_bar, access_kitchen, access_morgue)
minimal_access = list(access_kitchen, access_morgue)
-/datum/job/cook/equip_items(mob/living/carbon/human/H)
- cooks += 1
+/datum/outfit/job/cook
+ name = "Cook"
+
+ belt = /obj/item/device/pda/cook
+ ears = /obj/item/device/radio/headset/headset_srv
+ uniform = /obj/item/clothing/under/rank/chef
+ suit = /obj/item/clothing/suit/toggle/chef
+ head = /obj/item/clothing/head/chefhat
+
+/datum/outfit/job/cook/pre_equip(mob/living/carbon/human/H)
+ ..()
+ var/datum/job/cook/J = SSjob.GetJob(H.job)
+ J.cooks++
+ if(J.cooks>1)//Cooks
+ suit = /obj/item/clothing/suit/apron/chef
+ head = /obj/item/clothing/head/soft/mime
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chef(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(H), slot_shoes)
- switch(cooks)
- if(1)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/chef(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/chefhat(H), slot_head)
- else
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/apron/chef(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/soft/mime(H), slot_head)
/*
Botanist
@@ -158,18 +169,21 @@ Botanist
supervisors = "the head of personnel"
selection_color = "#bbe291"
- default_pda = /obj/item/device/pda/botanist
- default_headset = /obj/item/device/radio/headset/headset_srv
+ outfit = /datum/outfit/job/botanist
access = list(access_hydroponics, access_bar, access_kitchen, access_morgue) // Removed tox and chem access because STOP PISSING OFF THE CHEMIST GUYS // //Removed medical access because WHAT THE FUCK YOU AREN'T A DOCTOR YOU GROW WHEAT //Given Morgue access because they have a viable means of cloning.
minimal_access = list(access_hydroponics, access_morgue) // Removed tox and chem access because STOP PISSING OFF THE CHEMIST GUYS // //Removed medical access because WHAT THE FUCK YOU AREN'T A DOCTOR YOU GROW WHEAT //Given Morgue access because they have a viable means of cloning.
-/datum/job/hydro/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/hydroponics(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/gloves/botanic_leather(H), slot_gloves)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/apron(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/device/analyzer/plant_analyzer(H), slot_s_store)
+/datum/outfit/job/botanist
+ name = "Botanist"
+
+ belt = /obj/item/device/pda/botanist
+ ears = /obj/item/device/radio/headset/headset_srv
+ uniform = /obj/item/clothing/under/rank/hydroponics
+ suit = /obj/item/clothing/suit/apron
+ gloves =/obj/item/clothing/gloves/botanic_leather
+ suit_store = /obj/item/device/analyzer/plant_analyzer
+
/*
Janitor
@@ -186,12 +200,14 @@ Janitor
selection_color = "#bbe291"
var/global/janitors = 0
- default_pda = /obj/item/device/pda/janitor
- default_headset = /obj/item/device/radio/headset/headset_srv
+ outfit = /datum/outfit/job/janitor
access = list(access_janitor, access_maint_tunnels)
minimal_access = list(access_janitor, access_maint_tunnels)
-/datum/job/janitor/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/janitor(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(H), slot_shoes)
+/datum/outfit/job/janitor
+ name = "Janitor"
+
+ belt = /obj/item/device/pda/janitor
+ ears = /obj/item/device/radio/headset/headset_srv
+ uniform = /obj/item/clothing/under/rank/janitor
\ No newline at end of file
diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm
index 01ab44ea8a1..2e97c7482d9 100644
--- a/code/game/jobs/job/civilian.dm
+++ b/code/game/jobs/job/civilian.dm
@@ -12,25 +12,32 @@ Clown
supervisors = "the head of personnel"
selection_color = "#dddddd"
- default_pda = /obj/item/device/pda/clown
- default_backpack = /obj/item/weapon/storage/backpack/clown
- default_satchel = /obj/item/weapon/storage/backpack/clown
+ outfit = /datum/outfit/job/clown
access = list(access_theatre)
minimal_access = list(access_theatre)
-/datum/job/clown/equip_items(mob/living/carbon/human/H)
- H.fully_replace_character_name(H.real_name, pick(clown_names)) // Give him a temporary random name to prevent identity revealing
+/datum/outfit/job/clown
+ name = "Clown"
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), slot_wear_mask)
- H.equip_to_slot_or_del(new /obj/item/weapon/bikehorn(H), slot_l_store)
- H.equip_to_slot_or_del(new /obj/item/toy/crayon/rainbow(H), slot_r_store)
+ belt = /obj/item/device/pda/clown
+ uniform = /obj/item/clothing/under/rank/clown
+ shoes = /obj/item/clothing/shoes/clown_shoes
+ mask = /obj/item/clothing/mask/gas/clown_hat
+ l_pocket = /obj/item/weapon/bikehorn
+ r_pocket = /obj/item/toy/crayon/rainbow
+ backpack_contents = list(/obj/item/weapon/stamp/clown=1,/obj/item/weapon/reagent_containers/spray/waterflower=1)
- H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(H, 50), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/weapon/stamp/clown(H), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/spray/waterflower(H), slot_in_backpack)
+ backpack = /obj/item/weapon/storage/backpack/clown
+ satchel = /obj/item/weapon/storage/backpack/clown
+
+/datum/outfit/job/clown/pre_equip(mob/living/carbon/human/H)
+ ..()
+ H.fully_replace_character_name(H.real_name, pick(clown_names))
+
+/datum/outfit/job/clown/post_equip(mob/living/carbon/human/H)
+ ..()
+ new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(H.back, 50)
H.dna.add_mutation(CLOWNMUT)
H.rename_self("clown")
@@ -49,24 +56,28 @@ Mime
supervisors = "the head of personnel"
selection_color = "#dddddd"
- default_pda = /obj/item/device/pda/mime
- default_backpack = /obj/item/weapon/storage/backpack/mime
- default_satchel = /obj/item/weapon/storage/backpack/mime
+ outfit = /datum/outfit/job/mime
access = list(access_theatre)
minimal_access = list(access_theatre)
-/datum/job/mime/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/mime(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/white(H), slot_gloves)
- H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/mime(H), slot_wear_mask)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/suspenders(H), slot_wear_suit)
+/datum/outfit/job/mime
+ name = "Mime"
- H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/toy/crayon/mime(H), slot_in_backpack)
+ belt = /obj/item/device/pda/mime
+ uniform = /obj/item/clothing/under/rank/mime
+ mask = /obj/item/clothing/mask/gas/mime
+ gloves = /obj/item/clothing/gloves/color/white
+ head = /obj/item/clothing/head/beret
+ suit = /obj/item/clothing/suit/suspenders
+ backpack_contents = list(/obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing=1,\
+ /obj/item/toy/crayon/mime=1)
+ backpack = /obj/item/weapon/storage/backpack/mime
+ satchel = /obj/item/weapon/storage/backpack/mime
+
+/datum/outfit/job/mime/post_equip(mob/living/carbon/human/H)
+ ..()
if(H.mind)
H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall(null))
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mime/speak(null))
@@ -88,17 +99,19 @@ Librarian
supervisors = "the head of personnel"
selection_color = "#dddddd"
- default_pda = /obj/item/device/pda/librarian
+ outfit = /datum/outfit/job/librarian
access = list(access_library)
minimal_access = list(access_library)
-/datum/job/librarian/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/librarian(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/bag/books(H), slot_l_hand)
- H.equip_to_slot_or_del(new /obj/item/weapon/barcodescanner(H), slot_r_store)
- H.equip_to_slot_or_del(new /obj/item/device/laser_pointer(H), slot_l_store)
+/datum/outfit/job/librarian
+ name = "Librarian"
+
+ belt = /obj/item/device/pda/librarian
+ uniform = /obj/item/clothing/under/rank/librarian
+ l_hand = /obj/item/weapon/storage/bag/books
+ r_pocket = /obj/item/weapon/barcodescanner
+ l_pocket = /obj/item/device/laser_pointer
/*
Lawyer
@@ -113,25 +126,28 @@ Lawyer
spawn_positions = 2
supervisors = "the head of personnel"
selection_color = "#dddddd"
- var/global/lawyers = 0 //Counts lawyer amount
+ var/lawyers = 0 //Counts lawyer amount
- default_pda = /obj/item/device/pda/lawyer
- default_headset = /obj/item/device/radio/headset/headset_sec
+ outfit = /datum/outfit/job/lawyer
access = list(access_lawyer, access_court, access_sec_doors)
minimal_access = list(access_lawyer, access_court, access_sec_doors)
-/datum/job/lawyer/equip_items(mob/living/carbon/human/H)
- lawyers += 1
+/datum/outfit/job/lawyer
+ name = "Lawyer"
- switch(lawyers)
- if(1)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/lawyer/bluesuit(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/lawyer(H), slot_wear_suit)
- else
- H.equip_to_slot_or_del(new /obj/item/clothing/under/lawyer/purpsuit(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/lawyer/purple(H), slot_wear_suit)
+ belt = /obj/item/device/pda/lawyer
+ ears = /obj/item/device/radio/headset/headset_sec
+ uniform = /obj/item/clothing/under/lawyer/bluesuit
+ suit = /obj/item/clothing/suit/toggle/lawyer
+ shoes = /obj/item/clothing/shoes/laceup
+ l_hand = /obj/item/weapon/storage/briefcase
+ l_pocket = /obj/item/device/laser_pointer
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/briefcase(H), slot_l_hand)
- H.equip_to_slot_or_del(new /obj/item/device/laser_pointer(H), slot_l_store)
+/datum/outfit/job/lawyer/pre_equip(mob/living/carbon/human/H)
+ ..()
+ var/datum/job/lawyer/J = SSjob.GetJob(H.job)
+ J.lawyers++
+ if(J.lawyers>1)
+ uniform = /obj/item/clothing/under/lawyer/purpsuit
+ suit = /obj/item/clothing/suit/toggle/lawyer/purple
\ No newline at end of file
diff --git a/code/game/jobs/job/civilian_chaplain.dm b/code/game/jobs/job/civilian_chaplain.dm
index 87ffe8f8b19..261193a8563 100644
--- a/code/game/jobs/job/civilian_chaplain.dm
+++ b/code/game/jobs/job/civilian_chaplain.dm
@@ -13,14 +13,19 @@ Chaplain
supervisors = "the head of personnel"
selection_color = "#dddddd"
- default_pda = /obj/item/device/pda/chaplain
+ outfit = /datum/outfit/job/chaplain
access = list(access_morgue, access_chapel_office, access_crematorium)
minimal_access = list(access_morgue, access_chapel_office, access_crematorium)
-/datum/job/chaplain/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chaplain(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(H), slot_shoes)
+/datum/outfit/job/chaplain
+ name = "Chaplain"
+
+ belt = /obj/item/device/pda/chaplain
+ uniform = /obj/item/clothing/under/rank/chaplain
+
+/datum/outfit/job/chaplain/post_equip(mob/living/carbon/human/H)
+ ..()
var/obj/item/weapon/storage/book/bible/B = new /obj/item/weapon/storage/book/bible/booze(H)
var/new_religion = "Christianity"
diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm
index 1d7961293cf..77ddc8e8c23 100644
--- a/code/game/jobs/job/engineering.dm
+++ b/code/game/jobs/job/engineering.dm
@@ -14,13 +14,7 @@ Chief Engineer
req_admin_notify = 1
minimal_player_age = 7
- default_id = /obj/item/weapon/card/id/silver
- default_pda = /obj/item/device/pda/heads/ce
- default_pda_slot = slot_l_store
- default_headset = /obj/item/device/radio/headset/heads/ce
- default_backpack = /obj/item/weapon/storage/backpack/industrial
- default_satchel = /obj/item/weapon/storage/backpack/satchel_eng
- default_storagebox = /obj/item/weapon/storage/box/engineer
+ outfit = /datum/outfit/job/ce
access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
@@ -31,17 +25,27 @@ Chief Engineer
access_heads, access_construction, access_sec_doors, access_minisat,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_mineral_storeroom)
-/datum/job/chief_engineer/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_engineer(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/brown(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat/white(H), slot_head)
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt)
- H.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black/ce(H), slot_gloves)
+/datum/outfit/job/ce
+ name = "Chief Engineer"
- //Equip telebaton
- H.equip_to_slot_or_del(new /obj/item/weapon/melee/classic_baton/telescopic(H), slot_in_backpack)
+ id = /obj/item/weapon/card/id/silver
+ belt = /obj/item/weapon/storage/belt/utility/full
+ l_pocket = /obj/item/device/pda/heads/ce
+ ears = /obj/item/device/radio/headset/heads/ce
+ uniform = /obj/item/clothing/under/rank/chief_engineer
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ head = /obj/item/clothing/head/hardhat/white
+ gloves = /obj/item/clothing/gloves/color/black/ce
+ backpack_contents = list(/obj/item/weapon/melee/classic_baton/telescopic=1)
- announce_head(H, list("Engineering")) //tell underlings (engineering radio) they have a head
+ backpack = /obj/item/weapon/storage/backpack/industrial
+ satchel = /obj/item/weapon/storage/backpack/satchel_eng
+ box = /obj/item/weapon/storage/box/engineer
+ pda_slot = slot_l_store
+
+/datum/outfit/job/ce/post_equip(mob/living/carbon/human/H)
+ ..()
+ announce_head(H, list("Engineering"))
/*
Station Engineer
@@ -57,24 +61,28 @@ Station Engineer
supervisors = "the chief engineer"
selection_color = "#fff5cc"
- default_pda = /obj/item/device/pda/engineering
- default_pda_slot = slot_l_store
- default_headset = /obj/item/device/radio/headset/headset_eng
- default_backpack = /obj/item/weapon/storage/backpack/industrial
- default_satchel = /obj/item/weapon/storage/backpack/satchel_eng
- default_storagebox = /obj/item/weapon/storage/box/engineer
+ outfit = /datum/outfit/job/engineer
access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_external_airlocks, access_construction, access_atmospherics, access_tcomsat)
minimal_access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_external_airlocks, access_construction, access_tcomsat)
-/datum/job/engineer/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/engineer(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat(H), slot_head)
- H.equip_to_slot_or_del(new /obj/item/device/t_scanner(H), slot_r_store)
+/datum/outfit/job/engineer
+ name = "Station Engineer"
+
+ belt = /obj/item/weapon/storage/belt/utility/full
+ l_pocket = /obj/item/device/pda/engineering
+ ears = /obj/item/device/radio/headset/headset_eng
+ uniform = /obj/item/clothing/under/rank/engineer
+ shoes = /obj/item/clothing/shoes/workboots
+ head = /obj/item/clothing/head/hardhat
+ r_pocket = /obj/item/device/t_scanner
+
+ backpack = /obj/item/weapon/storage/backpack/industrial
+ satchel = /obj/item/weapon/storage/backpack/satchel_eng
+ box = /obj/item/weapon/storage/box/engineer
+ pda_slot = slot_l_store
/*
Atmospheric Technician
@@ -90,17 +98,20 @@ Atmospheric Technician
supervisors = "the chief engineer"
selection_color = "#fff5cc"
- default_pda = /obj/item/device/pda/atmos
- default_pda_slot = slot_l_store
- default_headset = /obj/item/device/radio/headset/headset_eng
- default_storagebox = /obj/item/weapon/storage/box/engineer
+ outfit = /datum/outfit/job/atmos
access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_external_airlocks, access_construction, access_atmospherics)
minimal_access = list(access_atmospherics, access_maint_tunnels, access_emergency_storage, access_construction)
-/datum/job/atmos/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/atmospheric_technician(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/device/analyzer(H), slot_r_store)
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/atmostech/(H), slot_belt)
\ No newline at end of file
+/datum/outfit/job/atmos
+ name = "Atmospheric Technician"
+
+ belt = /obj/item/weapon/storage/belt/utility/atmostech
+ l_pocket = /obj/item/device/pda/atmos
+ ears = /obj/item/device/radio/headset/headset_eng
+ uniform = /obj/item/clothing/under/rank/atmospheric_technician
+ r_pocket = /obj/item/device/analyzer
+
+ box = /obj/item/weapon/storage/box/engineer
+ pda_slot = slot_l_store
\ No newline at end of file
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index c688e4a4303..ca5fb09823c 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -39,62 +39,23 @@
//If you have the use_age_restriction_for_jobs config option enabled and the database set up, this option will add a requirement for players to be at least minimal_player_age days old. (meaning they first signed in at least that many days before.)
var/minimal_player_age = 0
- //Job specific items
- var/default_id = /obj/item/weapon/card/id //this is just the looks of it
- var/default_pda = /obj/item/device/pda
- var/default_pda_slot = slot_belt
- var/default_headset = /obj/item/device/radio/headset
- var/default_backpack = /obj/item/weapon/storage/backpack
- var/default_satchel = /obj/item/weapon/storage/backpack/satchel_norm
- var/default_storagebox= /obj/item/weapon/storage/box/survival
+ var/outfit = null
//Only override this proc
/datum/job/proc/equip_items(mob/living/carbon/human/H)
-//Or this proc
-/datum/job/proc/equip_backpack(mob/living/carbon/human/H)
- var/obj/item/weapon/storage/backpack/BPK
- if(H.backbag == 1) //Backpack
- BPK = new default_backpack(H)
- else //Satchel
- BPK = new default_satchel(H)
- new default_storagebox(BPK)
- H.equip_to_slot_or_del(BPK, slot_back,1)
-
//But don't override this
/datum/job/proc/equip(mob/living/carbon/human/H)
if(!H)
return 0
- //Equip backpack
- equip_backpack(H)
-
//Equip the rest of the gear
- if(H.dna)
- H.dna.species.before_equip_job(src, H)
+ H.dna.species.before_equip_job(src, H)
- equip_items(H)
+ if(outfit)
+ H.equipOutfit(outfit)
- if(H.dna)
- H.dna.species.after_equip_job(src, H)
-
- //Equip ID
- var/obj/item/weapon/card/id/C = new default_id(H)
- C.access = get_access()
- C.registered_name = H.real_name
- C.assignment = H.job
- C.update_label()
- H.equip_to_slot_or_del(C, slot_wear_id)
-
- //Equip PDA
- var/obj/item/device/pda/PDA = new default_pda(H)
- PDA.owner = H.real_name
- PDA.ownjob = H.job
- PDA.update_label()
- H.equip_to_slot_or_del(PDA, default_pda_slot)
-
- //Equip headset
- H.equip_to_slot_or_del(new src.default_headset(H), slot_ears)
+ H.dna.species.after_equip_job(src, H)
/datum/job/proc/apply_fingerprints(mob/living/carbon/human/H)
if(!istype(H))
@@ -169,8 +130,46 @@
/datum/job/proc/config_check()
return 1
-/datum/job/proc/announce_head(var/mob/living/carbon/human/H, var/channels) //tells the given channel that the given mob is the new department head. See communications.dm for valid channels.
+/datum/outfit/job
+ name = "Standard Gear"
+
+ uniform = /obj/item/clothing/under/color/grey
+ id = /obj/item/weapon/card/id
+ ears = /obj/item/device/radio/headset
+ belt = /obj/item/device/pda
+ back = /obj/item/weapon/storage/backpack
+ shoes = /obj/item/clothing/shoes/sneakers/black
+
+ var/backpack = /obj/item/weapon/storage/backpack
+ var/satchel = /obj/item/weapon/storage/backpack/satchel_norm
+ var/box = /obj/item/weapon/storage/box/survival
+
+ var/pda_slot = slot_belt
+
+/datum/outfit/job/pre_equip(mob/living/carbon/human/H)
+ if(H.backbag == 1) //Backpack
+ back = backpack
+ else //Satchel
+ back = satchel
+
+ backpack_contents[box] = 1
+
+/datum/outfit/job/post_equip(mob/living/carbon/human/H)
+ var/obj/item/weapon/card/id/C = H.wear_id
+ var/datum/job/J = SSjob.GetJob(H.job) // Not sure the best idea
+ C.access = J.get_access()
+ C.registered_name = H.real_name
+ C.assignment = H.job
+ C.update_label()
+ H.sec_hud_set_ID()
+
+ var/obj/item/device/pda/PDA = H.get_item_by_slot(pda_slot)
+ PDA.owner = H.real_name
+ PDA.ownjob = H.job
+ PDA.update_label()
+
+/datum/outfit/job/proc/announce_head(var/mob/living/carbon/human/H, var/channels) //tells the given channel that the given mob is the new department head. See communications.dm for valid channels.
spawn(4) //to allow some initialization
if(announcement_systems.len)
var/obj/machinery/announcement_system/announcer = pick(announcement_systems)
- announcer.announce("NEWHEAD", H.real_name, H.job, channels)
\ No newline at end of file
+ announcer.announce("NEWHEAD", H.real_name, H.job, channels)
diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm
index 6943b3e27eb..4566d4fb2a7 100644
--- a/code/game/jobs/job/medical.dm
+++ b/code/game/jobs/job/medical.dm
@@ -14,11 +14,7 @@ Chief Medical Officer
req_admin_notify = 1
minimal_player_age = 7
- default_id = /obj/item/weapon/card/id/silver
- default_pda = /obj/item/device/pda/heads/cmo
- default_headset = /obj/item/device/radio/headset/heads/cmo
- default_backpack = /obj/item/weapon/storage/backpack/medic
- default_satchel = /obj/item/weapon/storage/backpack/satchel_med
+ outfit = /datum/outfit/job/cmo
access = list(access_medical, access_morgue, access_genetics, access_heads, access_mineral_storeroom,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
@@ -27,14 +23,24 @@ Chief Medical Officer
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
access_keycard_auth, access_sec_doors)
-/datum/job/cmo/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_medical_officer(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/brown(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/labcoat/cmo(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(H), slot_l_hand)
- H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store)
- H.equip_to_slot_or_del(new /obj/item/weapon/melee/classic_baton/telescopic(H), slot_in_backpack)
+/datum/outfit/job/cmo
+ name = "Chief Medical Officer"
+ id = /obj/item/weapon/card/id/silver
+ belt = /obj/item/device/pda/heads/cmo
+ ears = /obj/item/device/radio/headset/heads/cmo
+ uniform = /obj/item/clothing/under/rank/chief_medical_officer
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ suit = /obj/item/clothing/suit/toggle/labcoat/cmo
+ l_hand = /obj/item/weapon/storage/firstaid/regular
+ suit_store = /obj/item/device/flashlight/pen
+ backpack_contents = list(/obj/item/weapon/melee/classic_baton/telescopic=1)
+
+ backpack = /obj/item/weapon/storage/backpack/medic
+ satchel = /obj/item/weapon/storage/backpack/satchel_med
+
+/datum/outfit/job/cmo/post_equip(mob/living/carbon/human/H)
+ ..()
announce_head(H, list("Medical")) //tell underlings (medical radio) they have a head
/*
@@ -51,20 +57,24 @@ Medical Doctor
supervisors = "the chief medical officer"
selection_color = "#ffeef0"
- default_pda = /obj/item/device/pda/medical
- default_headset = /obj/item/device/radio/headset/headset_med
- default_backpack = /obj/item/weapon/storage/backpack/medic
- default_satchel = /obj/item/weapon/storage/backpack/satchel_med
+ outfit = /datum/outfit/job/doctor
access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_mineral_storeroom)
minimal_access = list(access_medical, access_morgue, access_surgery)
-/datum/job/doctor/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/white(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/labcoat(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(H), slot_l_hand)
- H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store)
+/datum/outfit/job/doctor
+ name = "Medical Doctor"
+
+ belt = /obj/item/device/pda/medical
+ ears = /obj/item/device/radio/headset/headset_med
+ uniform = /obj/item/clothing/under/rank/medical
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat
+ l_hand = /obj/item/weapon/storage/firstaid/regular
+ suit_store = /obj/item/device/flashlight/pen
+
+ backpack = /obj/item/weapon/storage/backpack/medic
+ satchel = /obj/item/weapon/storage/backpack/satchel_med
/*
Chemist
@@ -80,16 +90,19 @@ Chemist
supervisors = "the chief medical officer"
selection_color = "#ffeef0"
- default_pda = /obj/item/device/pda/chemist
- default_headset = /obj/item/device/radio/headset/headset_med
+ outfit = /datum/outfit/job/chemist
access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_mineral_storeroom)
minimal_access = list(access_medical, access_chemistry, access_mineral_storeroom)
-/datum/job/chemist/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chemist(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/white(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/labcoat/chemist(H), slot_wear_suit)
+/datum/outfit/job/chemist
+ name = "Chemist"
+
+ belt = /obj/item/device/pda/chemist
+ ears = /obj/item/device/radio/headset/headset_med
+ uniform = /obj/item/clothing/under/rank/chemist
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat/chemist
/*
Geneticist
@@ -105,17 +118,20 @@ Geneticist
supervisors = "the chief medical officer and research director"
selection_color = "#ffeef0"
- default_pda = /obj/item/device/pda/geneticist
- default_headset = /obj/item/device/radio/headset/headset_medsci
+ outfit = /datum/outfit/job/geneticist
access = list(access_medical, access_morgue, access_chemistry, access_virology, access_genetics, access_research, access_xenobiology, access_robotics, access_mineral_storeroom, access_tech_storage)
minimal_access = list(access_medical, access_morgue, access_genetics, access_research)
-/datum/job/geneticist/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/geneticist(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/white(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/labcoat/genetics(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store)
+/datum/outfit/job/geneticist
+ name = "Geneticist"
+
+ belt = /obj/item/device/pda/geneticist
+ ears = /obj/item/device/radio/headset/headset_medsci
+ uniform = /obj/item/clothing/under/rank/geneticist
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat/genetics
+ suit_store = /obj/item/device/flashlight/pen
/*
Virologist
@@ -131,18 +147,21 @@ Virologist
supervisors = "the chief medical officer"
selection_color = "#ffeef0"
- default_pda = /obj/item/device/pda/viro
- default_headset = /obj/item/device/radio/headset/headset_med
- default_backpack = /obj/item/weapon/storage/backpack/medic
- default_satchel = /obj/item/weapon/storage/backpack/satchel_med
+ outfit = /datum/outfit/job/virologist
access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_mineral_storeroom)
minimal_access = list(access_medical, access_virology, access_mineral_storeroom)
-/datum/job/virologist/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/virologist(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/mask/surgical(H), slot_wear_mask)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/white(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/labcoat/virologist(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store)
+/datum/outfit/job/virologist
+ name = "Virologist"
+ belt = /obj/item/device/pda/viro
+ ears = /obj/item/device/radio/headset/headset_med
+ uniform = /obj/item/clothing/under/rank/virologist
+ mask = /obj/item/clothing/mask/surgical
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat/virologist
+ suit_store = /obj/item/device/flashlight/pen
+
+ backpack = /obj/item/weapon/storage/backpack/medic
+ satchel = /obj/item/weapon/storage/backpack/satchel_med
\ No newline at end of file
diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm
index f6b4c365bb8..0846f84c16b 100644
--- a/code/game/jobs/job/science.dm
+++ b/code/game/jobs/job/science.dm
@@ -14,9 +14,7 @@ Research Director
req_admin_notify = 1
minimal_player_age = 7
- default_id = /obj/item/weapon/card/id/silver
- default_pda = /obj/item/device/pda/heads/rd
- default_headset = /obj/item/device/radio/headset/heads/rd
+ outfit = /datum/outfit/job/rd
access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue,
access_tox_storage, access_teleporter, access_sec_doors,
@@ -29,14 +27,21 @@ Research Director
access_RC_announce, access_keycard_auth, access_gateway, access_mineral_storeroom,
access_tech_storage, access_minisat)
-/datum/job/rd/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/brown(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/research_director(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/labcoat(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/weapon/clipboard(H), slot_l_hand)
- H.equip_to_slot_or_del(new /obj/item/device/laser_pointer(H), slot_l_store)
- H.equip_to_slot_or_del(new /obj/item/weapon/melee/classic_baton/telescopic(H), slot_in_backpack)
+/datum/outfit/job/rd
+ name = "Research Director"
+ id = /obj/item/weapon/card/id/silver
+ belt = /obj/item/device/pda/heads/rd
+ ears = /obj/item/device/radio/headset/heads/rd
+ uniform = /obj/item/clothing/under/rank/research_director
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ suit = /obj/item/clothing/suit/toggle/labcoat
+ l_hand = /obj/item/weapon/clipboard
+ l_pocket = /obj/item/device/laser_pointer
+ backpack_contents = list(/obj/item/weapon/melee/classic_baton/telescopic=1)
+
+/datum/outfit/job/rd/post_equip(mob/living/carbon/human/H)
+ ..()
announce_head(H, list("Science")) //tell underlings (science radio) they have a head
/*
@@ -53,16 +58,19 @@ Scientist
supervisors = "the research director"
selection_color = "#ffeeff"
- default_pda = /obj/item/device/pda/toxins
- default_headset = /obj/item/device/radio/headset/headset_sci
+ outfit = /datum/outfit/job/scientist
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_mineral_storeroom, access_tech_storage, access_genetics)
minimal_access = list(access_tox, access_tox_storage, access_research, access_xenobiology, access_mineral_storeroom)
-/datum/job/scientist/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/white(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/labcoat/science(H), slot_wear_suit)
+/datum/outfit/job/scientist
+ name = "Scientist"
+
+ belt = /obj/item/device/pda/toxins
+ ears = /obj/item/device/radio/headset/headset_sci
+ uniform = /obj/item/clothing/under/rank/scientist
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat/science
/*
Roboticist
@@ -78,15 +86,18 @@ Roboticist
supervisors = "research director"
selection_color = "#ffeeff"
- default_pda = /obj/item/device/pda/roboticist
- default_headset = /obj/item/device/radio/headset/headset_sci
- default_pda_slot = slot_l_store
+ outfit = /datum/outfit/job/roboticist
access = list(access_robotics, access_tox, access_tox_storage, access_tech_storage, access_morgue, access_research, access_mineral_storeroom, access_xenobiology, access_genetics)
minimal_access = list(access_robotics, access_tech_storage, access_morgue, access_research, access_mineral_storeroom)
-/datum/job/roboticist/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/roboticist(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/labcoat(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt)
\ No newline at end of file
+/datum/outfit/job/roboticist
+ name = "Roboticist"
+
+ belt = /obj/item/weapon/storage/belt/utility/full
+ l_pocket = /obj/item/device/pda/roboticist
+ ears = /obj/item/device/radio/headset/headset_sci
+ uniform = /obj/item/clothing/under/rank/roboticist
+ suit = /obj/item/clothing/suit/toggle/labcoat
+
+ pda_slot = slot_l_store
diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm
index 616c05e9a05..89425545dcf 100644
--- a/code/game/jobs/job/security.dm
+++ b/code/game/jobs/job/security.dm
@@ -20,11 +20,7 @@ Head of Security
req_admin_notify = 1
minimal_player_age = 14
- default_id = /obj/item/weapon/card/id/silver
- default_pda = /obj/item/device/pda/heads/hos
- default_headset = /obj/item/device/radio/headset/heads/hos/alt
- default_backpack = /obj/item/weapon/storage/backpack/security
- default_satchel = /obj/item/weapon/storage/backpack/satchel_sec
+ outfit = /datum/outfit/job/hos
access = list(access_security, access_sec_doors, access_brig, access_armory, access_court, access_weapons,
access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers,
@@ -35,25 +31,33 @@ Head of Security
access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting,
access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway)
-/datum/job/hos/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_security(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/hos/trenchcoat(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black/hos(H), slot_gloves)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/HoS/beret(H), slot_head)
- H.equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/security/sunglasses(H), slot_glasses)
- H.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun(H), slot_s_store)
+/datum/outfit/job/hos
+ name = "Head of Security"
- H.equip_to_slot_or_del(new /obj/item/weapon/restraints/handcuffs(H), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/weapon/melee/classic_baton/telescopic(H), slot_in_backpack)
+ id = /obj/item/weapon/card/id/silver
+ belt = /obj/item/device/pda/heads/hos
+ ears = /obj/item/device/radio/headset/heads/hos/alt
+ uniform = /obj/item/clothing/under/rank/head_of_security
+ shoes = /obj/item/clothing/shoes/jackboots
+ suit = /obj/item/clothing/suit/armor/hos/trenchcoat
+ gloves = /obj/item/clothing/gloves/color/black/hos
+ head = /obj/item/clothing/head/HoS/beret
+ glasses = /obj/item/clothing/glasses/hud/security/sunglasses
+ suit_store = /obj/item/weapon/gun/energy/gun
+ backpack_contents = list(/obj/item/weapon/melee/classic_baton/telescopic=1,\
+ /obj/item/weapon/restraints/handcuffs=1)
+ backpack = /obj/item/weapon/storage/backpack/security
+ satchel = /obj/item/weapon/storage/backpack/satchel_sec
+
+/datum/outfit/job/hos/post_equip(mob/living/carbon/human/H)
+ ..()
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
L.imp_in = H
L.implanted = 1
H.sec_hud_set_implants()
announce_head(H, list("Security")) //tell underlings (security radio) they have a head
-
/*
Warden
*/
@@ -69,36 +73,41 @@ Warden
selection_color = "#ffeeee"
minimal_player_age = 7
- default_pda = /obj/item/device/pda/warden
- default_headset = /obj/item/device/radio/headset/headset_sec/alt
- default_backpack = /obj/item/weapon/storage/backpack/security
- default_satchel = /obj/item/weapon/storage/backpack/satchel_sec
+ outfit = /datum/outfit/job/warden
access = list(access_security, access_sec_doors, access_brig, access_armory, access_court, access_maint_tunnels, access_morgue, access_weapons, access_forensics_lockers)
minimal_access = list(access_security, access_sec_doors, access_brig, access_armory, access_court, access_weapons) //See /datum/job/warden/get_access()
-/datum/job/warden/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/warden(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/vest/warden(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/warden(H), slot_head)
- H.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black(H), slot_gloves)
- H.equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/security/sunglasses(H), slot_glasses)
- H.equip_to_slot_or_del(new /obj/item/device/flash/handheld(H), slot_l_store)
- H.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun/advtaser(H), slot_s_store)
-
- H.equip_to_slot_or_del(new /obj/item/weapon/restraints/handcuffs(H), slot_in_backpack)
-
- var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
- L.imp_in = H
- L.implanted = 1
- H.sec_hud_set_implants()
-
/datum/job/warden/get_access()
var/list/L = list()
L = ..() | check_config_for_sec_maint()
return L
+/datum/outfit/job/warden
+ name = "Warden"
+
+ belt = /obj/item/device/pda/warden
+ ears = /obj/item/device/radio/headset/headset_sec/alt
+ uniform = /obj/item/clothing/under/rank/warden
+ shoes = /obj/item/clothing/shoes/jackboots
+ suit = /obj/item/clothing/suit/armor/vest/warden
+ gloves = /obj/item/clothing/gloves/color/black
+ head = /obj/item/clothing/head/warden
+ glasses = /obj/item/clothing/glasses/hud/security/sunglasses
+ l_pocket = /obj/item/device/assembly/flash/handheld
+ suit_store = /obj/item/weapon/gun/energy/gun/advtaser
+ backpack_contents = list(/obj/item/weapon/restraints/handcuffs=1)
+
+ backpack = /obj/item/weapon/storage/backpack/security
+ satchel = /obj/item/weapon/storage/backpack/satchel_sec
+
+/datum/outfit/job/warden/post_equip(mob/living/carbon/human/H)
+ ..()
+ var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
+ L.imp_in = H
+ L.implanted = 1
+ H.sec_hud_set_implants()
+
/*
Detective
*/
@@ -114,28 +123,32 @@ Detective
selection_color = "#ffeeee"
minimal_player_age = 7
- default_pda = /obj/item/device/pda/detective
- default_headset = /obj/item/device/radio/headset/headset_sec
+ outfit = /datum/outfit/job/detective
access = list(access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court, access_weapons, access_brig, access_security)
minimal_access = list(access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court, access_weapons)
-/datum/job/detective/equip_items(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/det(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/brown(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/det_hat(H), slot_head)
- H.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black(H), slot_gloves)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/det_suit(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/toy/crayon/white(H), slot_l_store)
- H.equip_to_slot_or_del(new /obj/item/weapon/lighter(H), slot_r_store)
+/datum/outfit/job/detective
+ name = "Detective"
- var/obj/item/clothing/mask/cigarette/cig = new /obj/item/clothing/mask/cigarette(H)
+ belt = /obj/item/device/pda/detective
+ ears = /obj/item/device/radio/headset/headset_sec
+ uniform = /obj/item/clothing/under/rank/det
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ suit = /obj/item/clothing/suit/det_suit
+ gloves = /obj/item/clothing/gloves/color/black
+ head = /obj/item/clothing/head/det_hat
+ l_pocket = /obj/item/toy/crayon/white
+ r_pocket = /obj/item/weapon/lighter
+ backpack_contents = list(/obj/item/weapon/storage/box/evidence=1,\
+ /obj/item/device/detective_scanner=1,\
+ /obj/item/weapon/melee/classic_baton/telescopic=1)
+ mask = /obj/item/clothing/mask/cigarette
+
+/datum/outfit/job/detective/post_equip(mob/living/carbon/human/H)
+ ..()
+ var/obj/item/clothing/mask/cigarette/cig = H.wear_mask
cig.light("")
- H.equip_to_slot_or_del(cig, slot_wear_mask)
-
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/weapon/melee/classic_baton/telescopic(H), slot_in_backpack)
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
L.imp_in = H
@@ -156,102 +169,109 @@ Security Officer
supervisors = "the head of security, and the head of your assigned department (if applicable)"
selection_color = "#ffeeee"
minimal_player_age = 7
- var/list/dep_access = null
- default_pda = /obj/item/device/pda/security
- default_headset = /obj/item/device/radio/headset/headset_sec/alt
- default_backpack = /obj/item/weapon/storage/backpack/security
- default_satchel = /obj/item/weapon/storage/backpack/satchel_sec
- default_storagebox = /obj/item/weapon/storage/box/security
+ outfit = /datum/outfit/job/security
access = list(access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels, access_morgue, access_weapons, access_forensics_lockers)
minimal_access = list(access_security, access_sec_doors, access_brig, access_court, access_weapons) //But see /datum/job/warden/get_access()
-/datum/job/officer/equip_items(mob/living/carbon/human/H)
- assign_sec_to_department(H)
+/datum/job/officer/get_access()
+ var/list/L = list()
+ L |= ..() | check_config_for_sec_maint()
+ return L
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/vest(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/sec(H), slot_head)
- H.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black(H), slot_gloves)
- H.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun/advtaser(H), slot_s_store)
- H.equip_to_slot_or_del(new /obj/item/device/flash/handheld(H), slot_l_store)
+var/list/sec_departments = list("engineering", "supply", "medical", "science")
- H.equip_to_slot_or_del(new /obj/item/weapon/restraints/handcuffs(H), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/weapon/melee/baton/loaded(H), slot_in_backpack)
+/datum/outfit/job/security
+ name = "Security Officer"
+
+ belt = /obj/item/device/pda/security
+ ears = /obj/item/device/radio/headset/headset_sec/alt
+ uniform = /obj/item/clothing/under/rank/security
+ gloves = /obj/item/clothing/gloves/color/black
+ head = /obj/item/clothing/head/helmet/sec
+ suit = /obj/item/clothing/suit/armor/vest
+ shoes = /obj/item/clothing/shoes/jackboots
+ l_pocket = /obj/item/device/assembly/flash/handheld
+ suit_store = /obj/item/weapon/gun/energy/gun/advtaser
+ backpack_contents = list(/obj/item/weapon/restraints/handcuffs=1,\
+ /obj/item/weapon/melee/baton/loaded=1)
+
+ backpack = /obj/item/weapon/storage/backpack/security
+ satchel = /obj/item/weapon/storage/backpack/satchel_sec
+ box = /obj/item/weapon/storage/box/security
+
+ var/department = null
+ var/tie = null
+ var/list/dep_access = null
+ var/destination = null
+ var/spawn_point = null
+
+/datum/outfit/job/security/pre_equip(mob/living/carbon/human/H)
+ ..()
+ if(sec_departments.len)
+ department = pick(sec_departments)
+ sec_departments -= department
+ switch(department)
+ if("supply")
+ ears = /obj/item/device/radio/headset/headset_sec/alt/department/supply
+ dep_access = list(access_mailsorting, access_mining)
+ destination = /area/security/checkpoint/supply
+ spawn_point = locate(/obj/effect/landmark/start/depsec/supply) in department_security_spawns
+ tie = /obj/item/clothing/tie/armband/cargo
+ if("engineering")
+ ears = /obj/item/device/radio/headset/headset_sec/alt/department/engi
+ dep_access = list(access_construction, access_engine)
+ destination = /area/security/checkpoint/engineering
+ spawn_point = locate(/obj/effect/landmark/start/depsec/engineering) in department_security_spawns
+ tie = /obj/item/clothing/tie/armband/engine
+ if("medical")
+ ears = /obj/item/device/radio/headset/headset_sec/alt/department/med
+ dep_access = list(access_medical)
+ destination = /area/security/checkpoint/medical
+ spawn_point = locate(/obj/effect/landmark/start/depsec/medical) in department_security_spawns
+ tie = /obj/item/clothing/tie/armband/medblue
+ if("science")
+ ears = /obj/item/device/radio/headset/headset_sec/alt/department/sci
+ dep_access = list(access_research)
+ destination = /area/security/checkpoint/science
+ spawn_point = locate(/obj/effect/landmark/start/depsec/science) in department_security_spawns
+ tie = /obj/item/clothing/tie/armband/science
+
+/datum/outfit/job/security/post_equip(mob/living/carbon/human/H)
+ ..()
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
L.imp_in = H
L.implanted = 1
H.sec_hud_set_implants()
-/datum/job/officer/get_access()
- var/list/L = list()
- if(dep_access)
- L |= dep_access.Copy()
- L |= ..() | check_config_for_sec_maint()
- dep_access = null;
- return L
+ var/obj/item/clothing/under/U = H.w_uniform
+ if(tie)
+ U.attachTie(new tie)
-var/list/sec_departments = list("engineering", "supply", "medical", "science")
+ var/obj/item/weapon/card/id/W = H.wear_id
+ W.access |= dep_access
-/datum/job/officer/proc/assign_sec_to_department(mob/living/carbon/human/H)
- if(!sec_departments.len)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/security(H), slot_w_uniform)
- else
- var/department = pick(sec_departments)
- sec_departments -= department
- var/destination = null
- var/obj/effect/landmark/start/depsec/spawn_point = null
- var/obj/item/clothing/under/U = new /obj/item/clothing/under/rank/security(H)
-
- switch(department)
- if("supply")
- default_headset = /obj/item/device/radio/headset/headset_sec/alt/department/supply
- dep_access = list(access_mailsorting, access_mining)
- destination = /area/security/checkpoint/supply
- spawn_point = locate(/obj/effect/landmark/start/depsec/supply) in department_security_spawns
- U.attachTie(new /obj/item/clothing/tie/armband/cargo())
- if("engineering")
- default_headset = /obj/item/device/radio/headset/headset_sec/alt/department/engi
- dep_access = list(access_construction, access_engine)
- destination = /area/security/checkpoint/engineering
- spawn_point = locate(/obj/effect/landmark/start/depsec/engineering) in department_security_spawns
- U.attachTie(new /obj/item/clothing/tie/armband/engine())
- if("medical")
- default_headset = /obj/item/device/radio/headset/headset_sec/alt/department/med
- dep_access = list(access_medical)
- destination = /area/security/checkpoint/medical
- spawn_point = locate(/obj/effect/landmark/start/depsec/medical) in department_security_spawns
- U.attachTie(new /obj/item/clothing/tie/armband/medblue())
- if("science")
- default_headset = /obj/item/device/radio/headset/headset_sec/alt/department/sci
- dep_access = list(access_research)
- destination = /area/security/checkpoint/science
- spawn_point = locate(/obj/effect/landmark/start/depsec/science) in department_security_spawns
- U.attachTie(new /obj/item/clothing/tie/armband/science())
-
- H.equip_to_slot_or_del(U, slot_w_uniform)
- var/teleport = 0
- if(!config.sec_start_brig)
- if(destination || spawn_point)
- teleport = 1
- if(teleport)
- var/turf/T
- if(spawn_point)
- T = get_turf(spawn_point)
- H.Move(T)
- else
- var/safety = 0
- while(safety < 25)
- T = safepick(get_area_turfs(destination))
- if(T && !H.Move(T))
- safety += 1
- continue
- else
- break
- H << "You have been assigned to [department]!"
- return
+ var/teleport = 0
+ if(!config.sec_start_brig)
+ if(destination || spawn_point)
+ teleport = 1
+ if(teleport)
+ var/turf/T
+ if(spawn_point)
+ T = get_turf(spawn_point)
+ H.Move(T)
+ else
+ var/safety = 0
+ while(safety < 25)
+ T = safepick(get_area_turfs(destination))
+ if(T && !H.Move(T))
+ safety += 1
+ continue
+ else
+ break
+ H << "You have been assigned to [department]!"
/obj/item/device/radio/headset/headset_sec/department/New()
wires = new(src)
diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm
index 9bcc58643d7..e47d66df179 100644
--- a/code/game/jobs/jobs.dm
+++ b/code/game/jobs/jobs.dm
@@ -125,3 +125,15 @@ var/list/nonhuman_positions = list(
/proc/guest_jobbans(job)
return ((job in command_positions) || (job in nonhuman_positions) || (job in security_positions))
+
+
+
+//this is necessary because antags happen before job datums are handed out, but NOT before they come into existence
+//so I can't simply use job datum.department_head straight from the mind datum, laaaaame.
+/proc/get_department_heads(var/job_title)
+ if(!job_title)
+ return list()
+
+ for(var/datum/job/J in SSjob.occupations)
+ if(J.title == job_title)
+ return J.department_head //this is a list
\ No newline at end of file
diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm
index 057bc5b6adb..77d87856371 100644
--- a/code/game/machinery/Beacon.dm
+++ b/code/game/machinery/Beacon.dm
@@ -24,7 +24,7 @@
if(Beacon)
qdel(Beacon)
Beacon = null
- ..()
+ return ..()
// update the invisibility and icon
/obj/machinery/bluespace_beacon/hide(intact)
diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm
index 892052ea48d..51693e6ca51 100644
--- a/code/game/machinery/PDApainter.dm
+++ b/code/game/machinery/PDApainter.dm
@@ -46,13 +46,13 @@
user << "There is already a PDA inside!"
return
else
- var/obj/item/device/pda/P = usr.get_active_hand()
+ var/obj/item/device/pda/P = user.get_active_hand()
if(istype(P))
if(!user.drop_item())
return
storedpda = P
P.loc = src
- P.add_fingerprint(usr)
+ P.add_fingerprint(user)
update_icon()
diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm
index 0532fc63f3f..92f6bf099ca 100644
--- a/code/game/machinery/ai_slipper.dm
+++ b/code/game/machinery/ai_slipper.dm
@@ -3,7 +3,7 @@
icon = 'icons/obj/device.dmi'
icon_state = "motion3"
layer = 3
- anchored = 1.0
+ anchored = 1
var/uses = 20
var/disabled = 1
var/lethal = 0
diff --git a/code/game/machinery/airlock_control.dm b/code/game/machinery/airlock_control.dm
index bc593f7fc69..ece732690c3 100644
--- a/code/game/machinery/airlock_control.dm
+++ b/code/game/machinery/airlock_control.dm
@@ -95,7 +95,7 @@
/obj/machinery/door/airlock/Destroy()
if(frequency && radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
+ return ..()
/obj/machinery/airlock_sensor
icon = 'icons/obj/airlock_machines.dmi'
@@ -168,4 +168,4 @@
/obj/machinery/airlock_sensor/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
\ No newline at end of file
+ return ..()
\ No newline at end of file
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index cfcd3967614..a3603f2fc04 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -81,9 +81,9 @@
// breathable air according to human/Life()
var/list/TLV = list(
"oxygen" = new/datum/tlv( 16, 19, 135, 140), // Partial pressure, kpa
- "carbon dioxide" = new/datum/tlv(-1.0, -1.0, 5, 10), // Partial pressure, kpa
- "plasma" = new/datum/tlv(-1.0, -1.0, 0.2, 0.5), // Partial pressure, kpa
- "other" = new/datum/tlv(-1.0, -1.0, 0.5, 1.0), // Partial pressure, kpa
+ "carbon dioxide" = new/datum/tlv(-1, -1, 5, 10), // Partial pressure, kpa
+ "plasma" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
+ "other" = new/datum/tlv(-1, -1, 0.5, 1), // Partial pressure, kpa
"pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.10,ONE_ATMOSPHERE*1.20), /* kpa */
"temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66), // K
)
@@ -91,25 +91,25 @@
/*
// breathable air according to wikipedia
"oxygen" = new/datum/tlv( 9, 12, 158, 296), // Partial pressure, kpa
- "carbon dioxide" = new/datum/tlv(-1.0,-1.0, 0.5, 1), // Partial pressure, kpa
+ "carbon dioxide" = new/datum/tlv(-1,-1, 0.5, 1), // Partial pressure, kpa
*/
/obj/machinery/alarm/server
//req_access = list(access_rd) //no, let departaments to work together
TLV = list(
- "oxygen" = new/datum/tlv(-1.0, -1.0,-1.0,-1.0), // Partial pressure, kpa
- "carbon dioxide" = new/datum/tlv(-1.0, -1.0,-1.0,-1.0), // Partial pressure, kpa
- "plasma" = new/datum/tlv(-1.0, -1.0,-1.0,-1.0), // Partial pressure, kpa
- "other" = new/datum/tlv(-1.0, -1.0,-1.0,-1.0), // Partial pressure, kpa
- "pressure" = new/datum/tlv(-1.0, -1.0,-1.0,-1.0), /* kpa */
- "temperature" = new/datum/tlv(-1.0, -1.0,-1.0,-1.0), // K
+ "oxygen" = new/datum/tlv(-1, -1,-1,-1), // Partial pressure, kpa
+ "carbon dioxide" = new/datum/tlv(-1, -1,-1,-1), // Partial pressure, kpa
+ "plasma" = new/datum/tlv(-1, -1,-1,-1), // Partial pressure, kpa
+ "other" = new/datum/tlv(-1, -1,-1,-1), // Partial pressure, kpa
+ "pressure" = new/datum/tlv(-1, -1,-1,-1), /* kpa */
+ "temperature" = new/datum/tlv(-1, -1,-1,-1), // K
)
/obj/machinery/alarm/kitchen_cold_room
TLV = list(
"oxygen" = new/datum/tlv( 16, 19, 135, 140), // Partial pressure, kpa
- "carbon dioxide" = new/datum/tlv(-1.0, -1.0, 5, 10), // Partial pressure, kpa
- "plasma" = new/datum/tlv(-1.0, -1.0, 0.2, 0.5), // Partial pressure, kpa
- "other" = new/datum/tlv(-1.0, -1.0, 0.5, 1.0), // Partial pressure, kpa
+ "carbon dioxide" = new/datum/tlv(-1, -1, 5, 10), // Partial pressure, kpa
+ "plasma" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
+ "other" = new/datum/tlv(-1, -1, 0.5, 1), // Partial pressure, kpa
"pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.50,ONE_ATMOSPHERE*1.60), /* kpa */
"temperature" = new/datum/tlv(200, 210, 273.15, 283.15), // K
)
@@ -122,12 +122,9 @@
var/list/air_vent_info = list()
var/list/air_scrub_info = list()
-/obj/machinery/alarm/New(nloc, ndir, nbuild)
+/obj/machinery/alarm/New(loc, ndir, nbuild)
..()
wires = new(src)
- if(nloc)
- loc = nloc
-
if(ndir)
dir = ndir
@@ -151,7 +148,9 @@
/obj/machinery/alarm/Destroy()
if(radio_controller)
radio_controller.remove_object(src, frequency)
- ..()
+ qdel(wires)
+ wires = null
+ return ..()
/obj/machinery/alarm/initialize()
set_frequency(frequency)
@@ -296,7 +295,7 @@
environment_data += list(list("name" = "Toxins", "value" = environment.toxins / total * 100, "unit" = "%", "danger_level" = plasma_danger))
cur_tlv = TLV["other"]
- var/other_moles = 0.0
+ var/other_moles = 0
for(var/datum/gas/G in environment.trace_gases)
other_moles+=G.moles
var/other_danger = cur_tlv.get_danger_level(other_moles*partial_pressure)
@@ -455,7 +454,7 @@
if (isnull(newval) || ..() || (locked && !(usr.has_unlimited_silicon_privilege)))
return
if (newval<0)
- tlv.vars[varname] = -1.0
+ tlv.vars[varname] = -1
else if (env=="temperature" && newval>5000)
tlv.vars[varname] = 5000
else if (env=="pressure" && newval>50*ONE_ATMOSPHERE)
@@ -655,7 +654,7 @@
var/plasma_dangerlevel = cur_tlv.get_danger_level(environment.toxins*GET_PP)
cur_tlv = TLV["other"]
- var/other_moles = 0.0
+ var/other_moles = 0
for(var/datum/gas/G in environment.trace_gases)
other_moles+=G.moles
var/other_dangerlevel = cur_tlv.get_danger_level(other_moles*GET_PP)
@@ -753,7 +752,7 @@
if (do_after(user, 20, target = src))
if (buildstage == 1)
user <<"You remove the air alarm electronics."
- new /obj/item/weapon/airalarm_electronics( src.loc )
+ new /obj/item/weapon/electronics/airalarm( src.loc )
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
buildstage = 0
update_icon()
@@ -780,7 +779,7 @@
update_icon()
return
if(0)
- if(istype(W, /obj/item/weapon/airalarm_electronics))
+ if(istype(W, /obj/item/weapon/electronics/airalarm))
if(user.unEquip(W))
user << "You insert the circuit."
buildstage = 1
@@ -791,7 +790,7 @@
if(istype(W, /obj/item/weapon/wrench))
user << "You detach \the [src] from the wall."
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- new /obj/item/alarm_frame( user.loc )
+ new /obj/item/wallframe/alarm( user.loc )
qdel(src)
return
@@ -810,7 +809,8 @@
/obj/machinery/alarm/emag_act(mob/user)
if(!emagged)
src.emagged = 1
- user.visible_message("Sparks fly out of the [src]!", "You emag the [src], disabling its safeties.")
+ if(user)
+ user.visible_message("Sparks fly out of the [src]!", "You emag the [src], disabling its safeties.")
playsound(src.loc, 'sound/effects/sparks4.ogg', 50, 1)
return
@@ -819,58 +819,20 @@
AIR ALARM CIRCUIT
Just a object used in constructing air alarms
*/
-/obj/item/weapon/airalarm_electronics
+/obj/item/weapon/electronics/airalarm
name = "air alarm electronics"
- icon = 'icons/obj/module.dmi'
icon_state = "airalarm_electronics"
- desc = "Looks like a circuit. Probably is."
- w_class = 2.0
- materials = list(MAT_METAL=50, MAT_GLASS=50)
-
/*
AIR ALARM ITEM
Handheld air alarm frame, for placing on walls
-Code shamelessly copied from apc_frame
*/
-/obj/item/alarm_frame
+/obj/item/wallframe/alarm
name = "air alarm frame"
desc = "Used for building Air Alarms"
icon = 'icons/obj/monitors.dmi'
icon_state = "alarm_bitem"
- flags = CONDUCT
-
-/obj/item/alarm_frame/attackby(obj/item/weapon/W, mob/user, params)
- if (istype(W, /obj/item/weapon/wrench))
- new /obj/item/stack/sheet/metal( get_turf(src.loc), 2 )
- qdel(src)
- return
- ..()
-
-/obj/item/alarm_frame/proc/try_build(turf/on_wall)
- if (get_dist(on_wall,usr)>1)
- return
-
- var/ndir = get_dir(on_wall,usr)
- if (!(ndir in cardinal))
- return
-
- var/turf/loc = get_turf(usr)
- var/area/A = loc.loc
- if (!istype(loc, /turf/simulated/floor))
- usr << "Air Alarm cannot be placed on this spot!"
- return
- if (A.requires_power == 0 || A.name == "Space")
- usr << "Air Alarm cannot be placed in this area!"
- return
-
- if(gotwallitem(loc, ndir))
- usr << "There's already an item on this wall!"
- return
-
- new /obj/machinery/alarm(loc, ndir, 1)
-
- qdel(src)
+ result_path = /obj/machinery/alarm
/*
@@ -881,11 +843,11 @@ FIRE ALARM
desc = "\"Pull this in case of emergency\". Thus, keep pulling it forever."
icon = 'icons/obj/monitors.dmi'
icon_state = "fire0"
- var/detecting = 1.0
- var/time = 10.0
- var/timing = 0.0
+ var/detecting = 1
+ var/time = 10
+ var/timing = 0
var/lockdownbyai = 0
- anchored = 1.0
+ anchored = 1
use_power = 1
idle_power_usage = 2
active_power_usage = 6
@@ -894,7 +856,6 @@ FIRE ALARM
var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
/obj/machinery/firealarm/update_icon()
-
src.overlays = list()
var/area/A = src.loc
@@ -938,7 +899,8 @@ FIRE ALARM
/obj/machinery/firealarm/emag_act(mob/user)
if(!emagged)
src.emagged = 1
- user.visible_message("Sparks fly out of the [src]!", "You emag the [src], disabling its thermal sensors.")
+ if(user)
+ user.visible_message("Sparks fly out of the [src]!", "You emag the [src], disabling its thermal sensors.")
playsound(src.loc, 'sound/effects/sparks4.ogg', 50, 1)
return
@@ -1014,11 +976,11 @@ FIRE ALARM
user << "You remove the destroyed circuit."
else
user << "You pry out the circuit."
- new /obj/item/weapon/firealarm_electronics(user.loc)
+ new /obj/item/weapon/electronics/firealarm(user.loc)
buildstage = 0
update_icon()
if(0)
- if(istype(W, /obj/item/weapon/firealarm_electronics))
+ if(istype(W, /obj/item/weapon/electronics/firealarm))
user << "You insert the circuit."
qdel(W)
buildstage = 1
@@ -1027,7 +989,7 @@ FIRE ALARM
else if(istype(W, /obj/item/weapon/wrench))
user.visible_message("[user] removes the fire alarm assembly from the wall.", \
"You remove the fire alarm assembly from the wall.")
- var/obj/item/firealarm_frame/frame = new /obj/item/firealarm_frame()
+ var/obj/item/wallframe/firealarm/frame = new /obj/item/wallframe/firealarm()
frame.loc = user.loc
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
qdel(src)
@@ -1151,14 +1113,11 @@ FIRE ALARM
//playsound(src.loc, 'sound/ambience/signal.ogg', 75, 0)
return
-/obj/machinery/firealarm/New(loc, dir, building)
+/obj/machinery/firealarm/New(loc, ndir, building)
..()
- if(loc)
- src.loc = loc
-
- if(dir)
- src.dir = dir
+ if(ndir)
+ src.dir = ndir
if(building)
buildstage = 0
@@ -1178,59 +1137,21 @@ FIRE ALARM
FIRE ALARM CIRCUIT
Just a object used in constructing fire alarms
*/
-/obj/item/weapon/firealarm_electronics
+/obj/item/weapon/electronics/firealarm
name = "fire alarm electronics"
- icon = 'icons/obj/doors/door_assembly.dmi'
- icon_state = "door_electronics"
desc = "A circuit. It has a label on it, it says \"Can handle heat levels up to 40 degrees celsius!\""
- w_class = 2.0
- materials = list(MAT_METAL=50, MAT_GLASS=50)
/*
FIRE ALARM ITEM
Handheld fire alarm frame, for placing on walls
-Code shamelessly copied from apc_frame
*/
-/obj/item/firealarm_frame
+/obj/item/wallframe/firealarm
name = "fire alarm frame"
desc = "Used for building Fire Alarms"
icon = 'icons/obj/monitors.dmi'
icon_state = "fire_bitem"
- flags = CONDUCT
-
-
-/obj/item/firealarm_frame/attackby(obj/item/weapon/W, mob/user, params)
- if (istype(W, /obj/item/weapon/wrench))
- new /obj/item/stack/sheet/metal( get_turf(src.loc), 2 )
- qdel(src)
- return
- ..()
-
-/obj/item/firealarm_frame/proc/try_build(turf/on_wall)
- if (get_dist(on_wall,usr)>1)
- return
-
- var/ndir = get_dir(on_wall,usr)
- if (!(ndir in cardinal))
- return
-
- var/turf/loc = get_turf(usr)
- var/area/A = loc.loc
- if (!istype(loc, /turf/simulated/floor))
- usr << "Fire Alarm cannot be placed on this spot."
- return
- if (A.requires_power == 0 || A.name == "Space")
- usr << "Fire Alarm cannot be placed in this area."
- return
-
- if(gotwallitem(loc, ndir))
- usr << "There's already an item on this wall!"
- return
-
- new /obj/machinery/firealarm(loc, ndir, 1)
-
- qdel(src)
+ result_path = /obj/machinery/firealarm
/*
* Party button
diff --git a/code/game/machinery/announcement_system.dm b/code/game/machinery/announcement_system.dm
index 738d69b14cf..692bf7faceb 100644
--- a/code/game/machinery/announcement_system.dm
+++ b/code/game/machinery/announcement_system.dm
@@ -65,6 +65,7 @@ var/list/announcement_systems = list()
/obj/machinery/announcement_system/Destroy()
announcement_systems -= src //"OH GOD WHY ARE THERE 100,000 LISTED ANNOUNCEMENT SYSTEMS?!!"
+ return ..()
/obj/machinery/announcement_system/power_change()
..()
diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm
index 38cc653cda8..1c71111943c 100644
--- a/code/game/machinery/atmo_control.dm
+++ b/code/game/machinery/atmo_control.dm
@@ -81,7 +81,7 @@
SSair.atmos_machinery -= src
if(radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
+ return ..()
/////////////////////////////////////////////////////////////
// GENERAL AIR CONTROL (a.k.a atmos computer)
@@ -180,7 +180,7 @@
/obj/machinery/computer/general_air_control/Destroy()
if(radio_controller)
radio_controller.remove_object(src, frequency)
- ..()
+ return ..()
/obj/machinery/computer/general_air_control/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm
index 82f0e3a1a78..cfd7a1cca0f 100644
--- a/code/game/machinery/atmoalter/canister.dm
+++ b/code/game/machinery/atmoalter/canister.dm
@@ -1,9 +1,10 @@
/obj/machinery/portable_atmospherics/canister
name = "canister"
+ desc = "A canister for the storage of gas."
icon = 'icons/obj/atmos.dmi'
icon_state = "yellow"
density = 1
- var/health = 100.0
+ var/health = 100
var/valve_open = 0
var/release_pressure = ONE_ATMOSPHERE
@@ -21,31 +22,37 @@
/obj/machinery/portable_atmospherics/canister/sleeping_agent
name = "canister: \[N2O\]"
+ desc = "Nitrous oxide gas. Known to cause drowsiness."
icon_state = "redws"
canister_color = "redws"
can_label = 0
/obj/machinery/portable_atmospherics/canister/nitrogen
name = "canister: \[N2\]"
+ desc = "Nitrogen gas. Reportedly useful for something."
icon_state = "red"
canister_color = "red"
can_label = 0
/obj/machinery/portable_atmospherics/canister/oxygen
name = "canister: \[O2\]"
+ desc = "Oxygen. Necessary for human life."
icon_state = "blue"
canister_color = "blue"
can_label = 0
/obj/machinery/portable_atmospherics/canister/toxins
- name = "canister \[Toxin (Bio)\]"
+ name = "canister \[Plasma\]"
+ desc = "Plasma gas. The reason YOU are here. Highly toxic."
icon_state = "orange"
canister_color = "orange"
can_label = 0
/obj/machinery/portable_atmospherics/canister/carbon_dioxide
name = "canister \[CO2\]"
+ desc = "Carbon dioxide. What the fuck is carbon dioxide?"
icon_state = "black"
canister_color = "black"
can_label = 0
/obj/machinery/portable_atmospherics/canister/air
name = "canister \[Air\]"
+ desc = "Pre-mixed air."
icon_state = "grey"
canister_color = "grey"
can_label = 0
@@ -210,21 +217,21 @@ update_flag
/obj/machinery/portable_atmospherics/canister/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
if(destroyed || prob(30))
qdel(src)
else
src.health = 0
healthcheck()
return
- if(2.0)
+ if(2)
if(destroyed)
qdel(src)
else
src.health -= rand(40, 100)
healthcheck()
return
- if(3.0)
+ if(3)
src.health -= rand(15,40)
healthcheck()
return
@@ -347,7 +354,7 @@ update_flag
"\[N2O\]" = "redws", \
"\[N2\]" = "red", \
"\[O2\]" = "blue", \
- "\[Toxin (Bio)\]" = "orange", \
+ "\[Plasma\]" = "orange", \
"\[CO2\]" = "black", \
"\[Air\]" = "grey", \
"\[CAUTION\]" = "yellow", \
diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm
index 5f6835bff24..3c2b7019529 100644
--- a/code/game/machinery/atmoalter/meter.dm
+++ b/code/game/machinery/atmoalter/meter.dm
@@ -4,7 +4,7 @@
icon = 'icons/obj/meter.dmi'
icon_state = "meterX"
var/obj/machinery/atmospherics/pipe/target = null
- anchored = 1.0
+ anchored = 1
power_channel = ENVIRON
var/frequency = 0
var/id
@@ -21,7 +21,7 @@
/obj/machinery/meter/Destroy()
SSair.atmos_machinery -= src
src.target = null
- ..()
+ return ..()
/obj/machinery/meter/initialize()
if (!target)
diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm
index e484b42e4c3..5384871b48e 100644
--- a/code/game/machinery/atmoalter/portable_atmospherics.dm
+++ b/code/game/machinery/atmoalter/portable_atmospherics.dm
@@ -30,7 +30,7 @@
/obj/machinery/portable_atmospherics/Destroy()
qdel(air_contents)
SSair.atmos_machinery -= src
- ..()
+ return ..()
/obj/machinery/portable_atmospherics/update_icon()
return null
@@ -47,7 +47,7 @@
//Perform the connection
connected_port = new_port
connected_port.connected_device = src
- var/datum/pipeline/connected_port_parent = connected_port.parents[PARENT1]
+ var/datum/pipeline/connected_port_parent = connected_port.PARENT1
connected_port_parent.reconcile_air()
anchored = 1 //Prevent movement
diff --git a/code/game/machinery/atmoalter/zvent.dm b/code/game/machinery/atmoalter/zvent.dm
index 7b3081092f1..deb83600c99 100644
--- a/code/game/machinery/atmoalter/zvent.dm
+++ b/code/game/machinery/atmoalter/zvent.dm
@@ -15,7 +15,7 @@
/obj/machinery/zvent/Destroy()
SSair.atmos_machinery -= src
- ..()
+ return ..()
/obj/machinery/zvent/process_atmos()
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 73026e5dac1..7472f7c6087 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -8,8 +8,8 @@
icon_state = "autolathe"
density = 1
- var/operating = 0.0
- anchored = 1.0
+ var/operating = 0
+ anchored = 1
var/list/L = list()
var/list/LL = list()
var/hacked = 0
@@ -59,6 +59,13 @@
files = new /datum/research/autolathe(src)
matching_designs = list()
+/obj/machinery/autolathe/Destroy()
+ qdel(wires)
+ wires = null
+ qdel(materials)
+ materials = null
+ return ..()
+
/obj/machinery/autolathe/interact(mob/user)
if(!is_operational())
return
@@ -109,7 +116,7 @@
if (stat)
return 1
- var/material_amount = materials.can_insert(O)
+ var/material_amount = materials.get_item_material_amount(O)
if(!material_amount)
user << "This object does not contain sufficient amounts of metal or glass to be accepted by the autolathe."
return 1
diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm
index 9c6639c3bd7..5a64e5ac3ea 100644
--- a/code/game/machinery/bots/bots.dm
+++ b/code/game/machinery/bots/bots.dm
@@ -10,8 +10,8 @@
var/on = 1
var/health = 0 //do not forget to set health for your bot!
var/maxhealth = 0
- var/fire_dam_coeff = 1.0
- var/brute_dam_coeff = 1.0
+ var/fire_dam_coeff = 1
+ var/brute_dam_coeff = 1
var/open = 0//Maint panel
var/locked = 1
var/hacked = 0 //Used to differentiate between being hacked by silicons and emagged by humans.
@@ -70,17 +70,16 @@
#define BOT_MOVING 9 // for clean/floor/med bots, when moving.
#define BOT_HEALING 10 // healing people (medbots)
#define BOT_RESPONDING 11 // responding to a call from the AI
- #define BOT_LOADING 12 // loading/unloading
- #define BOT_DELIVER 13 // moving to deliver
- #define BOT_GO_HOME 14 // returning to home
- #define BOT_BLOCKED 15 // blocked
- #define BOT_NAV 16 // computing navigation
- #define BOT_WAIT_FOR_NAV 17 // waiting for nav computation
- #define BOT_NO_ROUTE 18 // no destination beacon found (or no route)
+ #define BOT_DELIVER 12 // moving to deliver
+ #define BOT_GO_HOME 13 // returning to home
+ #define BOT_BLOCKED 14 // blocked
+ #define BOT_NAV 15 // computing navigation
+ #define BOT_WAIT_FOR_NAV 16 // waiting for nav computation
+ #define BOT_NO_ROUTE 17 // no destination beacon found (or no route)
var/list/mode_name = list("In Pursuit","Preparing to Arrest", "Arresting", \
"Beginning Patrol", "Patrolling", "Summoned by PDA", \
"Cleaning", "Repairing", "Proceeding to work site", "Healing", \
- "Proceeding to AI waypoint", "Loading/Unloading", "Navigating to Delivery Location", "Navigating to Home", \
+ "Proceeding to AI waypoint", "Navigating to Delivery Location", "Navigating to Home", \
"Waiting for clear path", "Calculating navigation path", "Pinging beacon network", "Unable to reach destination")
//This holds text for what the bot is mode doing, reported on the remote bot control interface.
@@ -114,7 +113,7 @@
/obj/machinery/bot/Destroy()
qdel(Radio)
qdel(botcard)
- ..()
+ return ..()
/obj/machinery/bot/proc/explode()
@@ -297,15 +296,15 @@
/obj/machinery/bot/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
explode()
return
- if(2.0)
+ if(2)
health -= rand(5,10)*fire_dam_coeff
health -= rand(10,20)*brute_dam_coeff
healthcheck()
return
- if(3.0)
+ if(3)
if (prob(50))
health -= rand(1,5)*fire_dam_coeff
health -= rand(1,5)*brute_dam_coeff
diff --git a/code/game/machinery/bots/cleanbot.dm b/code/game/machinery/bots/cleanbot.dm
index ea5613108f7..00f14c4a61b 100644
--- a/code/game/machinery/bots/cleanbot.dm
+++ b/code/game/machinery/bots/cleanbot.dm
@@ -4,11 +4,11 @@
name = "proxy bucket"
icon = 'icons/obj/aibots.dmi'
icon_state = "bucket_proxy"
- force = 3.0
- throwforce = 5.0
+ force = 3
+ throwforce = 5
throw_speed = 2
throw_range = 5
- w_class = 3.0
+ w_class = 3.
var/created_name = "Cleanbot"
@@ -18,7 +18,7 @@
desc = "A little cleaning robot, he looks so excited!"
icon = 'icons/obj/aibots.dmi'
icon_state = "cleanbot0"
- layer = 5.0
+ layer = 5
density = 0
anchored = 0
//weight = 1.0E7
@@ -151,7 +151,7 @@ text("[on ? "On" : "Off"]"))
PoolOrNew(/obj/effect/effect/foam, loc)
else if (prob(5))
- visible_message("[src] makes an excited beeping booping sound!")
+ audible_message("[src] makes an excited beeping booping sound!")
if(!target) //Search for cleanables it can see.
target = scan(/obj/effect/decal/cleanable/)
diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm
index 140fc457c41..57378c735e1 100644
--- a/code/game/machinery/bots/ed209bot.dm
+++ b/code/game/machinery/bots/ed209bot.dm
@@ -3,7 +3,7 @@
desc = "A security robot. He looks less than thrilled."
icon = 'icons/obj/aibots.dmi'
icon_state = "ed2090"
- layer = 5.0
+ layer = 5
density = 1
anchored = 0
// weight = 1.0E7
diff --git a/code/game/machinery/bots/floorbot.dm b/code/game/machinery/bots/floorbot.dm
index 75194d08fcd..7f107e9892b 100644
--- a/code/game/machinery/bots/floorbot.dm
+++ b/code/game/machinery/bots/floorbot.dm
@@ -4,11 +4,11 @@
name = "tiles and toolbox"
icon = 'icons/obj/aibots.dmi'
icon_state = "toolbox_tiles"
- force = 3.0
- throwforce = 10.0
+ force = 3
+ throwforce = 10
throw_speed = 2
throw_range = 5
- w_class = 3.0
+ w_class = 3
var/created_name = "Floorbot"
/obj/item/weapon/toolbox_tiles_sensor
@@ -16,11 +16,11 @@
name = "tiles, toolbox and sensor arrangement"
icon = 'icons/obj/aibots.dmi'
icon_state = "toolbox_tiles_sensor"
- force = 3.0
- throwforce = 10.0
+ force = 3
+ throwforce = 10
throw_speed = 2
throw_range = 5
- w_class = 3.0
+ w_class = 3
var/created_name = "Floorbot"
//Floorbot
@@ -29,7 +29,7 @@
desc = "A little floor repairing robot, he looks so excited!"
icon = 'icons/obj/aibots.dmi'
icon_state = "floorbot0"
- layer = 5.0
+ layer = 5
density = 0
anchored = 0
health = 25
@@ -216,7 +216,7 @@
nag()
if(prob(5))
- visible_message("[src] makes an excited booping beeping sound!")
+ audible_message("[src] makes an excited booping beeping sound!")
//Normal scanning procedure. We have tiles loaded, are not emagged.
if(!target && emagged < 2 && amount > 0)
@@ -289,7 +289,7 @@
F.break_tile_to_plating()
else
F.ReplaceWithLattice()
- visible_message("[src] makes an excited booping sound.")
+ audible_message("[src] makes an excited booping sound.")
spawn(50)
amount ++
anchored = 0
diff --git a/code/game/machinery/bots/medbot.dm b/code/game/machinery/bots/medbot.dm
index 620b163560a..a7a49945a18 100644
--- a/code/game/machinery/bots/medbot.dm
+++ b/code/game/machinery/bots/medbot.dm
@@ -8,7 +8,7 @@
desc = "A little medical robot. He looks somewhat underwhelmed."
icon = 'icons/obj/aibots.dmi'
icon_state = "medibot0"
- layer = 5.0
+ layer = 5
density = 0
anchored = 0
health = 20
@@ -70,7 +70,7 @@
var/build_step = 0
var/created_name = "Medibot" //To preserve the name if it's a unique medbot I guess
var/skin = null //Same as medbot, set to tox or ointment for the respective kits.
- w_class = 3.0
+ w_class = 3
/obj/item/weapon/firstaid_arm_assembly/New()
..()
@@ -110,7 +110,6 @@
/obj/machinery/bot/medbot/turn_off()
..()
- updateicon()
updateUsrDialog()
/obj/machinery/bot/medbot/bot_reset()
@@ -120,12 +119,14 @@
oldloc = null
last_found = world.time
declare_cooldown = 0
+ updateicon()
/obj/machinery/bot/medbot/proc/soft_reset() //Allows the medibot to still actively perform its medical duties without being completely halted as a hard reset does.
path = list()
patient = null
mode = BOT_IDLE
last_found = world.time
+ updateicon()
/obj/machinery/bot/medbot/set_custom_texts()
@@ -415,18 +416,14 @@
if(!istype(C))
oldpatient = patient
- patient = null
- mode = BOT_IDLE
- last_found = world.time
+ soft_reset()
return
if(C.stat == 2)
var/death_message = pick("No! NO!","Live, damnit! LIVE!","I...I've never lost a patient before. Not today, I mean.")
speak(death_message)
oldpatient = patient
- patient = null
- mode = BOT_IDLE
- last_found = world.time
+ soft_reset()
return
var/reagent_id = null
@@ -472,13 +469,9 @@
break
if(!reagent_id) //If they don't need any of that they're probably cured!
- oldpatient = patient
- patient = null
- mode = BOT_IDLE
- last_found = world.time
var/message = pick("All patched up!","An apple a day keeps me away.","Feel better soon!")
speak(message)
- updateicon()
+ bot_reset()
return
else
C.visible_message("[src] is trying to inject [patient]!", \
@@ -495,12 +488,10 @@
patient.reagents.add_reagent(reagent_id,injection_amount)
C.visible_message("[src] injects [patient] with its syringe!", \
"[src] injects you with its syringe!")
- patient = null
else
visible_message("[src] retracts its syringe.")
- mode = BOT_IDLE
- updateicon()
+ soft_reset()
return
reagent_id = null
diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm
index 68643c28cb6..0eadb6ab95f 100644
--- a/code/game/machinery/bots/mulebot.dm
+++ b/code/game/machinery/bots/mulebot.dm
@@ -6,6 +6,11 @@
var/global/mulebot_count = 0
+
+#define SIGH 0
+#define ANNOYED 1
+#define DELIGHT 2
+
/obj/machinery/bot/mulebot
name = "\improper MULEbot"
desc = "A Multiple Utility Load Effector bot."
@@ -21,14 +26,15 @@ var/global/mulebot_count = 0
var/atom/movable/load = null
bot_type = MULE_BOT
model = "MULE"
- blood_DNA = list()
+ can_buckle = 1
+ buckle_lying = 0
suffix = ""
var/turf/target // this is turf to navigate to (location of beacon)
var/loaddir = 0 // this the direction to unload onto/load from
var/home_destination = "" // tag of home beacon
- req_access = list(access_cargo)
+ req_access = list(access_cargo)
mode = BOT_IDLE
@@ -72,11 +78,37 @@ var/global/mulebot_count = 0
suffix = "#[mulebot_count]"
name = "\improper Mulebot ([suffix])"
+/obj/machinery/bot/mulebot/Destroy()
+ unload(0)
+ qdel(wires)
+ wires = null
+ return ..()
+
obj/machinery/bot/mulebot/bot_reset()
..()
reached_target = 0
+obj/machinery/bot/mulebot/Move(atom/newloc, direct)
+ . = ..()
+ if(buckled_mob)
+ if(!buckled_mob.Move(loc, direct))
+ loc = buckled_mob.loc //we gotta go back
+ last_move = buckled_mob.last_move
+ inertia_dir = last_move
+ buckled_mob.inertia_dir = last_move
+ . = 0
+
+obj/machinery/bot/mulebot/Process_Spacemove(movement_dir = 0)
+ if(buckled_mob)
+ return buckled_mob.Process_Spacemove(movement_dir)
+ return ..()
+
+obj/machinery/bot/mulebot/CanPass(atom/movable/mover, turf/target, height=1.5)
+ if(mover == buckled_mob)
+ return 1
+ return ..()
+
// attack by item
// emag : lock/unlock,
// screwdriver: open/close hatch
@@ -183,8 +215,6 @@ obj/machinery/bot/mulebot/bot_reset()
switch(mode)
if(BOT_IDLE)
dat += "Ready"
- if(BOT_LOADING)
- dat += "[mode_name[BOT_LOADING]]"
if(BOT_DELIVER)
dat += "[mode_name[BOT_DELIVER]]"
if(BOT_GO_HOME)
@@ -358,7 +388,7 @@ obj/machinery/bot/mulebot/bot_reset()
updateDialog()
if("unload")
- if(load && mode !=1)
+ if(load && mode != BOT_HUNT)
if(loc == target)
unload(loaddir)
else
@@ -379,7 +409,6 @@ obj/machinery/bot/mulebot/bot_reset()
-
// returns true if the bot has power
/obj/machinery/bot/mulebot/proc/has_power()
return !open && cell && cell.charge > 0 && wires.HasPower()
@@ -393,66 +422,94 @@ obj/machinery/bot/mulebot/bot_reset()
user << "Access denied."
return 0
+/obj/machinery/bot/mulebot/proc/buzz(type)
+ switch(type)
+ if(SIGH)
+ audible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.")
+ playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
+ if(ANNOYED)
+ audible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.")
+ playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
+ if(DELIGHT)
+ audible_message("[src] makes a delighted ping!", "You hear a ping.")
+ playsound(loc, 'sound/machines/ping.ogg', 50, 0)
+
+
// mousedrop a crate to load the bot
// can load anything if emagged
+/obj/machinery/bot/mulebot/MouseDrop_T(atom/movable/AM, mob/user)
-/obj/machinery/bot/mulebot/MouseDrop_T(atom/movable/C, mob/user)
-
- if(user.stat)
+ if(user.incapacitated() || user.lying)
return
- if (!on || !istype(C)|| C.anchored || get_dist(user, src) > 1 || get_dist(src,C) > 1 )
+ if (!istype(AM))
return
- if(load)
- return
-
- load(C)
-
+ load(AM)
// called to load a crate
-/obj/machinery/bot/mulebot/proc/load(atom/movable/C)
- if(wires.LoadCheck() && !istype(C,/obj/structure/closet/crate))
- visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.")
- playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
- return // if not emagged, only allow crates to be loaded
-
- //I'm sure someone will come along and ask why this is here... well people were dragging screen items onto the mule, and that was not cool.
- //So this is a simple fix that only allows a selection of item types to be considered. Further narrowing-down is below.
- if(!istype(C,/obj/item) && !istype(C,/obj/machinery) && !istype(C,/obj/structure) && !ismob(C))
- return
- if(!isturf(C.loc)) //To prevent the loading from stuff from someone's inventory, which wouldn't get handled properly.
+/obj/machinery/bot/mulebot/proc/load(atom/movable/AM)
+ if(load || AM.anchored)
return
- if(get_dist(C, src) > 1 || load || !on)
+ if(!isturf(AM.loc)) //To prevent the loading from stuff from someone's inventory or screen icons.
return
- mode = BOT_LOADING
- // if a create, close before loading
- var/obj/structure/closet/crate/crate = C
- if(istype(crate))
- crate.close()
+ var/obj/structure/closet/crate/CRATE
+ if(istype(AM,/obj/structure/closet/crate))
+ CRATE = AM
+ else
+ if(wires.LoadCheck())
+ buzz(SIGH)
+ return // if not emagged, only allow crates to be loaded
- C.loc = loc
- sleep(2)
- if(C.loc != loc) //To prevent you from going onto more thano ne bot.
- return
- C.loc = src
- load = C
+ if(CRATE) // if it's a crate, close before loading
+ CRATE.close()
- C.pixel_y += 9
- if(C.layer < layer)
- C.layer = layer + 0.1
- overlays += C
+ if(isobj(AM))
+ var/obj/O = AM
+ if(O.buckled_mob || (locate(/mob) in AM)) //can't load non crates objects with mobs buckled to it or inside it.
+ buzz(SIGH)
+ return
- if(ismob(C))
- var/mob/M = C
- if(M.client)
- M.client.perspective = EYE_PERSPECTIVE
- M.client.eye = src
+ if(isliving(AM))
+ if(!buckle_mob(AM))
+ return
+ else
+ AM.loc = src
+ AM.pixel_y += 9
+ if(AM.layer < layer)
+ AM.layer = layer + 0.1
+ overlays += AM
+ load= AM
mode = BOT_IDLE
+/obj/machinery/bot/mulebot/buckle_mob(mob/living/M)
+ if(M.buckled)
+ return 0
+ var/turf/T = get_turf(src)
+ if(M.loc != T)
+ density = 0
+ var/can_step = step_towards(M, T)
+ density = 1
+ if(!can_step)
+ return 0
+ return ..()
+
+
+/obj/machinery/bot/mulebot/post_buckle_mob(mob/living/M)
+ if(M == buckled_mob) //post buckling
+ M.pixel_y = initial(M.pixel_y) + 9
+ if(M.layer < layer)
+ M.layer = layer + 0.1
+
+ else //post unbuckling
+ load = null
+ M.layer = initial(M.layer)
+ M.pixel_y = initial(M.pixel_y)
+
+
// called to unload the bot
// argument is optional direction to unload
// if zero, unload at bot's location
@@ -460,18 +517,16 @@ obj/machinery/bot/mulebot/bot_reset()
if(!load)
return
- mode = BOT_LOADING
+ mode = BOT_IDLE
+
overlays.Cut()
- if(ismob(load))
- var/mob/M = load
- if(M.client)
- M.client.perspective = MOB_PERSPECTIVE
- M.client.eye = src
-
+ if(buckled_mob)
+ unbuckle_mob()
+ return
load.loc = loc
- load.pixel_y -= 9
+ load.pixel_y = initial(load.pixel_y)
load.layer = initial(load.layer)
if(dirn)
var/turf/T = loc
@@ -481,22 +536,7 @@ obj/machinery/bot/mulebot/bot_reset()
load = null
- // in case non-load items end up in contents, dump every else too
- // this seems to happen sometimes due to race conditions
- // with items dropping as mobs are loaded
- for(var/atom/movable/AM in src)
- if(AM == cell || istype(AM , botcard) || AM == Radio) continue
-
- AM.loc = loc
- AM.layer = initial(AM.layer)
- AM.pixel_y = initial(AM.pixel_y)
- if(ismob(AM))
- var/mob/M = AM
- if(M.client)
- M.client.perspective = MOB_PERSPECTIVE
- M.client.eye = src
- mode = BOT_IDLE
/obj/machinery/bot/mulebot/call_bot()
..()
@@ -536,14 +576,14 @@ obj/machinery/bot/mulebot/bot_reset()
if(refresh) updateDialog()
/obj/machinery/bot/mulebot/proc/process_bot()
- //if(mode) world << "Mode: [mode]"
+
+ if(!on)
+ return
switch(mode)
if(BOT_IDLE) // idle
icon_state = "mulebot0"
return
- if(BOT_LOADING) // loading/unloading
- return
if(BOT_DELIVER,BOT_GO_HOME,BOT_BLOCKED) // navigating to deliver,home, or blocked
if(loc == target) // reached target
@@ -603,26 +643,22 @@ obj/machinery/bot/mulebot/bot_reset()
blockcount++
mode = BOT_BLOCKED
if(blockcount == 3)
- visible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.")
- playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
+ buzz(ANNOYED)
if(blockcount > 10) // attempt 10 times before recomputing
// find new path excluding blocked turf
- visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.")
- playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
+ buzz(SIGH)
spawn(2)
calc_path(next)
if(path.len > 0)
- visible_message("[src] makes a delighted ping!", "You hear a ping.")
- playsound(loc, 'sound/machines/ping.ogg', 50, 0)
+ buzz(DELIGHT)
mode = BOT_BLOCKED
mode = BOT_WAIT_FOR_NAV
return
return
else
- visible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.")
- playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
+ buzz(ANNOYED)
//world << "Bad turf."
mode = BOT_NAV
return
@@ -641,20 +677,12 @@ obj/machinery/bot/mulebot/bot_reset()
if(path.len > 0)
blockcount = 0
mode = BOT_BLOCKED
- visible_message("[src] makes a delighted ping!", "You hear a ping.")
- playsound(loc, 'sound/machines/ping.ogg', 50, 0)
+ buzz(DELIGHT)
else
- visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.")
- playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
+ buzz(SIGH)
mode = BOT_NO_ROUTE
- //if(6)
- //world << "Pending path calc."
- //if(7)
- //world << "No dest / no route."
-
- return
// calculates a path to the current destination
@@ -673,6 +701,8 @@ obj/machinery/bot/mulebot/bot_reset()
// starts bot moving to current destination
/obj/machinery/bot/mulebot/proc/start()
+ if(!on)
+ return
if(destination == home_destination)
mode = BOT_GO_HOME
else
@@ -683,6 +713,8 @@ obj/machinery/bot/mulebot/bot_reset()
// starts bot moving to home
// sends a beacon query to find
/obj/machinery/bot/mulebot/proc/start_home()
+ if(!on)
+ return
spawn(0)
set_destination(home_destination)
mode = BOT_BLOCKED
@@ -692,7 +724,7 @@ obj/machinery/bot/mulebot/bot_reset()
/obj/machinery/bot/mulebot/proc/at_target()
if(!reached_target)
radio_frequency = SUPP_FREQ //Supply channel
- visible_message("[src] makes a chiming sound!", "You hear a chime.")
+ audible_message("[src] makes a chiming sound!", "You hear a chime.")
playsound(loc, 'sound/machines/chime.ogg', 50, 0)
reached_target = 1
@@ -719,7 +751,7 @@ obj/machinery/bot/mulebot/bot_reset()
break
else // otherwise, look for crates only
AM = locate(/obj/structure/closet/crate) in get_step(loc,loaddir)
- if(AM)
+ if(AM && AM.Adjacent(src))
load(AM)
if(report_delivery)
speak("Now loading [load] at [get_area(src)].", radio_frequency)
@@ -768,17 +800,16 @@ obj/machinery/bot/mulebot/bot_reset()
H.apply_damage(0.5*damage, BRUTE, "r_arm")
var/obj/effect/decal/cleanable/blood/B = new(loc)
- B.blood_DNA[H.dna.unique_enzymes] = H.dna.blood_type
- blood_DNA[H.dna.unique_enzymes] = H.dna.blood_type
+ B.add_blood_list(H)
+ add_blood_list(H)
bloodiness += 4
// player on mulebot attempted to move
/obj/machinery/bot/mulebot/relaymove(mob/user)
- if(user.stat)
+ if(user.incapacitated())
return
if(load == user)
unload(0)
- return
//Update navigation data. Called when commanded to deliver, return home, or a route update is needed...
@@ -828,5 +859,8 @@ obj/machinery/bot/mulebot/bot_reset()
s.start()
new /obj/effect/decal/cleanable/oil(loc)
- unload(0)
qdel(src)
+
+#undef SIGH
+#undef ANNOYED
+#undef DELIGHT
diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm
index ee609ef42cd..c85a12354b0 100644
--- a/code/game/machinery/bots/secbot.dm
+++ b/code/game/machinery/bots/secbot.dm
@@ -3,7 +3,7 @@
desc = "A little security robot. He looks less than thrilled."
icon = 'icons/obj/aibots.dmi'
icon_state = "secbot0"
- layer = 5.0
+ layer = 5
density = 0
anchored = 0
health = 25
diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index 67775ddd7d8..44bef9fac82 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -1,47 +1,219 @@
-/obj/machinery/driver_button
+/obj/machinery/button
+ name = "button"
+ desc = "A remote control switch."
+ icon = 'icons/obj/stationobjs.dmi'
+ icon_state = "doorctrl"
+ var/skin = "doorctrl"
+ power_channel = ENVIRON
+ var/obj/item/device/assembly/device
+ var/obj/item/weapon/electronics/airlock/board
+ var/device_type = null
+ var/id = null
+
+ anchored = 1
+ use_power = 1
+ idle_power_usage = 2
+
+
+/obj/machinery/button/New(loc, ndir = 0, built = 0)
+ ..()
+ if(built)
+ dir = ndir
+ pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
+ pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
+ panel_open = 1
+ update_icon()
+
+ if(id && !built && !device && device_type)
+ device = new device_type(src)
+
+ src.check_access(null)
+
+ if(req_access.len || req_one_access.len)
+ board = new(src)
+ if(req_access.len)
+ board.conf_access = req_access
+ else
+ board.use_one_access = 1
+ board.conf_access = req_one_access
+
+ if(id && istype(device, /obj/item/device/assembly/control))
+ var/obj/item/device/assembly/control/A = device
+ A.id = id
+
+
+/obj/machinery/button/update_icon()
+ overlays.Cut()
+ if(panel_open)
+ icon_state = "button-open"
+ if(device)
+ overlays += "button-device"
+ if(board)
+ overlays += "button-board"
+
+ else
+ if(stat & (NOPOWER|BROKEN))
+ icon_state = "[skin]-p"
+ else
+ icon_state = skin
+
+/obj/machinery/button/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/device/detective_scanner))
+ return
+
+ if(istype(W, /obj/item/weapon/screwdriver))
+ if(panel_open || allowed(user))
+ default_deconstruction_screwdriver(user, "button-open", "[skin]",W)
+ update_icon()
+ else
+ user << "Maintenance Access Denied"
+ flick("[skin]-denied", src)
+ return
+
+ if(panel_open)
+ if(!device && istype(W, /obj/item/device/assembly))
+ if(!user.unEquip(W))
+ user << "\The [W] is stuck to you!"
+ return
+ W.loc = src
+ device = W
+ user << "You add [W] to the button."
+
+ if(!board && istype(W, /obj/item/weapon/electronics/airlock))
+ if(!user.unEquip(W))
+ user << "\The [W] is stuck to you!"
+ return
+ W.loc = src
+ board = W
+ if(board.use_one_access)
+ req_one_access = board.conf_access
+ else
+ req_access = board.conf_access
+ user << "You add [W] to the button."
+
+ if(!device && !board && istype(W, /obj/item/weapon/wrench))
+ user << "You start unsecuring the button frame..."
+ playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
+ if(do_after(user, 40, target = src))
+ user << "You unsecure the button frame."
+ transfer_fingerprints_to(new /obj/item/wallframe/button(get_turf(src)))
+ playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ qdel(src)
+
+ update_icon()
+ return
+
+ return src.attack_hand(user)
+
+/obj/machinery/button/emag_act(mob/user)
+ req_access = list()
+ req_one_access = list()
+ playsound(src.loc, "sparks", 100, 1)
+
+/obj/machinery/button/attack_ai(mob/user)
+ if(!panel_open)
+ return attack_hand(user)
+
+/obj/machinery/button/attack_hand(mob/user)
+ src.add_fingerprint(user)
+ if(panel_open)
+ if(device || board)
+ if(device)
+ device.loc = get_turf(src)
+ device = null
+ if(board)
+ board.loc = get_turf(src)
+ req_access = list()
+ req_one_access = list()
+ board = null
+ update_icon()
+ user << "You remove electronics from the button frame."
+
+ else
+ if(skin == "doorctrl")
+ skin = "launcher"
+ else
+ skin = "doorctrl"
+ user << "You change the button frame's front panel."
+ return
+
+ if((stat & (NOPOWER|BROKEN)))
+ return
+
+ if(device && device.cooldown)
+ return
+
+ if(!allowed(user))
+ user << "Access Denied"
+ flick("[skin]-denied", src)
+ return
+
+ use_power(5)
+ icon_state = "[skin]1"
+
+ if(device)
+ device.pulsed()
+
+ spawn(15)
+ update_icon()
+
+/obj/machinery/button/power_change()
+ ..()
+ update_icon()
+
+
+
+/obj/machinery/button/door
+ name = "door button"
+ desc = "A door remote control switch."
+ var/normaldoorcontrol = 0
+ var/specialfunctions = OPEN // Bitflag, see assembly file
+
+/obj/machinery/button/door/New(loc, ndir = 0, built = 0)
+ if(id && !built && !device)
+ if(normaldoorcontrol)
+ var/obj/item/device/assembly/control/airlock/A = new(src)
+ device = A
+ A.specialfunctions = specialfunctions
+ else
+ device = new /obj/item/device/assembly/control(src)
+ ..()
+
+
+/obj/machinery/button/massdriver
name = "mass driver button"
- icon = 'icons/obj/objects.dmi'
- icon_state = "launcherbtt"
desc = "A remote control switch for a mass driver."
- var/id = null
- var/active = 0
- anchored = 1.0
- use_power = 1
- idle_power_usage = 2
- active_power_usage = 4
+ icon_state = "launcher"
+ skin = "launcher"
+ device_type = /obj/item/device/assembly/control/massdriver
-/obj/machinery/ignition_switch
+/obj/machinery/button/ignition
name = "ignition switch"
- icon = 'icons/obj/objects.dmi'
- icon_state = "launcherbtt"
desc = "A remote control switch for a mounted igniter."
- var/id = null
- var/active = 0
- anchored = 1.0
- use_power = 1
- idle_power_usage = 2
- active_power_usage = 4
+ icon_state = "launcher"
+ skin = "launcher"
+ device_type = /obj/item/device/assembly/control/igniter
-/obj/machinery/flasher_button
+/obj/machinery/button/flasher
name = "flasher button"
desc = "A remote control switch for a mounted flasher."
- icon = 'icons/obj/objects.dmi'
- icon_state = "launcherbtt"
- var/id = null
- var/active = 0
- anchored = 1.0
- use_power = 1
- idle_power_usage = 2
- active_power_usage = 4
+ icon_state = "launcher"
+ skin = "launcher"
+ device_type = /obj/item/device/assembly/control/flasher
-/obj/machinery/crema_switch
- desc = "Burn baby burn!"
+/obj/machinery/button/crematorium
name = "crematorium igniter"
- icon = 'icons/obj/power.dmi'
- icon_state = "crema_switch"
- anchored = 1.0
+ desc = "Burn baby burn!"
+ icon_state = "launcher"
+ skin = "launcher"
+ device_type = /obj/item/device/assembly/control/crematorium
req_access = list(access_crematorium)
- var/on = 0
- var/area/area = null
- var/otherarea = null
- var/id = 1
\ No newline at end of file
+ id = 1
+
+/obj/item/wallframe/button
+ name = "button frame"
+ desc = "Used for building buttons."
+ icon = 'icons/obj/apc_repair.dmi'
+ icon_state = "button_frame"
+ result_path = /obj/machinery/button
+ materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT)
\ No newline at end of file
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 33b4a99844c..e16f3f851ab 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -1,3 +1,7 @@
+#define CAMERA_UPGRADE_XRAY 1
+#define CAMERA_UPGRADE_EMP_PROOF 2
+#define CAMERA_UPGRADE_MOTION 4
+
/obj/machinery/camera
name = "security camera"
desc = "It's used to monitor rooms."
@@ -17,7 +21,7 @@
var/start_active = 0 //If it ignores the random chance to start broken on round start
var/invuln = null
var/obj/item/device/camera_bug/bug = null
- var/obj/item/weapon/camera_assembly/assembly = null
+ var/obj/machinery/camera_assembly/assembly = null
//OTHER
@@ -29,19 +33,21 @@
var/busy = 0
var/emped = 0 //Number of consecutive EMP's on this camera
+ // Upgrades bitflag
+ var/upgrades = 0
+
/obj/machinery/camera/New()
+ ..()
assembly = new(src)
assembly.state = 4
- assembly.anchored = 1
- assembly.update_icon()
-
+ cameranet.cameras += src
+ cameranet.addCamera(src)
/* // Use this to look for cameras that have the same c_tag.
for(var/obj/machinery/camera/C in cameranet.cameras)
var/list/tempnetwork = C.network&src.network
if(C != src && C.c_tag == src.c_tag && tempnetwork.len)
world.log << "[src.c_tag] [src.x] [src.y] [src.z] conflicts with [C.c_tag] [C.x] [C.y] [C.z]"
*/
- ..()
/obj/machinery/camera/initialize()
if(z == 1 && prob(3) && !start_active)
@@ -58,7 +64,9 @@
bug.current = null
bug = null
cameranet.removeCamera(src) //Will handle removal from the camera network and the chunks, so we don't need to worry about that
- ..()
+ cameranet.cameras -= src
+ cameranet.removeCamera(src)
+ return ..()
/obj/machinery/camera/emp_act(severity)
if(!isEmpProof())
@@ -82,7 +90,8 @@
cameranet.addCamera(src)
emped = 0 //Resets the consecutive EMP count
spawn(100)
- cancelCameraAlarm()
+ if(!qdeleted(src))
+ cancelCameraAlarm()
for(var/mob/O in mob_list)
if (O.client && O.client.eye == src)
O.unset_machine()
@@ -150,7 +159,6 @@
assembly.loc = src.loc
assembly.state = 1
assembly.dir = src.dir
- assembly.update_icon()
assembly = null
qdel(src)
return
@@ -237,6 +245,11 @@
return
/obj/machinery/camera/proc/deactivate(mob/user, displaymessage = 1) //this should be called toggle() but doing a find and replace for this would be ass
+ if(can_use())
+ cameranet.addCamera(src)
+ else
+ SetLuminosity(0)
+ cameranet.removeCamera(src)
status = !status
cameranet.updateChunk(x, y, z)
var/change_msg = "deactivates"
@@ -247,7 +260,8 @@
change_msg = "reactivates"
triggerCameraAlarm()
spawn(100)
- cancelCameraAlarm()
+ if(!qdeleted(src))
+ cancelCameraAlarm()
if(displaymessage)
if(user)
visible_message("[user] [change_msg] [src]!")
diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm
index dce9196f8db..f43488a5103 100644
--- a/code/game/machinery/camera/camera_assembly.dm
+++ b/code/game/machinery/camera/camera_assembly.dm
@@ -1,41 +1,36 @@
-/obj/item/weapon/camera_assembly
+/obj/item/wallframe/camera
name = "camera assembly"
desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
icon = 'icons/obj/monitors.dmi'
icon_state = "cameracase"
- w_class = 2
- anchored = 0
-
materials = list(MAT_METAL=400, MAT_GLASS=250)
+ result_path = /obj/machinery/camera_assembly
+
+/obj/machinery/camera_assembly
+ name = "camera assembly"
+ desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
+ icon = 'icons/obj/monitors.dmi'
+ icon_state = "camera1"
// Motion, EMP-Proof, X-Ray
var/list/obj/item/possible_upgrades = list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/sheet/mineral/plasma, /obj/item/device/analyzer)
var/list/upgrades = list()
- var/state = 0
+ var/state = 1
var/busy = 0
/*
- 0 = Nothing done to it
- 1 = Wrenched in place
- 2 = Welded in place
- 3 = Wires attached to it (you can now attach/dettach upgrades)
- 4 = Screwdriver panel closed and is fully built (you cannot attach upgrades)
+ 1 = Wrenched in place
+ 2 = Welded in place
+ 3 = Wires attached to it (you can now attach/dettach upgrades)
+ 4 = Screwdriver panel closed and is fully built (you cannot attach upgrades)
*/
-/obj/item/weapon/camera_assembly/attackby(obj/item/W, mob/living/user, params)
+/obj/machinery/camera_assembly/New(loc, ndir, building)
+ ..()
+ if(building)
+ dir = ndir
+/obj/machinery/camera_assembly/attackby(obj/item/W, mob/living/user, params)
switch(state)
-
- if(0)
- // State 0
- if(istype(W, /obj/item/weapon/wrench) && isturf(src.loc))
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- user << "You wrench the assembly into place."
- anchored = 1
- state = 1
- update_icon()
- auto_turn()
- return
-
if(1)
// State 1
if(istype(W, /obj/item/weapon/weldingtool))
@@ -48,9 +43,8 @@
else if(istype(W, /obj/item/weapon/wrench))
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You unattach the assembly from its place."
- anchored = 0
- update_icon()
- state = 0
+ new /obj/item/wallframe/camera(get_turf(src))
+ qdel(src)
return
if(2)
@@ -93,25 +87,14 @@
var/obj/machinery/camera/C = new(src.loc)
src.loc = C
C.assembly = src
-
- C.auto_turn()
+ C.dir = src.dir
C.network = tempnetwork
var/area/A = get_area_master(src)
C.c_tag = "[A.name] ([rand(1, 999)])"
- for(var/i = 5; i >= 0; i -= 1)
- var/direct = input(user, "Direction?", "Assembling Camera", null) in list("LEAVE IT", "NORTH", "EAST", "SOUTH", "WEST" )
- if(direct != "LEAVE IT")
- C.dir = text2dir(direct)
- if(i != 0)
- var/confirm = alert(user, "Is this what you want? Chances Remaining: [i]", "Confirmation", "Yes", "No")
- if(confirm == "Yes")
- break
- return
else if(istype(W, /obj/item/weapon/wirecutters))
-
new/obj/item/stack/cable_coil(get_turf(src), 2)
playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
user << "You cut the wires from the circuits."
@@ -139,18 +122,7 @@
..()
-/obj/item/weapon/camera_assembly/update_icon()
- if(anchored)
- icon_state = "camera1"
- else
- icon_state = "cameracase"
-
-/obj/item/weapon/camera_assembly/attack_hand(mob/user)
- if(!anchored)
- ..()
-
-/obj/item/weapon/camera_assembly/proc/weld(obj/item/weapon/weldingtool/WT, mob/living/user)
-
+/obj/machinery/camera_assembly/proc/weld(obj/item/weapon/weldingtool/WT, mob/living/user)
if(busy)
return 0
if(!WT.remove_fuel(0, user))
@@ -165,4 +137,4 @@
return 0
return 1
busy = 0
- return 0
+ return 0
\ No newline at end of file
diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm
index cc1139e511d..94049ba063d 100644
--- a/code/game/machinery/camera/presets.dm
+++ b/code/game/machinery/camera/presets.dm
@@ -61,25 +61,25 @@
// CHECKS
/obj/machinery/camera/proc/isEmpProof()
- var/O = locate(/obj/item/stack/sheet/mineral/plasma) in assembly.upgrades
- return O
+ return upgrades & CAMERA_UPGRADE_EMP_PROOF
/obj/machinery/camera/proc/isXRay()
- var/O = locate(/obj/item/device/analyzer) in assembly.upgrades
- return O
+ return upgrades & CAMERA_UPGRADE_XRAY
/obj/machinery/camera/proc/isMotion()
- var/O = locate(/obj/item/device/assembly/prox_sensor) in assembly.upgrades
- return O
+ return upgrades & CAMERA_UPGRADE_MOTION
// UPGRADE PROCS
/obj/machinery/camera/proc/upgradeEmpProof()
assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/plasma(assembly))
+ upgrades |= CAMERA_UPGRADE_EMP_PROOF
/obj/machinery/camera/proc/upgradeXRay()
assembly.upgrades.Add(new /obj/item/device/analyzer(assembly))
+ upgrades |= CAMERA_UPGRADE_XRAY
// If you are upgrading Motion, and it isn't in the camera's New(), add it to the machines list.
/obj/machinery/camera/proc/upgradeMotion()
assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly))
+ upgrades |= CAMERA_UPGRADE_MOTION
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index c2613b9a80c..221d898227c 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -54,7 +54,7 @@
icon = 'icons/obj/cloning.dmi'
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
item_state = "card-id"
- w_class = 1.0
+ w_class = 1
var/list/fields = list()
var/read_only = 0 //Well,it's still a floppy disk
@@ -185,7 +185,7 @@
H.ckey = ckey
H << "Consciousness slowly creeps over you as your body regenerates. So this is what cloning feels like?"
- hardset_dna(H, ui, se, null, null, mrace, features)
+ H.hardset_dna(ui, se, H.real_name, null, mrace, features)
H.faction |= factions
H.set_cloned_appearance()
@@ -301,13 +301,13 @@
return
/obj/machinery/clonepod/proc/go_out()
- if (src.locked)
+ if (locked)
return
- if (src.mess) //Clean that mess and dump those gibs!
- src.mess = 0
- gibs(src.loc)
- src.icon_state = "pod_0"
+ if (mess) //Clean that mess and dump those gibs!
+ mess = 0
+ gibs(loc)
+ icon_state = "pod_0"
/*
for(var/obj/O in src)
@@ -315,22 +315,22 @@
*/
return
- if (!(src.occupant))
+ if (!occupant)
return
/*
for(var/obj/O in src)
O.loc = src.loc
*/
- if (src.occupant.client)
- src.occupant.client.eye = src.occupant.client.mob
- src.occupant.client.perspective = MOB_PERSPECTIVE
+ if (occupant.client)
+ occupant.client.eye = occupant.client.mob
+ occupant.client.perspective = MOB_PERSPECTIVE
if(occupant.loc == src)
- src.occupant.loc = src.loc
- src.icon_state = "pod_0"
- src.eject_wait = 0 //If it's still set somehow.
- domutcheck(src.occupant) //Waiting until they're out before possible monkeyizing.
- src.occupant = null
+ occupant.loc = loc
+ icon_state = "pod_0"
+ eject_wait = 0 //If it's still set somehow.
+ occupant.domutcheck() //Waiting until they're out before possible monkeyizing.
+ occupant = null
return
/obj/machinery/clonepod/proc/malfunction()
diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm
index 6a96b8ac0fb..9f3630160d1 100644
--- a/code/game/machinery/computer/HolodeckControl.dm
+++ b/code/game/machinery/computer/HolodeckControl.dm
@@ -135,7 +135,7 @@
//This could all be done better, but it works for now.
/obj/machinery/computer/HolodeckControl/Destroy()
emergencyShutdown()
- ..()
+ return ..()
/obj/machinery/computer/HolodeckControl/emp_act(severity)
@@ -332,7 +332,7 @@
density = 1
layer = 3.2//Just above doors
pressure_resistance = 4*ONE_ATMOSPHERE
- anchored = 1.0
+ anchored = 1
flags = ON_BORDER
@@ -343,11 +343,11 @@
name = "holographic energy sword"
desc = "May the force be with you. Sorta"
icon_state = "sword0"
- force = 3.0
+ force = 3
throw_speed = 2
throw_range = 5
throwforce = 0
- w_class = 2.0
+ w_class = 2
hitsound = "swing_hit"
flags = NOSHIELD
var/active = 0
@@ -463,7 +463,7 @@
var/area/currentarea = null
var/eventstarted = 0
- anchored = 1.0
+ anchored = 1
use_power = 1
idle_power_usage = 2
active_power_usage = 6
diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm
index 4ec583172e6..a0b79dd7dad 100644
--- a/code/game/machinery/computer/Operating.dm
+++ b/code/game/machinery/computer/Operating.dm
@@ -49,7 +49,7 @@
/obj/machinery/computer/operating/proc/get_patient_info()
var/dat = {"
"
dat += "Like many before you, your crew never made it to Orion, lost to space... Forever."
if(settlers.len == 0)
@@ -419,14 +424,13 @@
user << "You're never going to make it to Orion..."
user.death()
emagged = 0 //removes the emagged status after you lose
- playing = 0 //also a new game
+ gameStatus = ORION_STATUS_START
name = "The Orion Trail"
desc = "Learn how our ancestors got to Orion, and have fun in the process!"
-
else if(event)
dat = eventdat
- else if(playing)
+ else if(gameStatus == ORION_STATUS_NORMAL)
var/title = stops[turns]
var/subtext = stopblurbs[turns]
dat = "
[title]
"
@@ -464,247 +468,275 @@
busy = 1
if (href_list["continue"]) //Continue your travels
- if(turns >= ORION_TRAIL_WINTURN)
- win()
- else
- food -= (alive+lings_aboard)*2
- fuel -= 5
- if(turns == 2 && prob(30))
- event = ORION_TRAIL_COLLISION
- event()
- else if(prob(75))
- event = pickweight(events)
- if(lings_aboard)
- if(event == ORION_TRAIL_LING || prob(55))
- event = ORION_TRAIL_LING_ATTACK
- event()
- turns += 1
- if(emagged)
- var/mob/living/carbon/M = usr //for some vars
- switch(event)
- if(ORION_TRAIL_RAIDERS)
- if(prob(50))
- usr << "You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?"
- M.hallucination += 30
- else
- usr << "Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there..."
- M.take_organ_damage(30)
- playsound(loc, 'sound/weapons/genhit2.ogg', 100, 1)
- if(ORION_TRAIL_ILLNESS)
- var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS
- if(severity == 1)
- M << "You suddenly feel slightly nauseous." //got off lucky
- if(severity == 2)
- usr << "You suddenly feel extremely nauseous and hunch over until it passes."
- M.Stun(3)
- if(severity >= 3) //you didn't pray hard enough
- M << "An overpowering wave of nausea consumes over you. You hunch over, your stomach's contents preparing for a spectacular exit."
- M.Stun(5)
- sleep(30)
- say("[M] violently throws up!")
- playsound(loc, 'sound/effects/splat.ogg', 50, 1)
- M.nutrition -= 50 //lose a lot of food
- var/turf/location = usr.loc
- if(istype(location, /turf/simulated))
- location.add_vomit_floor(src, 1)
- if(ORION_TRAIL_FLUX)
- if(prob(75))
- M.Weaken(3)
- say("A sudden gust of powerful wind slams [M] into the floor!")
- M.take_organ_damage(25)
- playsound(src.loc, 'sound/weapons/Genhit.ogg', 100, 1)
- else
- M << "A violent gale blows past you, and you barely manage to stay standing!"
- if(ORION_TRAIL_COLLISION) //by far the most damaging event
- if(prob(90))
- playsound(src.loc, 'sound/effects/bang.ogg', 100, 1)
- var/turf/simulated/floor/F
- for(F in orange(1, src))
- F.ChangeTurf(F.baseturf)
- say("Something slams into the floor around [src], exposing it to space!")
- if(hull)
- sleep(10)
- say("A new floor suddenly appears around [src]. What the hell?")
+ if(gameStatus == ORION_STATUS_NORMAL && !event && turns != 7)
+ if(turns >= ORION_TRAIL_WINTURN)
+ win()
+ else
+ food -= (alive+lings_aboard)*2
+ fuel -= 5
+ if(turns == 2 && prob(30))
+ event = ORION_TRAIL_COLLISION
+ event()
+ else if(prob(75))
+ event = pickweight(events)
+ if(lings_aboard)
+ if(event == ORION_TRAIL_LING || prob(55))
+ event = ORION_TRAIL_LING_ATTACK
+ event()
+ turns += 1
+ if(emagged)
+ var/mob/living/carbon/M = usr //for some vars
+ switch(event)
+ if(ORION_TRAIL_RAIDERS)
+ if(prob(50))
+ usr << "You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?"
+ M.hallucination += 30
+ else
+ usr << "Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there..."
+ M.take_organ_damage(30)
+ playsound(loc, 'sound/weapons/genhit2.ogg', 100, 1)
+ if(ORION_TRAIL_ILLNESS)
+ var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS
+ if(severity == 1)
+ M << "You suddenly feel slightly nauseous." //got off lucky
+ if(severity == 2)
+ usr << "You suddenly feel extremely nauseous and hunch over until it passes."
+ M.Stun(3)
+ if(severity >= 3) //you didn't pray hard enough
+ M << "An overpowering wave of nausea consumes over you. You hunch over, your stomach's contents preparing for a spectacular exit."
+ M.Stun(5)
+ sleep(30)
+ say("[M] violently throws up!")
+ playsound(loc, 'sound/effects/splat.ogg', 50, 1)
+ M.nutrition -= 50 //lose a lot of food
+ var/turf/location = usr.loc
+ if(istype(location, /turf/simulated))
+ location.add_vomit_floor(src, 1)
+ if(ORION_TRAIL_FLUX)
+ if(prob(75))
+ M.Weaken(3)
+ say("A sudden gust of powerful wind slams [M] into the floor!")
+ M.take_organ_damage(25)
playsound(src.loc, 'sound/weapons/Genhit.ogg', 100, 1)
- var/turf/space/T
- for(T in orange(1, src))
- T.ChangeTurf(/turf/simulated/floor/plating/)
- else
- say("Something slams into the floor around [src] - luckily, it didn't get through!")
- playsound(src.loc, 'sound/effects/bang.ogg', 50, 1)
- if(ORION_TRAIL_MALFUNCTION)
- playsound(src.loc, 'sound/effects/EMPulse.ogg', 50, 1)
- src.visible_message("[src] malfunctions, randomizing in-game stats!")
- var/oldfood = food
- var/oldfuel = fuel
- food = rand(10,80) / rand(1,2)
- fuel = rand(10,60) / rand(1,2)
- if(electronics)
- sleep(10)
- if(oldfuel > fuel && oldfood > food)
- src.audible_message("[src] lets out a somehow reassuring chime.")
- else if(oldfuel < fuel || oldfood < food)
- src.audible_message("[src] lets out a somehow ominous chime.")
- food = oldfood
- fuel = oldfuel
- playsound(src.loc, 'sound/machines/chime.ogg', 50, 1)
+ else
+ M << "A violent gale blows past you, and you barely manage to stay standing!"
+ if(ORION_TRAIL_COLLISION) //by far the most damaging event
+ if(prob(90))
+ playsound(src.loc, 'sound/effects/bang.ogg', 100, 1)
+ var/turf/simulated/floor/F
+ for(F in orange(1, src))
+ F.ChangeTurf(F.baseturf)
+ say("Something slams into the floor around [src], exposing it to space!")
+ if(hull)
+ sleep(10)
+ say("A new floor suddenly appears around [src]. What the hell?")
+ playsound(src.loc, 'sound/weapons/Genhit.ogg', 100, 1)
+ var/turf/space/T
+ for(T in orange(1, src))
+ T.ChangeTurf(/turf/simulated/floor/plating/)
+ else
+ say("Something slams into the floor around [src] - luckily, it didn't get through!")
+ playsound(src.loc, 'sound/effects/bang.ogg', 50, 1)
+ if(ORION_TRAIL_MALFUNCTION)
+ playsound(src.loc, 'sound/effects/EMPulse.ogg', 50, 1)
+ src.visible_message("[src] malfunctions, randomizing in-game stats!")
+ var/oldfood = food
+ var/oldfuel = fuel
+ food = rand(10,80) / rand(1,2)
+ fuel = rand(10,60) / rand(1,2)
+ if(electronics)
+ sleep(10)
+ if(oldfuel > fuel && oldfood > food)
+ src.audible_message("[src] lets out a somehow reassuring chime.")
+ else if(oldfuel < fuel || oldfood < food)
+ src.audible_message("[src] lets out a somehow ominous chime.")
+ food = oldfood
+ fuel = oldfuel
+ playsound(src.loc, 'sound/machines/chime.ogg', 50, 1)
else if(href_list["newgame"]) //Reset everything
- newgame()
+ if(gameStatus == ORION_STATUS_START)
+ newgame()
else if(href_list["menu"]) //back to the main menu
- playing = 0
- event = null
- gameover = 0
- food = 80
- fuel = 60
- settlers = list("Harry","Larry","Bob")
+ if(gameStatus == ORION_STATUS_GAMEOVER)
+ gameStatus = ORION_STATUS_START
+ event = null
+ food = 80
+ fuel = 60
+ settlers = list("Harry","Larry","Bob")
else if(href_list["slow"]) //slow down
- food -= (alive+lings_aboard)*2
- fuel -= 5
+ if(event == ORION_TRAIL_FLUX)
+ food -= (alive+lings_aboard)*2
+ fuel -= 5
event = null
else if(href_list["pastblack"]) //slow down
- food -= ((alive+lings_aboard)*2)*3
- fuel -= 15
- turns += 1
- event = null
- else if(href_list["useengine"]) //use parts
- engine -= 1
- event = null
- else if(href_list["useelec"]) //use parts
- electronics -= 1
- event = null
- else if(href_list["usehull"]) //use parts
- hull -= 1
- event = null
- else if(href_list["wait"]) //wait 3 days
- food -= ((alive+lings_aboard)*2)*3
- event = null
- else if(href_list["keepspeed"]) //keep speed
- if(prob(75))
- event = "Breakdown"
- event()
- else
- event = null
- else if(href_list["blackhole"]) //keep speed past a black hole
- if(prob(75))
- event = ORION_TRAIL_BLACKHOLE
- event()
- if(emagged) //has to be here because otherwise it doesn't work
- playsound(src.loc, 'sound/effects/supermatter.ogg', 100, 1)
- say("A miniature black hole suddenly appears in front of [src], devouring [usr] alive!")
- usr.Stun(10) //you can't run :^)
- var/S = new /obj/singularity/academy(usr.loc)
- emagged = 0 //immediately removes emagged status so people can't kill themselves by sprinting up and interacting
- sleep(50)
- say("[S] winks out, just as suddenly as it appeared.")
- qdel(S)
- else
- event = null
+ if(turns == 7)
+ food -= ((alive+lings_aboard)*2)*3
+ fuel -= 15
turns += 1
+ event = null
+ else if(href_list["useengine"]) //use parts
+ if(event == ORION_TRAIL_BREAKDOWN)
+ engine = max(0, --engine)
+ event = null
+ else if(href_list["useelec"]) //use parts
+ if(event == ORION_TRAIL_MALFUNCTION)
+ electronics = max(0, --electronics)
+ event = null
+ else if(href_list["usehull"]) //use parts
+ if(event == ORION_TRAIL_COLLISION)
+ hull = max(0, --hull)
+ event = null
+ else if(href_list["wait"]) //wait 3 days
+ if(event == ORION_TRAIL_BREAKDOWN || event == ORION_TRAIL_MALFUNCTION || event == ORION_TRAIL_COLLISION)
+ food -= ((alive+lings_aboard)*2)*3
+ event = null
+ else if(href_list["keepspeed"]) //keep speed
+ if(event == ORION_TRAIL_FLUX)
+ if(prob(75))
+ event = "Breakdown"
+ event()
+ else
+ event = null
+ else if(href_list["blackhole"]) //keep speed past a black hole
+ if(turns == 7)
+ if(prob(75))
+ event = ORION_TRAIL_BLACKHOLE
+ event()
+ if(emagged) //has to be here because otherwise it doesn't work
+ playsound(src.loc, 'sound/effects/supermatter.ogg', 100, 1)
+ say("A miniature black hole suddenly appears in front of [src], devouring [usr] alive!")
+ usr.Stun(10) //you can't run :^)
+ var/S = new /obj/singularity/academy(usr.loc)
+ emagged = 0 //immediately removes emagged status so people can't kill themselves by sprinting up and interacting
+ sleep(50)
+ say("[S] winks out, just as suddenly as it appeared.")
+ qdel(S)
+ else
+ event = null
+ turns += 1
else if(href_list["holedeath"])
- gameover = 1
- event = null
+ if(event == ORION_TRAIL_BLACKHOLE)
+ gameStatus = ORION_STATUS_GAMEOVER
+ event = null
else if(href_list["eventclose"]) //end an event
- event = null
+ if(canContinueEvent)
+ event = null
else if(href_list["killcrew"]) //shoot a crewmember
- var/sheriff = remove_crewmember() //I shot the sheriff
- playsound(loc,'sound/weapons/Gunshot.ogg', 100, 1)
+ if(gameStatus == ORION_STATUS_NORMAL || event == ORION_TRAIL_LING)
+ var/sheriff = remove_crewmember() //I shot the sheriff
+ playsound(loc,'sound/weapons/Gunshot.ogg', 100, 1)
- if(settlers.len == 0 || alive == 0)
- say("The last crewmember [sheriff], shot themselves, GAME OVER!")
- if(emagged)
- usr.death(0)
- emagged = 0
- gameover = 1
- event = null
- else if(emagged)
- if(usr.name == sheriff)
- say("The crew of the ship chose to kill [usr.name]!")
- usr.death(0)
+ if(settlers.len == 0 || alive == 0)
+ say("The last crewmember [sheriff], shot themselves, GAME OVER!")
+ if(emagged)
+ usr.death(0)
+ emagged = 0
+ gameStatus = ORION_STATUS_GAMEOVER
+ event = null
+ else if(emagged)
+ if(usr.name == sheriff)
+ say("The crew of the ship chose to kill [usr.name]!")
+ usr.death(0)
- if(event == ORION_TRAIL_LING) //only ends the ORION_TRAIL_LING event, since you can do this action in multiple places
- event = null
+ if(event == ORION_TRAIL_LING) //only ends the ORION_TRAIL_LING event, since you can do this action in multiple places
+ event = null
//Spaceport specific interactions
//they get a header because most of them don't reset event (because it's a shop, you leave when you want to)
//they also call event() again, to regen the eventdata, which is kind of odd but necessary
else if(href_list["buycrew"]) //buy a crewmember
- var/bought = add_crewmember()
- last_spaceport_action = "You hired [bought] as a new crewmember."
- fuel -= 10
- food -= 10
- event()
+ if(gameStatus == ORION_STATUS_MARKET)
+ if(!spaceport_raided && food >= 10 && fuel >= 10)
+ var/bought = add_crewmember()
+ last_spaceport_action = "You hired [bought] as a new crewmember."
+ fuel -= 10
+ food -= 10
+ event()
else if(href_list["sellcrew"]) //sell a crewmember
- var/sold = remove_crewmember()
- last_spaceport_action = "You sold your crewmember, [sold]!"
- fuel += 15
- food += 15
- event()
+ if(gameStatus == ORION_STATUS_MARKET)
+ if(!spaceport_raided && settlers.len > 1)
+ var/sold = remove_crewmember()
+ last_spaceport_action = "You sold your crewmember, [sold]!"
+ fuel += 7
+ food += 7
+ event()
else if(href_list["leave_spaceport"])
- event = null
- spaceport_raided = 0
- spaceport_freebie = 0
- last_spaceport_action = ""
+ if(gameStatus == ORION_STATUS_MARKET)
+ event = null
+ gameStatus = ORION_STATUS_NORMAL
+ spaceport_raided = 0
+ spaceport_freebie = 0
+ last_spaceport_action = ""
else if(href_list["raid_spaceport"])
- var/success = min(15 * alive,100) //default crew (4) have a 60% chance
- spaceport_raided = 1
+ if(gameStatus == ORION_STATUS_MARKET)
+ if(!spaceport_raided)
+ var/success = min(15 * alive,100) //default crew (4) have a 60% chance
+ spaceport_raided = 1
- var/FU = 0
- var/FO = 0
- if(prob(success))
- FU = rand(5,15)
- FO = rand(5,15)
- last_spaceport_action = "You successfully raided the spaceport! you gained [FU] Fuel and [FO] Food! (+[FU]FU,+[FO]FO)"
- else
- FU = rand(-5,-15)
- FO = rand(-5,-15)
- last_spaceport_action = "You failed to raid the spaceport! you lost [FU*-1] Fuel and [FO*-1] Food in your scramble to escape! ([FU]FU,[FO]FO)"
+ var/FU = 0
+ var/FO = 0
+ if(prob(success))
+ FU = rand(5,15)
+ FO = rand(5,15)
+ last_spaceport_action = "You successfully raided the spaceport! you gained [FU] Fuel and [FO] Food! (+[FU]FU,+[FO]FO)"
+ else
+ FU = rand(-5,-15)
+ FO = rand(-5,-15)
+ last_spaceport_action = "You failed to raid the spaceport! you lost [FU*-1] Fuel and [FO*-1] Food in your scramble to escape! ([FU]FU,[FO]FO)"
- //your chance of lose a crewmember is 1/2 your chance of success
- //this makes higher % failures hurt more, don't get cocky space cowboy!
- if(prob(success*5))
- var/lost_crew = remove_crewmember()
- last_spaceport_action = "You failed to raid the spaceport! you lost [FU*-1] Fuel and [FO*-1] Food, AND [lost_crew] in your scramble to escape! ([FU]FI,[FO]FO,-Crew)"
- if(emagged)
- say("WEEWOO WEEWOO, Spaceport Security en route!")
- for(var/i, i<=3, i++)
- var/mob/living/simple_animal/hostile/syndicate/ranged/orion/O = new/mob/living/simple_animal/hostile/syndicate/ranged/orion(get_turf(src))
- O.target = usr
+ //your chance of lose a crewmember is 1/2 your chance of success
+ //this makes higher % failures hurt more, don't get cocky space cowboy!
+ if(prob(success*5))
+ var/lost_crew = remove_crewmember()
+ last_spaceport_action = "You failed to raid the spaceport! you lost [FU*-1] Fuel and [FO*-1] Food, AND [lost_crew] in your scramble to escape! ([FU]FI,[FO]FO,-Crew)"
+ if(emagged)
+ say("WEEWOO WEEWOO, Spaceport Security en route!")
+ for(var/i, i<=3, i++)
+ var/mob/living/simple_animal/hostile/syndicate/ranged/orion/O = new/mob/living/simple_animal/hostile/syndicate/ranged/orion(get_turf(src))
+ O.target = usr
- fuel += FU
- food += FO
- event()
+ fuel += FU
+ food += FO
+ event()
else if(href_list["buyparts"])
- switch(text2num(href_list["buyparts"]))
- if(1) //Engine Parts
- engine++
- last_spaceport_action = "Bought Engine Parts"
- if(2) //Hull Plates
- hull++
- last_spaceport_action = "Bought Hull Plates"
- if(3) //Spare Electronics
- electronics++
- last_spaceport_action = "Bought Spare Electronics"
- fuel -= 5 //they all cost 5
- event()
+ if(gameStatus == ORION_STATUS_MARKET)
+ if(!spaceport_raided && fuel > 5)
+ switch(text2num(href_list["buyparts"]))
+ if(1) //Engine Parts
+ engine++
+ last_spaceport_action = "Bought Engine Parts"
+ if(2) //Hull Plates
+ hull++
+ last_spaceport_action = "Bought Hull Plates"
+ if(3) //Spare Electronics
+ electronics++
+ last_spaceport_action = "Bought Spare Electronics"
+ fuel -= 5 //they all cost 5
+ event()
else if(href_list["trade"])
- switch(text2num(href_list["trade"]))
- if(1) //Fuel
- fuel -= 5
- food += 5
- last_spaceport_action = "Traded Fuel for Food"
- if(2) //Food
- fuel += 5
- food -= 5
- last_spaceport_action = "Traded Food for Fuel"
- event()
+ if(gameStatus == ORION_STATUS_MARKET)
+ if(!spaceport_raided)
+ switch(text2num(href_list["trade"]))
+ if(1) //Fuel
+ if(fuel > 5)
+ fuel -= 5
+ food += 5
+ last_spaceport_action = "Traded Fuel for Food"
+ event()
+ if(2) //Food
+ if(food > 5)
+ fuel += 5
+ food -= 5
+ last_spaceport_action = "Traded Food for Fuel"
+ event()
src.add_fingerprint(usr)
src.updateUsrDialog()
@@ -714,7 +746,7 @@
/obj/machinery/computer/arcade/orion_trail/proc/event()
eventdat = "
[event]
"
-
+ canContinueEvent = 0
switch(event)
if(ORION_TRAIL_RAIDERS)
eventdat += "Raiders have come aboard your ship!"
@@ -731,6 +763,7 @@
eventdat += " Fortunately you fended them off without any trouble."
eventdat += "
"
+ 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."
@@ -744,6 +777,7 @@
eventdat += " [deadname] was killed by the disease."
eventdat += "
"
+ canContinueEvent = 1
if(ORION_TRAIL_SPACEPORT)
+ gameStatus = ORION_STATUS_MARKET
if(spaceport_raided)
eventdat += "The Spaceport is on high alert! they wont let you dock since you tried to attack them!"
if(last_spaceport_action)
@@ -899,7 +936,7 @@
//Sell crew
if(settlers.len > 1)
- eventdat += "
"
dat += "Chemical Implants "
var/turf/Tr = null
- for(var/obj/item/weapon/implant/chem/C in world)
+ for(var/obj/item/weapon/implant/chem/C in tracked_implants)
Tr = get_turf(C)
if((Tr) && (Tr.z != src.z)) continue//Out of range
if(!C.implanted) continue
@@ -43,7 +43,7 @@
dat += "((10)) "
dat += "******************************** "
dat += "Tracking Implants "
- for(var/obj/item/weapon/implant/tracking/T in world)
+ for(var/obj/item/weapon/implant/tracking/T in tracked_implants)
if(!iscarbon(T.imp_in))
continue
if(!T.implanted)
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index c87a35f2486..21b7b401754 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -49,7 +49,7 @@
dat = text("Confirm Identity: []", src, (scan ? text("[]", scan.name) : "----------"))
if(authenticated)
switch(screen)
- if(1.0)
+ if(1)
//body tag start + onload and onkeypress (onkeyup) javascript event calls
dat += ""
@@ -156,10 +156,10 @@
"}
dat += text("Record Maintenance
", src)
dat += text("{Log Out}",src)
- if(2.0)
+ if(2)
dat += "Records Maintenance"
dat += " Delete All Records
Back"
- if(3.0)
+ if(3)
dat += "Security Record "
if(istype(active1, /datum/data/record) && data_core.general.Find(active1))
if(istype(active1.fields["photo_front"], /obj/item/weapon/photo))
@@ -418,7 +418,7 @@ What a mess.*/
if("Purge All Records")
investigate_log("[usr.name] ([usr.key]) has purged all the security records.", "records")
for(var/datum/data/record/R in data_core.security)
- del(R)
+ qdel(R)
data_core.security.Cut()
temp = "All Security records deleted."
@@ -667,7 +667,7 @@ What a mess.*/
investigate_log("[usr.name] ([usr.key]) has deleted the security records for [active1.fields["name"]].", "records")
if(active2)
data_core.security -= active2
- del(active2)
+ qdel(active2)
if("Delete Record (ALL) Execute")
if(active1)
@@ -675,14 +675,14 @@ What a mess.*/
for(var/datum/data/record/R in data_core.medical)
if((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"]))
data_core.medical -= R
- del(R)
+ qdel(R)
break
data_core.general -= active1
- del(active1)
+ qdel(active1)
if(active2)
data_core.security -= active2
- del(active2)
+ qdel(active2)
else
temp = "This function does not appear to be working at the moment. Our apologies."
@@ -734,7 +734,7 @@ What a mess.*/
continue
else if(prob(1))
- del(R)
+ qdel(R)
continue
..(severity)
diff --git a/code/game/machinery/computer/shuttle.dm b/code/game/machinery/computer/shuttle.dm
index 2ea4b0b285e..2bb54ab86e3 100644
--- a/code/game/machinery/computer/shuttle.dm
+++ b/code/game/machinery/computer/shuttle.dm
@@ -3,7 +3,7 @@
desc = "For shuttle control."
icon_screen = "shuttle"
icon_keyboard = "tech_key"
- var/auth_need = 3.0
+ var/auth_need = 3
var/list/authorized = list()
@@ -93,7 +93,9 @@
else if(istype(A, /mob/living)) // You Shall Not Pass!
var/mob/living/M = A
- if(!M.lying && !ismonkey(M) && !isslime(M)) //If your not laying down, or a small creature, no pass.
+ if(M.buckled && istype(M.buckled, /obj/machinery/bot/mulebot)) // mulebot passenger gets a free pass.
+ return 1
+ if(!M.lying && !M.ventcrawler && M.mob_size != MOB_SIZE_TINY) //If your not laying down, or a ventcrawler or a small creature, no pass.
return 0
return ..()
@@ -124,7 +126,7 @@
if(T)
if(istype(T, /turf/simulated/floor))
T.blocks_air = 0
- ..()
+ return ..()
/obj/machinery/computer/supplycomp
name = "supply shuttle console"
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 1feb4e3b5e3..7de5be767b8 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -58,10 +58,10 @@ for reference:
desc = "This space is blocked off by a wooden barricade."
icon = 'icons/obj/structures.dmi'
icon_state = "woodenbarricade"
- anchored = 1.0
- density = 1.0
- var/health = 100.0
- var/maxhealth = 100.0
+ anchored = 1
+ density = 1
+ var/health = 100
+ var/maxhealth = 100
/obj/structure/barricade/wooden/attackby(obj/item/W, mob/user, params)
user.changeNext_move(CLICK_CD_MELEE)
@@ -93,11 +93,11 @@ for reference:
/obj/structure/barricade/wooden/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
visible_message("The barricade is blown apart!")
qdel(src)
return
- if(2.0)
+ if(2)
src.health -= 25
if (src.health <= 0)
visible_message("The barricade is blown apart!")
@@ -135,12 +135,12 @@ for reference:
name = "deployable barrier"
desc = "A deployable barrier. Swipe your ID card to lock/unlock it."
icon = 'icons/obj/objects.dmi'
- anchored = 0.0
- density = 1.0
+ anchored = 0
+ density = 1
icon_state = "barrier0"
- var/health = 100.0
- var/maxhealth = 100.0
- var/locked = 0.0
+ var/health = 100
+ var/maxhealth = 100
+ var/locked = 0
// req_access = list(access_maint_tunnels)
/obj/machinery/deployable/barrier/New()
@@ -151,14 +151,14 @@ for reference:
/obj/machinery/deployable/barrier/attackby(obj/item/weapon/W, mob/user, params)
if (W.GetID())
if (src.allowed(user))
- if (src.emagged < 2.0)
+ if (src.emagged < 2)
src.locked = !src.locked
src.anchored = !src.anchored
src.icon_state = "barrier[src.locked]"
- if ((src.locked == 1.0) && (src.emagged < 2.0))
+ if ((src.locked == 1) && (src.emagged < 2))
user << "Barrier lock toggled on."
return
- else if ((src.locked == 0.0) && (src.emagged < 2.0))
+ else if ((src.locked == 0) && (src.emagged < 2))
user << "Barrier lock toggled off."
return
else
@@ -213,10 +213,10 @@ for reference:
/obj/machinery/deployable/barrier/ex_act(severity)
switch(severity)
- if(1.0)
+ if(1)
src.explode()
return
- if(2.0)
+ if(2)
src.health -= 25
if (src.health <= 0)
src.explode()
diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm
new file mode 100644
index 00000000000..ac18b3fe445
--- /dev/null
+++ b/code/game/machinery/dna_scanner.dm
@@ -0,0 +1,167 @@
+/obj/machinery/dna_scannernew
+ name = "\improper DNA scanner"
+ desc = "It scans DNA structures."
+ icon = 'icons/obj/Cryogenic2.dmi'
+ icon_state = "scanner"
+ density = 1
+ var/locked = 0
+ anchored = 1
+ use_power = 1
+ idle_power_usage = 50
+ active_power_usage = 300
+ var/damage_coeff
+ var/scan_level
+ var/precision_coeff
+
+/obj/machinery/dna_scannernew/New()
+ ..()
+ component_parts = list()
+ component_parts += new /obj/item/weapon/circuitboard/clonescanner(null)
+ component_parts += new /obj/item/weapon/stock_parts/scanning_module(null)
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
+ component_parts += new /obj/item/weapon/stock_parts/micro_laser(null)
+ component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
+ component_parts += new /obj/item/stack/cable_coil(null, 1)
+ component_parts += new /obj/item/stack/cable_coil(null, 1)
+ RefreshParts()
+
+
+/obj/machinery/dna_scannernew/RefreshParts()
+ scan_level = 0
+ damage_coeff = 0
+ precision_coeff = 0
+ for(var/obj/item/weapon/stock_parts/scanning_module/P in component_parts)
+ scan_level += P.rating
+ for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts)
+ precision_coeff = P.rating
+ for(var/obj/item/weapon/stock_parts/micro_laser/P in component_parts)
+ damage_coeff = P.rating
+
+/obj/machinery/dna_scannernew/update_icon()
+
+ //no power or maintenance
+ if(stat & (NOPOWER|BROKEN))
+ icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_unpowered"
+ return
+
+ if((stat & MAINT) || panel_open)
+ icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_maintenance"
+ return
+
+ //running and someone in there
+ if(occupant)
+ icon_state = initial(icon_state)+ "_occupied"
+ return
+
+ //running
+ icon_state = initial(icon_state)+ (state_open ? "_open" : "")
+
+/obj/machinery/dna_scannernew/power_change()
+ ..()
+ update_icon()
+
+/obj/machinery/dna_scannernew/proc/toggle_open(mob/user)
+ if(panel_open)
+ user << "Close the maintenance panel first."
+ return
+
+ if(state_open)
+ close_machine()
+ return
+
+ else if(locked)
+ user << "The bolts are locked down, securing the door shut."
+ return
+
+ open_machine()
+
+/obj/machinery/dna_scannernew/container_resist()
+ var/mob/living/user = usr
+ var/breakout_time = 2
+ if(state_open || !locked) //Open and unlocked, no need to escape
+ state_open = 1
+ return
+ user.changeNext_move(CLICK_CD_BREAKOUT)
+ user.last_special = world.time + CLICK_CD_BREAKOUT
+ user << "You lean on the back of [src] and start pushing the door open... (this will take about [breakout_time] minutes.)"
+ user.visible_message("You hear a metallic creaking from [src]!")
+
+ if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
+ if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked)
+ return
+
+ locked = 0
+ visible_message("[user] successfully broke out of [src]!")
+ user << "You successfully break out of [src]!"
+
+ open_machine()
+
+/obj/machinery/dna_scannernew/close_machine()
+ if(!state_open)
+ return 0
+
+ ..()
+
+ // search for ghosts, if the corpse is empty and the scanner is connected to a cloner
+ if(occupant)
+ if(locate(/obj/machinery/computer/cloning, get_step(src, NORTH)) \
+ || locate(/obj/machinery/computer/cloning, get_step(src, SOUTH)) \
+ || locate(/obj/machinery/computer/cloning, get_step(src, EAST)) \
+ || locate(/obj/machinery/computer/cloning, get_step(src, WEST)))
+
+ occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!")
+ return 1
+
+/obj/machinery/dna_scannernew/open_machine()
+ if(state_open)
+ return 0
+
+ ..()
+
+ return 1
+
+/obj/machinery/dna_scannernew/relaymove(mob/user as mob)
+ if(user.stat || locked)
+ return
+
+ open_machine()
+ return
+
+/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params)
+
+ if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))//sent icon_state is irrelevant...
+ update_icon()//..since we're updating the icon here, since the scanner can be unpowered when opened/closed
+ return
+
+ if(exchange_parts(user, I))
+ return
+
+ if(default_pry_open(I))
+ return
+
+ if(default_deconstruction_crowbar(I))
+ return
+
+ if(istype(I, /obj/item/weapon/grab))
+ var/obj/item/weapon/grab/G = I
+ if(!ismob(G.affecting))
+ return
+
+ if(!state_open)
+ user << "Open the scanner first."
+ return
+
+ var/mob/M = G.affecting
+ M.loc = loc
+ user.stop_pulling()
+ qdel(G)
+
+/obj/machinery/dna_scannernew/attack_hand(mob/user)
+ if(..(user,1,0)) //don't set the machine, since there's no dialog
+ return
+
+ toggle_open(user)
+
+/obj/machinery/dna_scannernew/blob_act()
+ if(prob(75))
+ qdel(src)
\ No newline at end of file
diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm
deleted file mode 100644
index c235aadf40b..00000000000
--- a/code/game/machinery/door_control.dm
+++ /dev/null
@@ -1,170 +0,0 @@
-/obj/machinery/door_control
- name = "remote door-control"
- desc = "It controls doors, remotely."
- icon = 'icons/obj/stationobjs.dmi'
- icon_state = "doorctrl0"
- desc = "A remote control-switch for a door."
- power_channel = ENVIRON
- var/id = null
- var/normaldoorcontrol = 0
- var/specialfunctions = 1
- /*
- Bitflag, 1= open
- 2= idscan,
- 4= bolts
- 8= shock
- 16= door safties
-
- */
-
- var/exposedwires = 0
- var/wires = 3
- /*
- Bitflag, 1=checkID
- 2=Network Access
- */
-
- anchored = 1.0
- use_power = 1
- idle_power_usage = 2
- active_power_usage = 4
-
-/obj/machinery/door_control/attack_ai(mob/user)
- if(wires & 2)
- return src.attack_hand(user)
- else
- user << "Error, no route to host."
-
-/obj/machinery/door_control/attack_paw(mob/user)
- return src.attack_hand(user)
-
-/obj/machinery/door_control/attackby(obj/item/weapon/W, mob/user, params)
- /* For later implementation
- if (istype(W, /obj/item/weapon/screwdriver))
- {
- if(wiresexposed)
- icon_state = "doorctrl0"
- wiresexposed = 0
-
- else
- icon_state = "doorctrl-open"
- wiresexposed = 1
-
- return
- }
- */
- if(istype(W, /obj/item/device/detective_scanner))
- return
- return src.attack_hand(user)
-
-/obj/machinery/door_control/emag_act(mob/user)
- req_access = list()
- req_one_access = list()
- playsound(src.loc, "sparks", 100, 1)
-
-/obj/machinery/door_control/attack_hand(mob/user)
- src.add_fingerprint(usr)
- if(stat & (NOPOWER|BROKEN))
- return
-
- if(!allowed(user) && (wires & 1))
- user << "Access Denied"
- flick("doorctrl-denied",src)
- return
-
- use_power(5)
- icon_state = "doorctrl1"
- add_fingerprint(user)
-
- if(normaldoorcontrol)
- for(var/obj/machinery/door/airlock/D in world)
- if(D.id_tag == src.id)
- if(specialfunctions & OPEN)
- spawn(0)
- if(D)
- if(D.density) D.open()
- else D.close()
- return
- if(specialfunctions & IDSCAN)
- D.aiDisabledIdScanner = !D.aiDisabledIdScanner
- if(specialfunctions & BOLTS)
- if(!D.isWireCut(4) && D.hasPower())
- D.locked = !D.locked
- D.update_icon()
- if(specialfunctions & SHOCK)
- D.secondsElectrified = D.secondsElectrified ? 0 : -1
- if(specialfunctions & SAFE)
- D.safe = !D.safe
- else
- var/openclose
- for(var/obj/machinery/door/poddoor/M in world)
- if(M.id == src.id)
- if(openclose == null)
- openclose = M.density
- spawn(0)
- if(M)
- if(openclose) M.open()
- else M.close()
- return
-
- spawn(15)
- if(!(stat & NOPOWER))
- icon_state = "doorctrl0"
-
-/obj/machinery/door_control/power_change()
- ..()
- if(stat & NOPOWER)
- icon_state = "doorctrl-p"
- else
- icon_state = "doorctrl0"
-
-/obj/machinery/driver_button/attack_ai(mob/user)
- return src.attack_hand(user)
-
-/obj/machinery/driver_button/attack_paw(mob/user)
- return src.attack_hand(user)
-
-/obj/machinery/driver_button/attackby(obj/item/weapon/W, mob/user, params)
-
- if(istype(W, /obj/item/device/detective_scanner))
- return
- return src.attack_hand(user)
-
-/obj/machinery/driver_button/attack_hand(mob/user)
-
- src.add_fingerprint(usr)
- if(stat & (NOPOWER|BROKEN))
- return
- if(active)
- return
- add_fingerprint(user)
-
- use_power(5)
-
- active = 1
- icon_state = "launcheract"
-
- for(var/obj/machinery/door/poddoor/M in world)
- if (M.id == src.id)
- spawn( 0 )
- M.open()
- return
-
- sleep(20)
-
- for(var/obj/machinery/mass_driver/M in world)
- if(M.id == src.id)
- M.drive()
-
- sleep(50)
-
- for(var/obj/machinery/door/poddoor/M in world)
- if (M.id == src.id)
- spawn( 0 )
- M.close()
- return
-
- icon_state = "launcherbtt"
- active = 0
-
- return
\ No newline at end of file
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 245b949cb79..3a148e997f7 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -17,11 +17,18 @@
// Wires for the airlock are located in the datum folder, inside the wires datum folder.
+#define AIRLOCK_CLOSED 1
+#define AIRLOCK_CLOSING 2
+#define AIRLOCK_OPEN 3
+#define AIRLOCK_OPENING 4
+#define AIRLOCK_DENY 5
+#define AIRLOCK_EMAG 6
+var/list/airlock_overlays = list()
/obj/machinery/door/airlock
name = "airlock"
- icon = 'icons/obj/doors/Doorint.dmi'
- icon_state = "door_closed"
+ icon = 'icons/obj/doors/airlocks/station/public.dmi'
+ icon_state = "closed"
var/aiControlDisabled = 0 //If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in.
var/hackProof = 0 // if 1, this door can't be hacked by the AI
@@ -42,259 +49,29 @@
var/justzap = 0
var/safe = 1
normalspeed = 1
- var/obj/item/weapon/airlock_electronics/electronics = null
+ var/obj/item/weapon/electronics/airlock/electronics = null
var/hasShocked = 0 //Prevents multiple shocks from happening
var/autoclose = 1
var/obj/item/device/doorCharge/charge = null //If applied, causes an explosion upon opening the door
var/detonated = 0
+ var/airlock_material = null //material of inner filling; if its an airlock with glass, this should be set to "glass"
+ var/overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
+
explosion_block = 1
-/obj/machinery/door/airlock/command
- icon = 'icons/obj/doors/Doorcom.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_com
-
-/obj/machinery/door/airlock/security
- icon = 'icons/obj/doors/Doorsec.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_sec
-
-/obj/machinery/door/airlock/engineering
- icon = 'icons/obj/doors/Dooreng.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_eng
-
-/obj/machinery/door/airlock/medical
- icon = 'icons/obj/doors/Doormed.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_med
-
-/obj/machinery/door/airlock/maintenance
- name = "maintenance access"
- icon = 'icons/obj/doors/Doormaint.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_mai
-
-/obj/machinery/door/airlock/external
- name = "external airlock"
- icon = 'icons/obj/doors/Doorext.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_ext
-
-/obj/machinery/door/airlock/glass
- name = "glass airlock"
- icon = 'icons/obj/doors/Doorglass.dmi'
- opacity = 0
- doortype = /obj/structure/door_assembly/door_assembly_glass
- glass = 1
-
-/obj/machinery/door/airlock/centcom
- icon = 'icons/obj/doors/Doorele.dmi'
- opacity = 1
- doortype = /obj/structure/door_assembly/door_assembly_centcom
-
-/obj/machinery/door/airlock/vault
- name = "vault door"
- icon = 'icons/obj/doors/vault.dmi'
- opacity = 1
- doortype = /obj/structure/door_assembly/door_assembly_vault
- explosion_block = 2
-
-/obj/machinery/door/airlock/glass_large
- name = "glass airlock"
- icon = 'icons/obj/doors/Door2x1glassfull.dmi'
- opacity = 0
- doortype = null //(double glass door) there's no door assembly sprites for this one.
- glass = 1
- bound_width = 64 // 2x1
-
-/obj/machinery/door/airlock/freezer
- name = "freezer airlock"
- icon = 'icons/obj/doors/Doorfreezer.dmi'
- opacity = 1
- doortype = /obj/structure/door_assembly/door_assembly_fre
-
-/obj/machinery/door/airlock/hatch
- name = "airtight hatch"
- icon = 'icons/obj/doors/Doorhatchele.dmi'
- opacity = 1
- doortype = /obj/structure/door_assembly/door_assembly_hatch
-
-/obj/machinery/door/airlock/maintenance_hatch
- name = "maintenance hatch"
- icon = 'icons/obj/doors/Doorhatchmaint2.dmi'
- opacity = 1
- doortype = /obj/structure/door_assembly/door_assembly_mhatch
-
-/obj/machinery/door/airlock/glass_command
- name = "maintenance hatch"
- icon = 'icons/obj/doors/Doorcomglass.dmi'
- opacity = 0
- doortype = /obj/structure/door_assembly/door_assembly_com/glass
- glass = 1
-
-/obj/machinery/door/airlock/glass_engineering
- name = "maintenance hatch"
- icon = 'icons/obj/doors/Doorengglass.dmi'
- opacity = 0
- doortype = /obj/structure/door_assembly/door_assembly_eng/glass
- glass = 1
-
-/obj/machinery/door/airlock/glass_security
- name = "maintenance hatch"
- icon = 'icons/obj/doors/Doorsecglass.dmi'
- opacity = 0
- doortype = /obj/structure/door_assembly/door_assembly_sec/glass
- glass = 1
-
-/obj/machinery/door/airlock/glass_medical
- name = "maintenance hatch"
- icon = 'icons/obj/doors/Doormedglass.dmi'
- opacity = 0
- doortype = /obj/structure/door_assembly/door_assembly_med/glass
- glass = 1
-
-/obj/machinery/door/airlock/mining
- name = "mining airlock"
- icon = 'icons/obj/doors/Doormining.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_min
-
-/obj/machinery/door/airlock/atmos
- name = "atmospherics airlock"
- icon = 'icons/obj/doors/Dooratmo.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_atmo
-
-/obj/machinery/door/airlock/research
- icon = 'icons/obj/doors/Doorresearch.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_research
-
-/obj/machinery/door/airlock/glass_research
- name = "maintenance hatch"
- icon = 'icons/obj/doors/Doorresearchglass.dmi'
- opacity = 0
- doortype = /obj/structure/door_assembly/door_assembly_research/glass
- glass = 1
-
-/obj/machinery/door/airlock/glass_mining
- name = "maintenance hatch"
- icon = 'icons/obj/doors/Doorminingglass.dmi'
- opacity = 0
- doortype = /obj/structure/door_assembly/door_assembly_min/glass
- glass = 1
-
-/obj/machinery/door/airlock/glass_atmos
- name = "maintenance hatch"
- icon = 'icons/obj/doors/Dooratmoglass.dmi'
- opacity = 0
- doortype = /obj/structure/door_assembly/door_assembly_atmo/glass
- glass = 1
-
-/obj/machinery/door/airlock/gold
- name = "gold airlock"
- icon = 'icons/obj/doors/Doorgold.dmi'
- var/mineral = "gold"
- doortype = /obj/structure/door_assembly/door_assembly_gold
-
-/obj/machinery/door/airlock/silver
- name = "silver airlock"
- icon = 'icons/obj/doors/Doorsilver.dmi'
- var/mineral = "silver"
- doortype = /obj/structure/door_assembly/door_assembly_silver
-
-/obj/machinery/door/airlock/diamond
- name = "diamond airlock"
- icon = 'icons/obj/doors/Doordiamond.dmi'
- var/mineral = "diamond"
- doortype = /obj/structure/door_assembly/door_assembly_diamond
-
-/obj/machinery/door/airlock/uranium
- name = "uranium airlock"
- desc = "And they said I was crazy."
- icon = 'icons/obj/doors/Dooruranium.dmi'
- var/mineral = "uranium"
- doortype = /obj/structure/door_assembly/door_assembly_uranium
- var/last_event = 0
-
-/obj/machinery/door/airlock/uranium/process()
- if(world.time > last_event+20)
- if(prob(50))
- radiate()
- last_event = world.time
+/obj/machinery/door/airlock/New()
..()
-
-/obj/machinery/door/airlock/uranium/proc/radiate()
- for(var/mob/living/L in range (3,src))
- L.irradiate(15)
- return
-
-/obj/machinery/door/airlock/plasma
- name = "plasma airlock"
- desc = "No way this can end badly."
- icon = 'icons/obj/doors/Doorplasma.dmi'
- var/mineral = "plasma"
- doortype = /obj/structure/door_assembly/door_assembly_plasma
-
-/obj/machinery/door/airlock/plasma/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
- if(exposed_temperature > 300)
- PlasmaBurn(exposed_temperature)
-
-/obj/machinery/door/airlock/plasma/proc/ignite(exposed_temperature)
- if(exposed_temperature > 300)
- PlasmaBurn(exposed_temperature)
-
-/obj/machinery/door/airlock/plasma/proc/PlasmaBurn(temperature)
- atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 500)
- new/obj/structure/door_assembly/door_assembly_0( src.loc )
- qdel(src)
-
-/obj/machinery/door/airlock/plasma/BlockSuperconductivity() //we don't stop the heat~
- return 0
-
-/obj/machinery/door/airlock/clown
- name = "bananium airlock"
- desc = "Honkhonkhonk"
- icon = 'icons/obj/doors/Doorbananium.dmi'
- var/mineral = "bananium"
- doortype = /obj/structure/door_assembly/door_assembly_clown
-
-/obj/machinery/door/airlock/sandstone
- name = "sandstone airlock"
- icon = 'icons/obj/doors/Doorsand.dmi'
- var/mineral = "sandstone"
- doortype = /obj/structure/door_assembly/door_assembly_sandstone
-
-/obj/machinery/door/airlock/science
- icon = 'icons/obj/doors/Doorsci.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_science
-
-/obj/machinery/door/airlock/glass_science
- name = "glass airlock"
- icon = 'icons/obj/doors/Doorsciglass.dmi'
- opacity = 0
- doortype = /obj/structure/door_assembly/door_assembly_science/glass
- glass = 1
-
-/obj/machinery/door/airlock/highsecurity
- name = "high tech security airlock"
- icon = 'icons/obj/doors/hightechsecurity.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_highsecurity
- explosion_block = 2
-
-/obj/machinery/door/airlock/shuttle
- name = "shuttle airlock"
- icon = 'icons/obj/doors/doorshuttle.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_shuttle
-
-/obj/machinery/door/airlock/wood
- name = "wooden airlock"
- icon = 'icons/obj/doors/Doorwood.dmi'
- var/mineral = "wood"
- doortype = /obj/structure/door_assembly/door_assembly_wood
-
-/obj/machinery/door/airlock/virology
- icon = 'icons/obj/doors/Doorviro.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_viro
-
-/obj/machinery/door/airlock/glass_virology
- icon = 'icons/obj/doors/Doorviroglass.dmi'
- opacity = 0
- doortype = /obj/structure/door_assembly/door_assembly_viro/glass
- glass = 1
+ wires = new(src)
+ if(src.closeOtherId != null)
+ spawn (5)
+ for (var/obj/machinery/door/airlock/A in airlocks)
+ if(A.closeOtherId == src.closeOtherId && A != src)
+ src.closeOther = A
+ break
+ if(glass)
+ airlock_material = "glass"
+ update_icon()
/*
About the new airlock wires panel:
@@ -312,22 +89,24 @@ About the new airlock wires panel:
// You can find code for the airlock wires in the wire datum folder.
/obj/machinery/door/airlock/proc/bolt()
- if(locked)
+ if(locked || operating)
return
locked = 1
update_icon()
/obj/machinery/door/airlock/proc/unbolt()
- if(!locked)
+ if(!locked || operating)
return
locked = 0
update_icon()
/obj/machinery/door/airlock/Destroy()
+ qdel(wires)
+ wires = null
if(id_tag)
for(var/obj/machinery/doorButtons/D in world)
D.removeMe(src)
- ..()
+ return ..()
/obj/machinery/door/airlock/bumpopen(mob/living/user) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite
if(!issilicon(usr))
@@ -393,6 +172,8 @@ About the new airlock wires panel:
var/cont = 1
while (cont)
sleep(10)
+ if(qdeleted(src))
+ return
cont = 0
if(src.secondsMainPowerLost>0)
if((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)))
@@ -437,52 +218,133 @@ About the new airlock wires panel:
else
return 0
+/obj/machinery/door/airlock/update_icon(state=0)
+ switch(state)
+ if(0)
+ if(density)
+ state = AIRLOCK_CLOSED
+ else
+ state = AIRLOCK_OPEN
+ icon_state = ""
+ if(AIRLOCK_OPEN, AIRLOCK_CLOSED)
+ icon_state = ""
+ if(AIRLOCK_DENY, AIRLOCK_OPENING, AIRLOCK_CLOSING, AIRLOCK_EMAG)
+ icon_state = "nonexistenticonstate" //MADNESS
+ set_airlock_overlays(state)
-/obj/machinery/door/airlock/update_icon()
- if(overlays) overlays.Cut()
- if(density)
- if(locked && lights)
- icon_state = "door_locked"
- else
- icon_state = "door_closed"
- if(p_open || welded || emergency)
- overlays = list()
+/obj/machinery/door/airlock/proc/set_airlock_overlays(state)
+ var/image/frame_overlay
+ var/image/filling_overlay
+ var/image/lights_overlay
+ var/image/panel_overlay
+ var/image/weld_overlay
+ var/image/sparks_overlay
+
+ switch(state)
+ if(AIRLOCK_CLOSED)
+ frame_overlay = get_airlock_overlay("closed", icon)
+ if(airlock_material)
+ filling_overlay = get_airlock_overlay("[airlock_material]_closed", overlays_file)
+ else
+ filling_overlay = get_airlock_overlay("fill_closed", icon)
if(p_open)
- overlays += image(icon, "panel_open")
+ panel_overlay = get_airlock_overlay("panel_closed", overlays_file)
if(welded)
- overlays += image(icon, "welded")
- if(emergency && !locked)
- overlays += image(icon, "elights")
- else
- icon_state = "door_open"
+ weld_overlay = get_airlock_overlay("welded", overlays_file)
+ if(lights)
+ if(locked)
+ lights_overlay = get_airlock_overlay("lights_bolts", overlays_file)
+ else if(emergency)
+ lights_overlay = get_airlock_overlay("lights_emergency", overlays_file)
- return
+ if(AIRLOCK_DENY)
+ frame_overlay = get_airlock_overlay("closed", icon)
+ if(airlock_material)
+ filling_overlay = get_airlock_overlay("[airlock_material]_closed", overlays_file)
+ else
+ filling_overlay = get_airlock_overlay("fill_closed", icon)
+ if(p_open)
+ panel_overlay = get_airlock_overlay("panel_closed", overlays_file)
+ if(welded)
+ weld_overlay = get_airlock_overlay("welded", overlays_file)
+ lights_overlay = get_airlock_overlay("lights_denied", overlays_file)
+
+ if(AIRLOCK_EMAG)
+ frame_overlay = get_airlock_overlay("closed", icon)
+ sparks_overlay = get_airlock_overlay("sparks", overlays_file)
+ if(airlock_material)
+ filling_overlay = get_airlock_overlay("[airlock_material]_closed", overlays_file)
+ else
+ filling_overlay = get_airlock_overlay("fill_closed", icon)
+ if(p_open)
+ panel_overlay = get_airlock_overlay("panel_closed", overlays_file)
+ if(welded)
+ weld_overlay = get_airlock_overlay("welded", overlays_file)
+
+ if(AIRLOCK_CLOSING)
+ frame_overlay = get_airlock_overlay("closing", icon)
+ if(airlock_material)
+ filling_overlay = get_airlock_overlay("[airlock_material]_closing", overlays_file)
+ else
+ filling_overlay = get_airlock_overlay("fill_closing", icon)
+ if(lights)
+ lights_overlay = get_airlock_overlay("lights_closing", overlays_file)
+ if(p_open)
+ panel_overlay = get_airlock_overlay("panel_closing", overlays_file)
+
+ if(AIRLOCK_OPEN)
+ frame_overlay = get_airlock_overlay("open", icon)
+ if(airlock_material)
+ filling_overlay = get_airlock_overlay("[airlock_material]_open", overlays_file)
+ else
+ filling_overlay = get_airlock_overlay("fill_open", icon)
+ if(p_open)
+ panel_overlay = get_airlock_overlay("panel_open", overlays_file)
+
+ if(AIRLOCK_OPENING)
+ frame_overlay = get_airlock_overlay("opening", icon)
+ if(airlock_material)
+ filling_overlay = get_airlock_overlay("[airlock_material]_opening", overlays_file)
+ else
+ filling_overlay = get_airlock_overlay("fill_opening", icon)
+ if(lights)
+ lights_overlay = get_airlock_overlay("lights_opening", overlays_file)
+ if(p_open)
+ panel_overlay = get_airlock_overlay("panel_opening", overlays_file)
+
+ overlays.Cut()
+ overlays += frame_overlay
+ overlays += filling_overlay
+ overlays += lights_overlay
+ overlays += panel_overlay
+ overlays += weld_overlay
+ overlays += sparks_overlay
+
+/proc/get_airlock_overlay(icon_state, icon_file)
+ var/iconkey = "[icon_state][icon_file]"
+ if(airlock_overlays[iconkey])
+ return airlock_overlays[iconkey]
+ airlock_overlays[iconkey] = image(icon_file, icon_state)
+ return airlock_overlays[iconkey]
/obj/machinery/door/airlock/do_animate(animation)
switch(animation)
if("opening")
- if(overlays) overlays.Cut()
- if(p_open)
- spawn(2) // The only work around that works. Downside is that the door will be gone for a millisecond.
- flick("o_door_opening", src) //can not use flick due to BYOND bug updating overlays right before flicking
- else
- flick("door_opening", src)
+ update_icon(AIRLOCK_OPENING)
if("closing")
- if(overlays) overlays.Cut()
- if(p_open)
- flick("o_door_closing", src)
- else
- flick("door_closing", src)
- if("spark")
- flick("door_spark", src)
+ update_icon(AIRLOCK_CLOSING)
if("deny")
- flick("door_deny", src)
- return
+ update_icon(AIRLOCK_DENY)
+ sleep(6)
+ update_icon(AIRLOCK_CLOSED)
+ icon_state = "closed"
/obj/machinery/door/airlock/examine(mob/user)
..()
if(charge && !p_open && in_range(user, src))
- user << "The maintenance panel is bulging slightly."
+ user << "The maintenance panel seems haphazardly fastened."
+ if(charge && p_open)
+ user << "Something is wired up to the airlock's electronics!"
/obj/machinery/door/airlock/attack_ai(mob/user)
if(!src.canAIControl())
@@ -725,21 +587,22 @@ About the new airlock wires panel:
//disrupt main power
if(src.secondsMainPowerLost == 0)
src.loseMainPower()
+ update_icon()
else
usr << "Main power is already offline."
if(3)
//disrupt backup power
if(src.secondsBackupPowerLost == 0)
src.loseBackupPower()
+ update_icon()
else
usr << "Backup power is already offline."
if(4)
//drop door bolts
if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS))
usr << "You can't drop the door bolts - The door bolt dropping wire has been cut."
- else if(src.locked!=1)
- src.locked = 1
- update_icon()
+ else
+ bolt()
if(5)
//un-electrify door
if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY))
@@ -786,6 +649,7 @@ About the new airlock wires panel:
usr << text("Control to door bolt lights has been severed.")
else if (src.lights)
lights = 0
+ update_icon()
else
usr << text("Door bolt lights are already disabled!")
@@ -793,6 +657,7 @@ About the new airlock wires panel:
// Emergency access
if (src.emergency)
emergency = 0
+ update_icon()
else
usr << text("Emergency access is already disabled!")
@@ -816,8 +681,7 @@ About the new airlock wires panel:
usr << text("The door bolts are already up. \n")
else
if(src.hasPower())
- src.locked = 0
- update_icon()
+ unbolt()
else
usr << text("Cannot raise door bolts due to power failure. \n")
@@ -890,6 +754,7 @@ About the new airlock wires panel:
usr << text("Control to door bolt lights has been severed.")
else if (!src.lights)
lights = 1
+ update_icon()
src.updateUsrDialog()
else
usr << text("Door bolt lights are already enabled!")
@@ -898,11 +763,11 @@ About the new airlock wires panel:
// Emergency access
if (!src.emergency)
emergency = 1
+ update_icon()
else
usr << text("Emergency access is already enabled!")
add_fingerprint(usr)
- update_icon()
if(!nowindow)
updateUsrDialog()
return
@@ -915,6 +780,9 @@ About the new airlock wires panel:
if(istype(C, /obj/item/device/detective_scanner))
return
+ if(istype(C, /obj/item/weapon/card/emag))
+ return
+
src.add_fingerprint(user)
if((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density))
var/obj/item/weapon/weldingtool/W = C
@@ -940,11 +808,7 @@ About the new airlock wires panel:
src.p_open = !( src.p_open )
user << "You [p_open ? "open":"close"] the maintenance panel of the airlock."
src.update_icon()
- else if(istype(C, /obj/item/weapon/wirecutters))
- return src.attack_hand(user)
- else if(istype(C, /obj/item/device/multitool))
- return src.attack_hand(user)
- else if(istype(C, /obj/item/device/assembly/signaler))
+ else if(wires.IsInteractionTool(C))
return src.attack_hand(user)
else if(istype(C, /obj/item/weapon/pai_cable))
var/obj/item/weapon/pai_cable/cable = C
@@ -958,7 +822,7 @@ About the new airlock wires panel:
if(p_open && charge)
user << "You carefully start removing [charge] from [src]..."
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
- if(!do_after(user, 150))
+ if(!do_after(user, 150, target = src))
user << "You slip and [charge] detonates!"
charge.ex_act(1)
user.Weaken(3)
@@ -966,9 +830,6 @@ About the new airlock wires panel:
user.visible_message("[user] removes [charge] from [src].", \
"You gently pry out [charge] from [src] and unhook its wires.")
charge.loc = get_turf(user)
- if(prob(25))
- charge.ex_act(1)
- return
charge = null
return
if( beingcrowbarred && (density && welded && !operating && src.p_open && (!hasPower()) && !src.locked) )
@@ -990,9 +851,9 @@ About the new airlock wires panel:
return
user << "You remove the airlock electronics."
- var/obj/item/weapon/airlock_electronics/ae
+ var/obj/item/weapon/electronics/airlock/ae
if(!electronics)
- ae = new/obj/item/weapon/airlock_electronics( src.loc )
+ ae = new/obj/item/weapon/electronics/airlock( src.loc )
if(req_one_access)
ae.use_one_access = 1
ae.conf_access = src.req_one_access
@@ -1014,20 +875,24 @@ About the new airlock wires panel:
if(beingcrowbarred == 0) //being fireaxe'd
var/obj/item/weapon/twohanded/fireaxe/F = C
if(F:wielded)
- spawn(0) open(2)
+ spawn(0)
+ open(2)
else
user << "You need to be wielding the fire axe to do that!"
else
- spawn(0) open(2)
+ spawn(0)
+ open(2)
else
if(beingcrowbarred == 0)
var/obj/item/weapon/twohanded/fireaxe/F = C
if(F:wielded)
- spawn(0) close(2)
+ spawn(0)
+ close(2)
else
user << "You need to be wielding the fire axe to do that!"
else
- spawn(0) close(2)
+ spawn(0)
+ close(2)
else if(istype(C, /obj/item/weapon/airlock_painter))
change_paintjob(C, user)
@@ -1054,11 +919,11 @@ About the new airlock wires panel:
..()
return
-/obj/machinery/door/airlock/plasma/attackby(obj/C, mob/user, params)
- if(is_hot(C) > 300)//If the temperature of the object is over 300, then ignite
+/obj/machinery/door/airlock/plasma/attackby(obj/item/C, mob/user, params)
+ if(C.is_hot() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma airlock ignited by [key_name_admin(user)](?) (FLW) in ([x],[y],[z] - JMP)")
log_game("Plasma wall ignited by [key_name(user)] in ([x],[y],[z])")
- ignite(is_hot(C))
+ ignite(C.is_hot())
return
..()
@@ -1070,8 +935,9 @@ About the new airlock wires panel:
return 0
if(charge && !detonated)
p_open = 1
- update_icon()
+ update_icon(AIRLOCK_OPENING)
visible_message("[src]'s panel is blown off in a spray of deadly shrapnel!")
+ charge.loc = get_turf(src)
charge.ex_act(1)
detonated = 1
charge = null
@@ -1079,6 +945,7 @@ About the new airlock wires panel:
H.Paralyse(8)
H.adjust_fire_stacks(1)
H.IgniteMob() //Guaranteed knockout and ignition for nearby people
+ H.apply_damage(20, BRUTE, "chest")
return
if(forced < 2)
if(emagged)
@@ -1095,14 +962,31 @@ About the new airlock wires panel:
else
playsound(src.loc, 'sound/machines/airlockforced.ogg', 30, 1)
- if(autoclose && normalspeed)
+ if(autoclose && normalspeed)
spawn(150)
autoclose()
else if(autoclose && !normalspeed)
spawn(11)
autoclose()
- return ..()
+ if(!density)
+ return 1
+ if(!ticker)
+ return 0
+ operating = 1
+
+ do_animate("opening")
+ src.SetOpacity(0)
+ sleep(5)
+ src.density = 0
+ sleep(9)
+ src.layer = 2.7
+ update_icon()
+ SetOpacity(0)
+ operating = 0
+ air_update_turf(1)
+ update_freelook_sight()
+ return 1
/obj/machinery/door/airlock/close(forced=0)
@@ -1138,13 +1022,13 @@ About the new airlock wires panel:
if(density)
return 1
operating = 1
- do_animate("closing")
+ update_icon(AIRLOCK_CLOSING)
src.layer = 3.1
sleep(5)
src.density = 1
if(!safe)
crush()
- sleep(5)
+ sleep(9)
update_icon()
if(visible && !glass)
SetOpacity(1)
@@ -1156,17 +1040,6 @@ About the new airlock wires panel:
open()
return 1
-/obj/machinery/door/airlock/New()
- ..()
- wires = new(src)
- if(src.closeOtherId != null)
- spawn (5)
- for (var/obj/machinery/door/airlock/A in world)
- if(A.closeOtherId == src.closeOtherId && A != src)
- src.closeOther = A
- break
-
-
/obj/machinery/door/airlock/proc/prison_open()
if(emagged) return
src.locked = 0
@@ -1176,7 +1049,7 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/proc/autoclose()
- if(!density && !operating && !locked && !welded && autoclose)
+ if(!qdeleted(src) && !density && !operating && !locked && !welded && autoclose)
close()
/obj/machinery/door/airlock/proc/change_paintjob(obj/item/C, mob/user)
@@ -1190,75 +1063,63 @@ About the new airlock wires panel:
if(!W.can_use(user))
return
- if(glass == 1)
- //These airlocks have a glass version.
- var optionlist = list("Default", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining")
- var paintjob = input(user, "Please select a paintjob for this airlock.") in optionlist
- if((!in_range(src, usr) && src.loc != usr) || !W.use(user)) return
- switch(paintjob)
- if("Default")
- icon = 'icons/obj/doors/Doorglass.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_glass
- if("Engineering")
- icon = 'icons/obj/doors/Doorengglass.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_eng/glass
- if("Atmospherics")
- icon = 'icons/obj/doors/Dooratmoglass.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_atmo/glass
- if("Security")
- icon = 'icons/obj/doors/Doorsecglass.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_sec/glass
- if("Command")
- icon = 'icons/obj/doors/Doorcomglass.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_com/glass
- if("Medical")
- icon = 'icons/obj/doors/Doormedglass.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_med/glass
- if("Research")
- icon = 'icons/obj/doors/Doorresearchglass.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_research/glass
- if("Mining")
- icon = 'icons/obj/doors/Doorminingglass.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_min/glass
+ var/list/optionlist
+ if(airlock_material == "glass")
+ optionlist = list("Public", "Public2", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining", "Maintenance")
else
- //These airlocks have a regular version.
- var optionlist = list("Default", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining", "Maintenance", "External", "High Security")
- var paintjob = input(user, "Please select a paintjob for this airlock.") in optionlist
- if((!in_range(src, usr) && src.loc != usr) || !W.use(user)) return
- switch(paintjob)
- if("Default")
- icon = 'icons/obj/doors/Doorint.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_0
- if("Engineering")
- icon = 'icons/obj/doors/Dooreng.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_eng
- if("Atmospherics")
- icon = 'icons/obj/doors/Dooratmo.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_atmo
- if("Security")
- icon = 'icons/obj/doors/Doorsec.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_sec
- if("Command")
- icon = 'icons/obj/doors/Doorcom.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_com
- if("Medical")
- icon = 'icons/obj/doors/Doormed.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_med
- if("Research")
- icon = 'icons/obj/doors/Doorresearch.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_research
- if("Mining")
- icon = 'icons/obj/doors/Doormining.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_min
- if("Maintenance")
- icon = 'icons/obj/doors/Doormaint.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_mai
- if("External")
- icon = 'icons/obj/doors/Doorext.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_ext
- if("High Security")
- icon = 'icons/obj/doors/hightechsecurity.dmi'
- doortype = /obj/structure/door_assembly/door_assembly_highsecurity
+ optionlist = list("Public", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining", "Maintenance", "External", "High Security")
+
+ var/paintjob = input(user, "Please select a paintjob for this airlock.") in optionlist
+ if((!in_range(src, usr) && src.loc != usr) || !W.use(user)) return
+ switch(paintjob)
+ if("Public")
+ icon = 'icons/obj/doors/airlocks/station/public.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_0
+ if("Public2")
+ icon = 'icons/obj/doors/airlocks/station2/glass.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_glass
+ if("Engineering")
+ icon = 'icons/obj/doors/airlocks/station/engineering.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_eng
+ if("Atmospherics")
+ icon = 'icons/obj/doors/airlocks/station/atmos.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_atmo
+ if("Security")
+ icon = 'icons/obj/doors/airlocks/station/security.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_sec
+ if("Command")
+ icon = 'icons/obj/doors/airlocks/station/command.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_com
+ if("Medical")
+ icon = 'icons/obj/doors/airlocks/station/medical.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_med
+ if("Research")
+ icon = 'icons/obj/doors/airlocks/station/research.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_research
+ if("Mining")
+ icon = 'icons/obj/doors/airlocks/station/mining.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_min
+ if("Maintenance")
+ icon = 'icons/obj/doors/airlocks/station/maintenance.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_mai
+ if("External")
+ icon = 'icons/obj/doors/airlocks/external/external.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/external/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_ext
+ if("High Security")
+ icon = 'icons/obj/doors/airlocks/highsec/highsec.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/highsec/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_highsecurity
update_icon()
/obj/machinery/door/airlock/CanAStarPass(obj/item/weapon/card/id/ID)
@@ -1268,4 +1129,19 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/HasProximity(atom/movable/AM as mob|obj)
for (var/obj/A in contents)
A.HasProximity(AM)
- return
\ No newline at end of file
+ return
+
+/obj/machinery/door/airlock/emag_act(mob/user)
+ if(density && hasPower() && !emagged)
+ update_icon(AIRLOCK_EMAG)
+ sleep(6)
+ if(qdeleted(src))
+ return
+ if(!open())
+ update_icon(AIRLOCK_CLOSED)
+ emagged = 1
+ desc = "Its access panel is smoking slightly."
+ lights = 0
+ locked = 1
+ loseMainPower()
+ loseBackupPower()
diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm
index 0b1761281a2..11b4182152a 100644
--- a/code/game/machinery/doors/airlock_electronics.dm
+++ b/code/game/machinery/doors/airlock_electronics.dm
@@ -1,11 +1,7 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-/obj/item/weapon/airlock_electronics
+/obj/item/weapon/electronics/airlock
name = "airlock electronics"
- icon = 'icons/obj/doors/door_assembly.dmi'
- icon_state = "door_electronics"
- w_class = 2.0 //It should be tiny! -Agouri
- materials = list(MAT_METAL=50, MAT_GLASS=50)
req_access = list(access_maint_tunnels)
@@ -14,7 +10,7 @@
var/last_configurator = null
var/locked = 1
-/obj/item/weapon/airlock_electronics/attack_self(mob/user)
+/obj/item/weapon/electronics/airlock/attack_self(mob/user)
if (!ishuman(user))
return ..(user)
@@ -67,7 +63,7 @@
popup.open()
onclose(user, "airlock")
-/obj/item/weapon/airlock_electronics/Topic(href, href_list)
+/obj/item/weapon/electronics/airlock/Topic(href, href_list)
..()
if (usr.stat || usr.restrained() || !ishuman(usr))
return
@@ -95,7 +91,7 @@
attack_self(usr)
-/obj/item/weapon/airlock_electronics/proc/toggle_access(acc)
+/obj/item/weapon/electronics/airlock/proc/toggle_access(acc)
if (acc == "all")
conf_access = null
else if(acc == "one")
diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm
new file mode 100644
index 00000000000..e703f41c727
--- /dev/null
+++ b/code/game/machinery/doors/airlock_types.dm
@@ -0,0 +1,298 @@
+/*
+ Station Airlocks Regular
+*/
+/obj/machinery/door/airlock/command
+ icon = 'icons/obj/doors/airlocks/station/command.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_com
+
+/obj/machinery/door/airlock/security
+ icon = 'icons/obj/doors/airlocks/station/security.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_sec
+
+/obj/machinery/door/airlock/engineering
+ icon = 'icons/obj/doors/airlocks/station/engineering.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_eng
+
+/obj/machinery/door/airlock/medical
+ icon = 'icons/obj/doors/airlocks/station/medical.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_med
+
+/obj/machinery/door/airlock/maintenance
+ name = "maintenance access"
+ icon = 'icons/obj/doors/airlocks/station/maintenance.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_mai
+
+/obj/machinery/door/airlock/mining
+ name = "mining airlock"
+ icon = 'icons/obj/doors/airlocks/station/mining.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_min
+
+/obj/machinery/door/airlock/atmos
+ name = "atmospherics airlock"
+ icon = 'icons/obj/doors/airlocks/station/atmos.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_atmo
+
+/obj/machinery/door/airlock/research
+ icon = 'icons/obj/doors/airlocks/station/research.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_research
+
+/obj/machinery/door/airlock/freezer
+ name = "freezer airlock"
+ icon = 'icons/obj/doors/airlocks/station/freezer.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_fre
+
+/obj/machinery/door/airlock/science
+ icon = 'icons/obj/doors/airlocks/station/science.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_science
+
+/obj/machinery/door/airlock/virology
+ icon = 'icons/obj/doors/airlocks/station/virology.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_viro
+
+//////////////////////////////////
+/*
+ Station Airlocks Glass
+*/
+
+/obj/machinery/door/airlock/glass_command
+ icon = 'icons/obj/doors/airlocks/station/command.dmi'
+ opacity = 0
+ doortype = /obj/structure/door_assembly/door_assembly_com/glass
+ glass = 1
+
+/obj/machinery/door/airlock/glass_engineering
+ icon = 'icons/obj/doors/airlocks/station/engineering.dmi'
+ opacity = 0
+ doortype = /obj/structure/door_assembly/door_assembly_eng/glass
+ glass = 1
+
+/obj/machinery/door/airlock/glass_security
+ icon = 'icons/obj/doors/airlocks/station/security.dmi'
+ opacity = 0
+ doortype = /obj/structure/door_assembly/door_assembly_sec/glass
+ glass = 1
+
+/obj/machinery/door/airlock/glass_medical
+ icon = 'icons/obj/doors/airlocks/station/medical.dmi'
+ opacity = 0
+ doortype = /obj/structure/door_assembly/door_assembly_med/glass
+ glass = 1
+
+/obj/machinery/door/airlock/glass_research
+ icon = 'icons/obj/doors/airlocks/station/research.dmi'
+ opacity = 0
+ doortype = /obj/structure/door_assembly/door_assembly_research/glass
+ glass = 1
+
+/obj/machinery/door/airlock/glass_mining
+ icon = 'icons/obj/doors/airlocks/station/mining.dmi'
+ opacity = 0
+ doortype = /obj/structure/door_assembly/door_assembly_min/glass
+ glass = 1
+
+/obj/machinery/door/airlock/glass_atmos
+ icon = 'icons/obj/doors/airlocks/station/atmos.dmi'
+ opacity = 0
+ doortype = /obj/structure/door_assembly/door_assembly_atmo/glass
+ glass = 1
+
+/obj/machinery/door/airlock/glass_science
+ icon = 'icons/obj/doors/airlocks/station/science.dmi'
+ opacity = 0
+ doortype = /obj/structure/door_assembly/door_assembly_science/glass
+ glass = 1
+
+/obj/machinery/door/airlock/glass_virology
+ icon = 'icons/obj/doors/airlocks/station/virology.dmi'
+ opacity = 0
+ doortype = /obj/structure/door_assembly/door_assembly_viro/glass
+ glass = 1
+
+//////////////////////////////////
+/*
+ Station Airlocks Mineral
+*/
+
+/obj/machinery/door/airlock/gold
+ name = "gold airlock"
+ icon = 'icons/obj/doors/airlocks/station/gold.dmi'
+ var/mineral = "gold"
+ doortype = /obj/structure/door_assembly/door_assembly_gold
+
+/obj/machinery/door/airlock/silver
+ name = "silver airlock"
+ icon = 'icons/obj/doors/airlocks/station/silver.dmi'
+ var/mineral = "silver"
+ doortype = /obj/structure/door_assembly/door_assembly_silver
+
+/obj/machinery/door/airlock/diamond
+ name = "diamond airlock"
+ icon = 'icons/obj/doors/airlocks/station/diamond.dmi'
+ var/mineral = "diamond"
+ doortype = /obj/structure/door_assembly/door_assembly_diamond
+
+/obj/machinery/door/airlock/uranium
+ name = "uranium airlock"
+ icon = 'icons/obj/doors/airlocks/station/uranium.dmi'
+ var/mineral = "uranium"
+ doortype = /obj/structure/door_assembly/door_assembly_uranium
+ var/last_event = 0
+
+/obj/machinery/door/airlock/uranium/process()
+ if(world.time > last_event+20)
+ if(prob(50))
+ radiate()
+ last_event = world.time
+ ..()
+
+/obj/machinery/door/airlock/uranium/proc/radiate()
+ for(var/mob/living/L in range (3,src))
+ L.irradiate(15)
+ return
+
+/obj/machinery/door/airlock/plasma
+ name = "plasma airlock"
+ desc = "No way this can end badly."
+ icon = 'icons/obj/doors/airlocks/station/plasma.dmi'
+ var/mineral = "plasma"
+ doortype = /obj/structure/door_assembly/door_assembly_plasma
+
+/obj/machinery/door/airlock/plasma/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if(exposed_temperature > 300)
+ PlasmaBurn(exposed_temperature)
+
+/obj/machinery/door/airlock/plasma/proc/ignite(exposed_temperature)
+ if(exposed_temperature > 300)
+ PlasmaBurn(exposed_temperature)
+
+/obj/machinery/door/airlock/plasma/proc/PlasmaBurn(temperature)
+ atmos_spawn_air(SPAWN_HEAT | SPAWN_TOXINS, 500)
+ new/obj/structure/door_assembly/door_assembly_0( src.loc )
+ qdel(src)
+
+/obj/machinery/door/airlock/plasma/BlockSuperconductivity() //we don't stop the heat~
+ return 0
+
+/obj/machinery/door/airlock/clown
+ name = "bananium airlock"
+ desc = "Honkhonkhonk"
+ icon = 'icons/obj/doors/airlocks/station/bananium.dmi'
+ var/mineral = "bananium"
+ doortype = /obj/structure/door_assembly/door_assembly_clown
+
+/obj/machinery/door/airlock/sandstone
+ name = "sandstone airlock"
+ icon = 'icons/obj/doors/airlocks/station/sandstone.dmi'
+ var/mineral = "sandstone"
+ doortype = /obj/structure/door_assembly/door_assembly_sandstone
+
+
+/obj/machinery/door/airlock/wood
+ name = "wooden airlock"
+ icon = 'icons/obj/doors/airlocks/station/wood.dmi'
+ var/mineral = "wood"
+ doortype = /obj/structure/door_assembly/door_assembly_wood
+
+//////////////////////////////////
+/*
+ Station2 Airlocks
+*/
+
+/obj/machinery/door/airlock/glass
+ name = "glass airlock"
+ icon = 'icons/obj/doors/airlocks/station2/glass.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi'
+ opacity = 0
+ doortype = /obj/structure/door_assembly/door_assembly_glass
+ glass = 1
+
+//////////////////////////////////
+/*
+ External Airlocks
+*/
+
+/obj/machinery/door/airlock/external
+ name = "external airlock"
+ icon = 'icons/obj/doors/airlocks/external/external.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/external/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_ext
+
+//////////////////////////////////
+/*
+ Centcom Airlocks
+*/
+
+/obj/machinery/door/airlock/centcom
+ icon = 'icons/obj/doors/airlocks/centcom/centcom.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/centcom/overlays.dmi'
+ opacity = 1
+ doortype = /obj/structure/door_assembly/door_assembly_centcom
+
+//////////////////////////////////
+/*
+ Vault Airlocks
+*/
+
+/obj/machinery/door/airlock/vault
+ name = "vault door"
+ icon = 'icons/obj/doors/airlocks/vault/vault.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/vault/overlays.dmi'
+ opacity = 1
+ doortype = /obj/structure/door_assembly/door_assembly_vault
+ explosion_block = 2
+
+//////////////////////////////////
+/*
+ Hatch Airlocks
+*/
+
+/obj/machinery/door/airlock/hatch
+ name = "airtight hatch"
+ icon = 'icons/obj/doors/airlocks/hatch/centcom.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/hatch/overlays.dmi'
+ opacity = 1
+ doortype = /obj/structure/door_assembly/door_assembly_hatch
+
+/obj/machinery/door/airlock/maintenance_hatch
+ name = "maintenance hatch"
+ icon = 'icons/obj/doors/airlocks/hatch/maintenance.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/hatch/overlays.dmi'
+ opacity = 1
+ doortype = /obj/structure/door_assembly/door_assembly_mhatch
+
+//////////////////////////////////
+/*
+ High Security Airlocks
+*/
+
+/obj/machinery/door/airlock/highsecurity
+ name = "high tech security airlock"
+ icon = 'icons/obj/doors/airlocks/highsec/highsec.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/highsec/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_highsecurity
+ explosion_block = 2
+
+//////////////////////////////////
+/*
+ Shuttle Airlocks
+*/
+
+/obj/machinery/door/airlock/shuttle
+ name = "shuttle airlock"
+ icon = 'icons/obj/doors/airlocks/shuttle/shuttle.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/shuttle/overlays.dmi'
+ doortype = /obj/structure/door_assembly/door_assembly_shuttle
+
+
+//////////////////////////////////
+/*
+ Misc Airlocks
+*/
+
+/obj/machinery/door/airlock/glass_large
+ name = "glass airlock"
+ icon = 'icons/obj/doors/Door2x1glassfull.dmi'
+ opacity = 0
+ doortype = null //(double glass door) there's no door assembly sprites for this one.
+ glass = 1
+ bound_width = 64 // 2x1
diff --git a/code/game/machinery/doors/alarmlock.dm b/code/game/machinery/doors/alarmlock.dm
index 0264ae95312..c8525f3520d 100644
--- a/code/game/machinery/doors/alarmlock.dm
+++ b/code/game/machinery/doors/alarmlock.dm
@@ -1,7 +1,8 @@
/obj/machinery/door/airlock/alarmlock
name = "glass alarm airlock"
- icon = 'icons/obj/doors/Doorglass.dmi'
+ icon = 'icons/obj/doors/airlocks/station2/glass.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi'
opacity = 0
doortype = /obj/structure/door_assembly/door_assembly_glass
glass = 1
@@ -18,7 +19,7 @@
if(radio_controller)
radio_controller.remove_object(src,air_frequency)
air_connection = null
- ..()
+ return ..()
/obj/machinery/door/airlock/alarmlock/initialize()
..()
diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm
index d6d5f886095..b2c140555e1 100644
--- a/code/game/machinery/doors/brigdoors.dm
+++ b/code/game/machinery/doors/brigdoors.dm
@@ -19,7 +19,7 @@
icon_state = "frame"
desc = "A remote control for a door."
req_access = list(access_brig)
- anchored = 1.0 // can't pick it up
+ anchored = 1 // can't pick it up
density = 0 // can walk through it.
var/id = null // id of door it controls.
var/releasetime = 0 // when world.time reaches it - release the prisoneer
@@ -38,9 +38,6 @@
Radio = new/obj/item/device/radio(src)
Radio.listening = 0
- pixel_x = ((src.dir & 3)? (0) : (src.dir == 4 ? 32 : -32))
- pixel_y = ((src.dir & 3)? (src.dir ==1 ? 24 : -32) : (0))
-
spawn(20)
for(var/obj/machinery/door/window/brigdoor/M in range(20, src))
if (M.id == src.id)
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 129d03039b9..f0194cc645d 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -37,8 +37,7 @@
air_update_turf(1)
update_freelook_sight()
airlocks -= src
- ..()
- return
+ return ..()
//process()
//return
@@ -66,7 +65,7 @@
if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access) || emergency == 1))
open()
else
- flick("door_deny", src)
+ do_animate("deny")
return
return
@@ -98,7 +97,7 @@
if(allowed(user) || src.emergency == 1)
open()
else
- flick("door_deny", src)
+ do_animate("deny")
return
@@ -136,24 +135,9 @@
close()
return
if(src.density)
- flick("door_deny", src)
+ do_animate("deny")
return
-/obj/machinery/door/emag_act(mob/user)
- if(density && hasPower() && !emagged)
- flick("door_spark", src)
- sleep(6)
- open()
- emagged = 1
- desc = "Its access panel is smoking slightly."
- if(istype(src, /obj/machinery/door/airlock))
- var/obj/machinery/door/airlock/A = src
- A.lights = 0
- A.locked = 1
- A.loseMainPower()
- A.loseBackupPower()
- A.update_icon()
-
/obj/machinery/door/blob_act()
if(prob(40))
qdel(src)
@@ -275,6 +259,10 @@
/obj/machinery/door/proc/hasPower()
return !(stat & NOPOWER)
+/obj/machinery/door/proc/update_freelook_sight()
+ if(!glass && cameranet)
+ cameranet.updateVisibility(src, 0)
+
/obj/machinery/door/BlockSuperconductivity() // All non-glass airlocks block heat, this is intended.
if(opacity || heat_proof)
return 1
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 917e92f7f7e..2d85875a50b 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -170,13 +170,10 @@
icon = 'icons/obj/doors/Doorfire.dmi'
glass = 0
-/obj/item/weapon/firelock_board
+/obj/item/weapon/electronics/firelock
name = "firelock circuitry"
desc = "A circuit board used in construction of firelocks."
- icon = 'icons/obj/module.dmi'
icon_state = "mainboard"
- w_class = 2
- materials = list(MAT_METAL = 50, MAT_GLASS = 50)
/obj/structure/firelock_frame
name = "firelock frame"
@@ -270,7 +267,7 @@
if(constructionStep != CONSTRUCTION_GUTTED) return
user.visible_message("[user] removes [src]'s circuit board.", \
"You remove the circuit board from [src].")
- new /obj/item/weapon/firelock_board(get_turf(src))
+ new /obj/item/weapon/electronics/firelock(get_turf(src))
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
constructionStep = CONSTRUCTION_NOCIRCUIT
update_icon()
@@ -308,7 +305,7 @@
M.amount = 3
qdel(src)
return
- if(istype(C, /obj/item/weapon/firelock_board))
+ if(istype(C, /obj/item/weapon/electronics/firelock))
user.visible_message("[user] starts adding [C] to [src]...", \
"You begin adding a circuit board to [src]...")
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm
index c1836108462..181eb7923f4 100644
--- a/code/game/machinery/doors/poddoor.dm
+++ b/code/game/machinery/doors/poddoor.dm
@@ -91,14 +91,14 @@
//"BLAST" doors are obviously stronger than regular doors when it comes to BLASTS.
/obj/machinery/door/poddoor/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
if(prob(80))
qdel(src)
else
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(2, 1, src)
s.start()
- if(2.0)
+ if(2)
if(prob(20))
qdel(src)
else
@@ -106,7 +106,7 @@
s.set_up(2, 1, src)
s.start()
- if(3.0)
+ if(3)
if(prob(80))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(2, 1, src)
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 82a66b848e1..45d6b6e64be 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -4,11 +4,11 @@
icon = 'icons/obj/doors/windoor.dmi'
icon_state = "left"
var/base_state = "left"
- var/health = 150.0 //If you change this, consider changing ../door/window/brigdoor/ health at the bottom of this .dm file
- visible = 0.0
+ var/health = 150 //If you change this, consider changing ../door/window/brigdoor/ health at the bottom of this .dm file
+ visible = 0
flags = ON_BORDER
opacity = 0
- var/obj/item/weapon/airlock_electronics/electronics = null
+ var/obj/item/weapon/electronics/airlock/electronics = null
var/reinf = 0
/obj/machinery/door/window/New()
@@ -24,7 +24,7 @@
if(health == 0)
playsound(src, "shatter", 70, 1)
electronics = null
- ..()
+ return ..()
@@ -167,14 +167,14 @@
/obj/machinery/door/window/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
qdel(src)
- if(2.0)
+ if(2)
if(prob(25))
qdel(src)
else
take_damage(120)
- if(3.0)
+ if(3)
take_damage(60)
@@ -235,10 +235,8 @@
return
var/mob/living/simple_animal/M = user
M.do_attack_animation(src)
- if(M.melee_damage_upper <= 0)
- return
- attack_generic(M, M.melee_damage_upper)
-
+ if(M.melee_damage_upper > 0 && (M.melee_damage_type == BRUTE || M.melee_damage_type == BURN))
+ attack_generic(M, M.melee_damage_upper)
/obj/machinery/door/window/attack_slime(mob/living/simple_animal/slime/user)
user.do_attack_animation(src)
@@ -311,9 +309,9 @@
user << "You remove the airlock electronics."
- var/obj/item/weapon/airlock_electronics/ae
+ var/obj/item/weapon/electronics/airlock/ae
if(!electronics)
- ae = new/obj/item/weapon/airlock_electronics( src.loc )
+ ae = new/obj/item/weapon/electronics/airlock( src.loc )
if(req_one_access)
ae.use_one_access = 1
ae.conf_access = src.req_one_access
@@ -380,7 +378,7 @@
icon_state = "leftsecure"
base_state = "leftsecure"
var/id = null
- health = 300.0 //Stronger doors for prison (regular window door health is 200)
+ health = 300 //Stronger doors for prison (regular window door health is 200)
reinf = 1
explosion_block = 1
diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm
index 4d4e84cb3b2..b658e654d5c 100644
--- a/code/game/machinery/doppler_array.dm
+++ b/code/game/machinery/doppler_array.dm
@@ -2,7 +2,7 @@ var/list/doppler_arrays = list()
/obj/machinery/doppler_array
name = "tachyon-doppler array"
- desc = "A highly precise directional sensor array which measures the release of quants from decaying tachyons. The doppler shifting of the mirror-image formed by these quants can reveal the size, location and temporal affects of energetic disturbances within a large radius ahead of the array."
+ desc = "A highly precise directional sensor array which measures the release of quants from decaying tachyons. The doppler shifting of the mirror-image formed by these quants can reveal the size, location and temporal affects of energetic disturbances within a large radius ahead of the array.\nAlt-click to rotate it clockwise."
icon = 'icons/obj/machines/research.dmi'
icon_state = "tdoppler"
density = 1
@@ -15,7 +15,7 @@ var/list/doppler_arrays = list()
/obj/machinery/doppler_array/Destroy()
doppler_arrays -= src
- ..()
+ return ..()
/obj/machinery/doppler_array/process()
return PROCESS_KILL
@@ -44,6 +44,16 @@ var/list/doppler_arrays = list()
src.dir = turn(src.dir, 90)
return
+/obj/machinery/doppler_array/AltClick(mob/user)
+ ..()
+ if(!user.canUseTopic(user))
+ user << "You can't do that right now!"
+ return
+ if(!in_range(src, user))
+ return
+ else
+ rotate()
+
/obj/machinery/doppler_array/proc/sense_explosion(x0,y0,z0,devastation_range,heavy_impact_range,light_impact_range,
took,orig_dev_range,orig_heavy_range,orig_light_range)
if(stat & NOPOWER) return
diff --git a/code/game/machinery/droneDispenser.dm b/code/game/machinery/droneDispenser.dm
index 13c868ef183..86bdf54f452 100644
--- a/code/game/machinery/droneDispenser.dm
+++ b/code/game/machinery/droneDispenser.dm
@@ -1,22 +1,49 @@
-/obj/machinery/droneDispenser
+/obj/machinery/droneDispenser //Most customizable machine 2015
name = "drone shell dispenser"
desc = "A hefty machine that, when supplied with metal and glass, will periodically create a drone shell. Does not need to be manually operated."
icon = 'icons/obj/machines/droneDispenser.dmi'
icon_state = "on"
anchored = 1
density = 1
+
+ var/health = 100 //The health of the drone dispenser. It will break if it goes below 0
+ var/max_health = 100
+
+ var/icon_off = "off" //These variables allow for different icons when creating custom dispensers
+ var/icon_on = "on"
+ var/icon_recharging = "recharge"
+ var/icon_creating = "make"
+
var/metal = 0
var/glass = 0
+ var/metal_cost = 1000
+ var/glass_cost = 1000
+ var/power_used = 1000
+
var/droneMadeRecently = 0
- var/outputDirection = SOUTH
+ var/cooldownTime = 1800 //3 minutes
+ var/dispense_type = /obj/item/drone_shell //The item the dispenser will create
+
+ var/work_sound = 'sound/items/rped.ogg'
+ var/create_sound = 'sound/items/Deconstruct.ogg'
+ var/recharge_sound = 'sound/machines/ping.ogg'
+
+ var/begin_create_message = "whirs to life!"
+ var/end_create_message = "dispenses a drone shell."
+ var/recharge_message = "pings."
+ var/recharging_text = "It is whirring and clicking. It seems to be recharging."
+
+ var/break_message = "lets out a tinny alarm before falling dark."
+ var/break_sound = 'sound/machines/warning-buzzer.ogg'
/obj/machinery/droneDispenser/New()
..()
+ health = max_health
SSmachine.processing |= src
/obj/machinery/droneDispenser/Destroy()
SSmachine.processing -= src
- ..()
+ return ..()
/obj/machinery/droneDispenser/preloaded
metal = 5000
@@ -27,13 +54,60 @@
desc = "A suspicious machine that will create Syndicate exterminator drones when supplied with metal and glass. Disgusting."
metal = 25000
glass = 25000
+ dispense_type = /obj/item/drone_shell/syndrone
+ cooldownTime = 100 //If we're gonna be a jackass, go the full mile - 10 second recharge timer
+ end_create_message = "dispenses a suspicious drone shell."
+
+/obj/machinery/droneDispenser/hivebot //An example of a custom drone dispenser. This one requires no materials and creates basic hivebots
+ name = "hivebot fabricator"
+ desc = "A large, bulky machine that whirs with activity, steam hissing from vents in its sides."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "hivebot_fab"
+ icon_off = "hivebot_fab"
+ icon_on = "hivebot_fab"
+ icon_recharging = "hivebot_fab"
+ icon_creating = "hivebot_fab_on"
+ metal_cost = 0
+ glass_cost = 0
+ power_used = 0
+ cooldownTime = 10 //Only 1 second - hivebots are extremely weak
+ dispense_type = /mob/living/simple_animal/hostile/hivebot
+ begin_create_message = "closes and begins fabricating something within."
+ end_create_message = "slams open, revealing out a hivebot!"
+ recharge_sound = null
+ recharge_message = null
+
+/obj/machinery/droneDispenser/swarmer
+ name = "swarmer fabricator"
+ desc = "An alien machine of unknown origin. It whirs and hums with green-blue light, the air above it shimmering."
+ icon = 'icons/obj/machines/gateway.dmi'
+ icon_state = "toffcenter"
+ icon_off = "toffcenter"
+ icon_on = "toffcenter"
+ icon_recharging = "toffcenter"
+ icon_creating = "offcenter"
+ metal_cost = 0
+ glass_cost = 0
+ cooldownTime = 300 //30 seconds
+ dispense_type = /obj/item/unactivated_swarmer
+ begin_create_message = "hums softly as an interface appears above it, scrolling by at unreadable speed."
+ end_create_message = "materializes a strange shell, which drops to the ground."
+ recharging_text = "Its lights are slowly increasing in brightness."
+ work_sound = 'sound/effects/EMPulse.ogg'
+ create_sound = 'sound/effects/phasein.ogg'
+ break_sound = 'sound/effects/EMPulse.ogg'
+ break_message = "slowly falls dark, lights stuttering."
/obj/machinery/droneDispenser/examine(mob/user)
..()
- if(droneMadeRecently && !stat)
- user << "The control screen indicates that is recharging."
- user << "It has [metal] units of metal stored."
- user << "It has [glass] units of glass stored."
+ if(droneMadeRecently && !stat && recharging_text)
+ user << "[recharging_text]"
+ if(stat & BROKEN)
+ user << "[src] is smoking and steadily buzzing. It seems to be broken."
+ if(metal_cost)
+ user << "It has [metal] units of metal stored."
+ if(glass_cost)
+ user << "It has [glass] units of glass stored."
/obj/machinery/droneDispenser/power_change()
..()
@@ -50,36 +124,51 @@
..()
if(stat & (NOPOWER|BROKEN) || !anchored)
return
- if(droneMadeRecently || metal < 1000 || glass < 1000)
+ if((metal_cost && glass_cost) && (metal < metal_cost || glass < glass_cost))
+ return
+ if(droneMadeRecently)
+ icon_state = icon_recharging
return
droneMadeRecently = 1
- var/turf/T = get_step(src,SOUTH)
- visible_message("[src] whirs to life!")
- playsound(src, 'sound/items/rped.ogg', 50, 1)
- icon_state = "make"
+ if(begin_create_message)
+ visible_message("[src] [begin_create_message]")
+ if(work_sound)
+ playsound(src, work_sound, 50, 1)
+ icon_state = icon_creating
spawn(30)
- icon_state = "[initial(icon_state)]"
- visible_message("[src] dispenses a drone shell.")
- metal -= 1000
- glass -= 1000
- if(metal < 0) metal = 0
- if(glass < 0) glass = 0
- if(istype(src, /obj/machinery/droneDispenser/syndrone))
- new /obj/item/drone_shell/syndrone(T)
- else
- new /obj/item/drone_shell(T)
- use_power(1000)
- icon_state = "recharge"
- spawn(1800) //3 minute cooldown between shells
- icon_state = "[initial(icon_state)]"
+ icon_state = icon_on
+ metal -= metal_cost
+ glass -= glass_cost
+ if(metal < 0)
+ metal = 0
+ if(glass < 0)
+ glass = 0
+ if(power_used)
+ use_power(power_used)
+ new dispense_type(loc)
+ if(create_sound)
+ playsound(src, create_sound, 50, 1)
+ if(end_create_message)
+ visible_message("[src] [end_create_message]")
+ icon_state = icon_recharging
+ spawn(cooldownTime)
+ if(stat != BROKEN)
+ icon_state = icon_on
+ else
+ icon_state = icon_off
droneMadeRecently = 0
- playsound(src, 'sound/machines/ping.ogg', 50, 1)
- audible_message("[src] pings.")
+ if(recharge_sound)
+ playsound(src, recharge_sound, 50, 1)
+ if(recharge_message)
+ visible_message("[src] [recharge_message]")
/obj/machinery/droneDispenser/attackby(obj/item/O, mob/living/user)
if(istype(O, /obj/item/stack))
if(!O.materials[MAT_METAL] && !O.materials[MAT_GLASS])
return ..()
+ if(!metal_cost && !glass_cost)
+ user << "There isn't a place to insert [O]!"
+ return
var/stack = 1
var/obj/item/stack/sheets
sheets = O
@@ -102,4 +191,35 @@
if((O && O.loc == src) || !stack)
qdel(O)
return
+ if(istype(O, /obj/item/weapon/weldingtool) && (stat & BROKEN))
+ var/obj/item/weapon/weldingtool/WT = O
+ if(!WT.isOn())
+ return
+ if(WT.get_fuel() < 1)
+ user << "You need more fuel to complete this task!"
+ return
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
+ user.visible_message("[user] begins patching up [src] with [WT].", \
+ "You begin restoring the damage to [src]...")
+ if(!do_after(user, 40, target = src))
+ return
+ if(!src || !WT.remove_fuel(1, user)) return
+ user.visible_message("[user] fixes [src]!", \
+ "You restore [src] to operation.")
+ stat -= BROKEN
+ icon_state = icon_on
+ return
+ if(O.force && stat != BROKEN)
+ user.visible_message("[user] hits [src] with [O]!", \
+ "You hit [src] with [O]!")
+ playsound(src, O.hitsound, 50, 1)
+ health = Clamp(health - O.force, 0, max_health)
+ if(health <= 0)
+ if(break_message)
+ audible_message("[src] [break_message]")
+ if(break_sound)
+ playsound(src, break_sound, 50, 1)
+ stat = BROKEN
+ icon_state = icon_off
+ return
..()
diff --git a/code/game/machinery/embedded_controller/access_controller.dm b/code/game/machinery/embedded_controller/access_controller.dm
index bba22799b5f..e8b978c7fec 100644
--- a/code/game/machinery/embedded_controller/access_controller.dm
+++ b/code/game/machinery/embedded_controller/access_controller.dm
@@ -118,7 +118,7 @@
for(var/obj/machinery/doorButtons/access_button/A in world)
if(A.controller == src)
A.controller = null
- ..()
+ return ..()
/obj/machinery/doorButtons/airlock_controller/Topic(href, href_list)
if(..())
diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm
index e528bf28b69..6acfaafc359 100644
--- a/code/game/machinery/embedded_controller/embedded_controller_base.dm
+++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm
@@ -7,7 +7,7 @@
if(master)
master.post_signal(signal, comm_line)
else
- del(signal)
+ qdel(signal)
/datum/computer/file/embedded_program/proc/receive_user_command(command)
@@ -77,7 +77,7 @@
/obj/machinery/embedded_controller/radio/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
+ return ..()
/obj/machinery/embedded_controller/radio/initialize()
set_frequency(frequency)
diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm
index be2f33815a8..407db623ab9 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -5,7 +5,7 @@
desc = "A wall-mounted flashbulb device."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "mflash1"
- var/obj/item/device/flash/handheld/bulb = null
+ var/obj/item/device/assembly/flash/handheld/bulb = null
var/id = null
var/range = 2 //this is roughly the size of brig cell
var/last_flash = 0 //Don't want it getting spammed like regular flashes
@@ -23,12 +23,13 @@
density = 1
/obj/machinery/flasher/New()
- bulb = new /obj/item/device/flash/handheld(src)
+ ..() // ..() is EXTREMELY IMPORTANT, never forget to add it
+ bulb = new /obj/item/device/assembly/flash/handheld(src)
/obj/machinery/flasher/power_change()
if (powered() && anchored && bulb)
stat &= ~NOPOWER
- if(bulb.broken)
+ if(bulb.crit_fail)
icon_state = "[base_state]1-p"
else
icon_state = "[base_state]1"
@@ -48,7 +49,7 @@
bulb = null
power_change()
- else if (istype(W, /obj/item/device/flash/handheld))
+ else if (istype(W, /obj/item/device/assembly/flash/handheld))
if (!bulb)
if(!user.drop_item())
return
@@ -68,10 +69,11 @@
return
/obj/machinery/flasher/proc/flash()
+
if (!powered() || !bulb)
return
- if (bulb.broken || (last_flash && world.time < src.last_flash + 150))
+ if (bulb.crit_fail || (last_flash && world.time < src.last_flash + 150))
return
if(!bulb.flash_recharge(30)) //Bulb can burn out if it's used too often too fast
@@ -132,37 +134,4 @@
power_change()
else
- ..()
-
-/obj/machinery/flasher_button/attack_ai(mob/user)
- return attack_hand(user)
-
-/obj/machinery/flasher_button/attack_paw(mob/user)
- return attack_hand(user)
-
-/obj/machinery/flasher_button/attackby(obj/item/weapon/W, mob/user, params)
- return attack_hand(user)
-
-/obj/machinery/flasher_button/attack_hand(mob/user)
-
- if(stat & (NOPOWER|BROKEN))
- return
- if(active)
- return
-
- use_power(5)
-
- active = 1
- icon_state = "launcheract"
-
- for(var/obj/machinery/flasher/M in world)
- if(M.id == id)
- spawn()
- M.flash()
-
- sleep(50)
-
- icon_state = "launcherbtt"
- active = 0
-
- return
+ ..()
\ No newline at end of file
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 39f3f01ee08..8ed6035d818 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -220,12 +220,12 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
//Destruction procs.
/obj/machinery/hologram/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
qdel(src)
- if(2.0)
+ if(2)
if (prob(50))
qdel(src)
- if(3.0)
+ if(3)
if (prob(5))
qdel(src)
return
@@ -237,7 +237,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/hologram/holopad/Destroy()
for (var/mob/living/silicon/ai/master in masters)
clear_holo(master)
- ..()
+ return ..()
/*
Holographic project of everything else.
diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm
index 6a275734570..9920a4f5de7 100644
--- a/code/game/machinery/igniter.dm
+++ b/code/game/machinery/igniter.dm
@@ -4,8 +4,8 @@
icon = 'icons/obj/stationobjs.dmi'
icon_state = "igniter1"
var/id = null
- var/on = 1.0
- anchored = 1.0
+ var/on = 1
+ anchored = 1
use_power = 1
idle_power_usage = 2
active_power_usage = 4
@@ -115,43 +115,4 @@
..(severity)
return
ignite()
- ..(severity)
-
-/obj/machinery/ignition_switch/attack_ai(mob/user)
- return src.attack_hand(user)
-
-/obj/machinery/ignition_switch/attack_paw(mob/user)
- return src.attack_hand(user)
-
-/obj/machinery/ignition_switch/attackby(obj/item/weapon/W, mob/user, params)
- return src.attack_hand(user)
-
-/obj/machinery/ignition_switch/attack_hand(mob/user)
-
- if(stat & (NOPOWER|BROKEN))
- return
- if(active)
- return
-
- use_power(5)
-
- active = 1
- icon_state = "launcheract"
-
- for(var/obj/machinery/sparker/M in world)
- if (M.id == src.id)
- spawn( 0 )
- M.ignite()
-
- for(var/obj/machinery/igniter/M in world)
- if(M.id == src.id)
- use_power(50)
- M.on = !( M.on )
- M.icon_state = text("igniter[]", M.on)
-
- sleep(50)
-
- icon_state = "launcherbtt"
- active = 0
-
- return
\ No newline at end of file
+ ..(severity)
\ No newline at end of file
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index 0ca76f39213..143d5d30029 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -124,10 +124,10 @@
var/mob/living/carbon/human/T = attached
- if(!istype(T)) return
- if(!T.dna)
+ if(!istype(T))
return
- if(NOCLONE in T.mutations)
+
+ if(T.disabilities & NOCLONE)
return
if(NOBLOOD in T.dna.species.specflags)
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index ea104d8a86d..2383172069b 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -5,7 +5,7 @@
name = "light switch"
icon = 'icons/obj/power.dmi'
icon_state = "light1"
- anchored = 1.0
+ anchored = 1
var/on = 1
var/area/area = null
var/otherarea = null
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 4952544aeb7..c0e195c669c 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -128,7 +128,7 @@ Class Procs:
SSmachine.processing -= src
if(occupant)
dropContents()
- ..()
+ return ..()
/obj/machinery/proc/locate_machinery()
return
@@ -230,6 +230,8 @@ Class Procs:
return
/mob/living/canUseTopic(atom/movable/M, be_close = 0, no_dextery = 0)
+ if(incapacitated())
+ return
if(no_dextery)
if(be_close && in_range(M, src))
return 1
@@ -334,6 +336,7 @@ Class Procs:
deconstruction()
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(src.loc)
+ transfer_fingerprints_to(M)
M.state = 2
M.icon_state = "box_1"
for(var/obj/item/I in component_parts)
@@ -364,7 +367,7 @@ Class Procs:
return 1
return 0
-/obj/machinery/proc/default_unfasten_wrench(mob/user, obj/item/weapon/wrench/W, time = 20)
+/obj/proc/default_unfasten_wrench(mob/user, obj/item/weapon/wrench/W, time = 20)
if(istype(W))
user << "You begin [anchored ? "un" : ""]securing [name]..."
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm
index 43b767934ee..a0b8b57f938 100644
--- a/code/game/machinery/magnet.dm
+++ b/code/game/machinery/magnet.dm
@@ -45,7 +45,7 @@
/obj/machinery/magnetic_module/Destroy()
if(radio_controller)
radio_controller.remove_object(src, freq)
- ..()
+ . = ..()
center = null
// update the invisibility and icon
@@ -204,7 +204,7 @@
icon = 'icons/obj/airlock_machines.dmi' // uses an airlock machine icon, THINK GREEN HELP THE ENVIRONMENT - RECYCLING!
icon_state = "airlock_control_standby"
density = 0
- anchored = 1.0
+ anchored = 1
use_power = 1
idle_power_usage = 45
var/frequency = 1449
@@ -244,7 +244,7 @@
/obj/machinery/magnetic_controller/Destroy()
if(radio_controller)
radio_controller.remove_object(src, frequency)
- ..()
+ . = ..()
magnets = null
rpath = null
@@ -375,7 +375,7 @@
// N, S, E, W are directional
// C is center
// R is random (in magnetic field's bounds)
- del(signal)
+ qdel(signal)
break // break the loop if the character located is invalid
signal.data["command"] = nextmove
diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm
index a49787b25c4..ee18baacda4 100644
--- a/code/game/machinery/navbeacon.dm
+++ b/code/game/machinery/navbeacon.dm
@@ -36,7 +36,7 @@
/obj/machinery/navbeacon/Destroy()
navbeacons &= src //Remove from beacon list, if in one.
deliverybeacons &= src
- ..()
+ return ..()
// set the transponder codes assoc list from codes_txt
/obj/machinery/navbeacon/proc/set_codes()
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index 43d313fec05..a0b3c353862 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -159,34 +159,12 @@ var/list/obj/machinery/newscaster/allCasters = list()
-/obj/item/newscaster_frame
+/obj/item/wallframe/newscaster
name = "newscaster frame"
desc = "Used to build newscasters, just secure to the wall."
icon_state = "newscaster"
- item_state = "syringe_kit"
materials = list(MAT_METAL=14000, MAT_GLASS=8000)
-
-/obj/item/newscaster_frame/proc/try_build(turf/on_wall)
- if (get_dist(on_wall,usr)>1)
- return
- var/ndir = get_dir(usr,on_wall)
- if (!(ndir in cardinal))
- return
- var/turf/loc = get_turf(usr)
- var/area/A = loc.loc
- if (!istype(loc, /turf/simulated/floor))
- usr << "Newscaster cannot be placed on this spot!"
- return
- if (A.requires_power == 0 || A.name == "Space")
- usr << "Newscaster cannot be placed in this area!"
- return
- for(var/obj/machinery/newscaster/T in loc)
- usr << "There is another newscaster here!"
- return
- var/obj/machinery/newscaster/N = new(loc)
- N.pixel_y -= (loc.y - on_wall.y) * 32
- N.pixel_x -= (loc.x - on_wall.x) * 32
- qdel(src)
+ result_path = /obj/machinery/newscaster
/obj/machinery/newscaster
@@ -200,7 +178,7 @@ var/list/obj/machinery/newscaster/allCasters = list()
var/isbroken = 0
var/ispowered = 1
var/screen = 0
- var/paper_remaining = 0
+ var/paper_remaining = 15
var/securityCaster = 0
var/unit_no = 0
var/alert_delay = 500
@@ -220,19 +198,23 @@ var/list/obj/machinery/newscaster/allCasters = list()
name = "security newscaster"
securityCaster = 1
-/obj/machinery/newscaster/New()
+/obj/machinery/newscaster/New(loc, ndir, building)
+ ..()
+ if(building)
+ dir = ndir
+ pixel_x = (dir & 3)? 0 : (dir == 4 ? -32 : 32)
+ pixel_y = (dir & 3)? (dir ==1 ? -32 : 32) : 0
+
allCasters += src
- paper_remaining = 15
for(var/obj/machinery/newscaster/NEWSCASTER in allCasters)
unit_no++
update_icon()
- ..()
/obj/machinery/newscaster/Destroy()
allCasters -= src
viewing_channel = null
photo = null
- ..()
+ return ..()
/obj/machinery/newscaster/update_icon()
if(!ispowered || isbroken)
@@ -266,9 +248,9 @@ var/list/obj/machinery/newscaster/allCasters = list()
/obj/machinery/newscaster/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
qdel(src)
- if(2.0)
+ if(2)
isbroken=1
if(prob(50))
qdel(src)
@@ -743,7 +725,7 @@ var/list/obj/machinery/newscaster/allCasters = list()
playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
if(do_after(user, 60, target = src))
user << "You [anchored ? "un" : ""]secure [name]."
- new /obj/item/newscaster_frame(loc)
+ new /obj/item/wallframe/newscaster(loc)
playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1)
qdel(src)
return
@@ -895,8 +877,15 @@ var/list/obj/machinery/newscaster/allCasters = list()
var/creationTime
/obj/item/weapon/newspaper/suicide_act(mob/user)
- user.visible_message("[user] is focusing intently on [src]! It looks like they're trying to commit sudoku.")
- return(OXYLOSS)
+ user.visible_message("[user] is focusing intently on [src]! It looks like they're trying to commit sudoku... until their eyes light up with realization!")
+ user.say(";JOURNALISM IS MY CALLING! EVERYBODY APPRECIATES UNBIASED REPORTI-GLORF")
+ var/mob/living/carbon/human/H = user
+ var/obj/W = new /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey(H.loc)
+ playsound(H.loc, 'sound/items/drink.ogg', rand(10,50), 1)
+ W.reagents.trans_to(H, W.reagents.total_volume)
+ user.visible_message("[user] downs the contents of [W.name] in one gulp! Shoulda stuck to sudoku!")
+
+ return(TOXLOSS)
/obj/item/weapon/newspaper/attack_self(mob/user)
if(ishuman(user))
diff --git a/code/game/machinery/overview.dm b/code/game/machinery/overview.dm
index 873a51797d2..dcdfd5a74e3 100644
--- a/code/game/machinery/overview.dm
+++ b/code/game/machinery/overview.dm
@@ -174,8 +174,8 @@
HI.Insert(I, frame=1, delay = 5)
HI.Insert(J, frame=2, delay = 5)
- del(I)
- del(J)
+ qdel(I)
+ qdel(J)
H.icon = HI
H.layer = 25
usr.mapobjs += H
@@ -294,7 +294,7 @@
var/icon/I = imap[i+1]
H.icon = I
- del(I)
+ qdel(I)
H.layer = 25
usr.mapobjs += H
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index 2d49668927f..78adee3d5b0 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -2,36 +2,10 @@
Buildable pipes
Buildable meters
*/
-#define PIPE_SIMPLE_STRAIGHT 0
-#define PIPE_SIMPLE_BENT 1
-#define PIPE_HE_STRAIGHT 2
-#define PIPE_HE_BENT 3
-#define PIPE_CONNECTOR 4
-#define PIPE_MANIFOLD 5
-#define PIPE_JUNCTION 6
-#define PIPE_UVENT 7
-#define PIPE_MVALVE 8
-#define PIPE_PUMP 9
-#define PIPE_SCRUBBER 10
-#define PIPE_GAS_FILTER 11
-#define PIPE_GAS_MIXER 12
-#define PIPE_PASSIVE_GATE 13
-#define PIPE_VOLUME_PUMP 14
-#define PIPE_HEAT_EXCHANGE 15
-#define PIPE_DVALVE 16
-#define PIPE_4WAYMANIFOLD 17
-//Disposal piping numbers - do NOT hardcode these, use the defines
-#define DISP_PIPE_STRAIGHT 0
-#define DISP_PIPE_BENT 1
-#define DISP_JUNCTION 2
-#define DISP_JUNCTION_FLIP 3
-#define DISP_YJUNCTION 4
-#define DISP_END_TRUNK 5
-#define DISP_END_BIN 6
-#define DISP_END_OUTLET 7
-#define DISP_END_CHUTE 8
-#define DISP_SORTJUNCTION 9
-#define DISP_SORTJUNCTION_FLIP 10
+
+//construction defines are in __defines/pipe_construction.dm
+//update those defines ANY TIME an atmos path is changed...
+//...otherwise construction will stop working
/obj/item/pipe
name = "pipe"
@@ -45,112 +19,120 @@ Buildable meters
w_class = 3
level = 2
var/flipped = 0
+ var/is_bent = 0
+
+ var/global/list/pipe_types = list(
+ PIPE_SIMPLE, \
+ PIPE_MANIFOLD, \
+ PIPE_4WAYMANIFOLD, \
+ PIPE_HE, \
+ PIPE_HE_MANIFOLD, \
+ PIPE_HE_4WAYMANIFOLD, \
+ PIPE_JUNCTION, \
+ \
+ PIPE_CONNECTOR, \
+ PIPE_UVENT, \
+ PIPE_SCRUBBER, \
+ PIPE_HEAT_EXCHANGE, \
+ \
+ PIPE_PUMP, \
+ PIPE_PASSIVE_GATE, \
+ PIPE_VOLUME_PUMP, \
+ PIPE_MVALVE, \
+ PIPE_DVALVE, \
+ \
+ PIPE_GAS_FILTER, \
+ PIPE_GAS_MIXER, \
+ )
+
+/obj/item/pipe/examine(mob/user)
+ ..()
+ user << "Alt-click to rotate it clockwise."
/obj/item/pipe/New(loc, pipe_type, dir, obj/machinery/atmospherics/make_from)
..()
- if (make_from)
+ if(make_from)
src.dir = make_from.dir
src.pipename = make_from.name
src.color = make_from.color
- var/is_bent
- if (make_from.initialize_directions in list(NORTH|SOUTH, WEST|EAST))
- is_bent = 0
- else
- is_bent = 1
- if (istype(make_from, /obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction))
- src.pipe_type = PIPE_JUNCTION
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/heat_exchanging))
- src.pipe_type = PIPE_HE_STRAIGHT + is_bent
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple))
- src.pipe_type = PIPE_SIMPLE_STRAIGHT + is_bent
- else if(istype(make_from, /obj/machinery/atmospherics/components/unary/portables_connector))
- src.pipe_type = PIPE_CONNECTOR
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold))
- src.pipe_type = PIPE_MANIFOLD
- else if(istype(make_from, /obj/machinery/atmospherics/components/unary/vent_pump))
- src.pipe_type = PIPE_UVENT
- else if(istype(make_from, /obj/machinery/atmospherics/components/binary/valve/digital))
- src.pipe_type = PIPE_DVALVE
- else if(istype(make_from, /obj/machinery/atmospherics/components/binary/valve))
- src.pipe_type = PIPE_MVALVE
- else if(istype(make_from, /obj/machinery/atmospherics/components/binary/pump))
- src.pipe_type = PIPE_PUMP
- else if(istype(make_from, /obj/machinery/atmospherics/components/trinary/filter))
- src.pipe_type = PIPE_GAS_FILTER
- else if(istype(make_from, /obj/machinery/atmospherics/components/trinary/mixer))
- src.pipe_type = PIPE_GAS_MIXER
- else if(istype(make_from, /obj/machinery/atmospherics/components/unary/vent_scrubber))
- src.pipe_type = PIPE_SCRUBBER
- else if(istype(make_from, /obj/machinery/atmospherics/components/binary/passive_gate))
- src.pipe_type = PIPE_PASSIVE_GATE
- else if(istype(make_from, /obj/machinery/atmospherics/components/binary/volume_pump))
- src.pipe_type = PIPE_VOLUME_PUMP
- else if(istype(make_from, /obj/machinery/atmospherics/components/unary/heat_exchanger))
- src.pipe_type = PIPE_HEAT_EXCHANGE
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold4w))
- src.pipe_type = PIPE_4WAYMANIFOLD
+
+ if(make_from.type in pipe_types)
+ src.pipe_type = make_from.type
+ else //make pipe_type a value we can work with
+ for(var/P in pipe_types)
+ if(istype(make_from, P))
+ src.pipe_type = P
+ break
var/obj/machinery/atmospherics/components/trinary/triP = make_from
if(istype(triP) && triP.flipped)
src.flipped = 1
src.dir = turn(src.dir, -45)
-
else
src.pipe_type = pipe_type
src.dir = dir
- //src.pipe_dir = get_pipe_dir()
+
+ if(src.dir in diagonals)
+ is_bent = 1
+
update()
src.pixel_x = rand(-5, 5)
src.pixel_y = rand(-5, 5)
//update the name and icon of the pipe item depending on the type
var/global/list/pipeID2State = list(
- "simple", \
- "simple", \
- "he", \
- "he", \
- "connector", \
- "manifold", \
- "junction", \
- "uvent", \
- "mvalve", \
- "pump", \
- "scrubber", \
- "filter", \
- "mixer", \
- "passivegate", \
- "volumepump", \
- "heunary", \
- "dvalve", \
- "manifold4w", \
+ "[PIPE_SIMPLE]" = "simple", \
+ "[PIPE_MANIFOLD]" = "manifold", \
+ "[PIPE_4WAYMANIFOLD]" = "manifold4w", \
+ "[PIPE_HE]" = "he", \
+ "[PIPE_HE_MANIFOLD]" = "he_manifold", \
+ "[PIPE_HE_4WAYMANIFOLD]" = "he_manifold4w", \
+ "[PIPE_JUNCTION]" = "junction", \
+ \
+ "[PIPE_CONNECTOR]" = "connector", \
+ "[PIPE_UVENT]" = "uvent", \
+ "[PIPE_SCRUBBER]" = "scrubber", \
+ "[PIPE_HEAT_EXCHANGE]" = "heunary", \
+ \
+ "[PIPE_PUMP]" = "pump", \
+ "[PIPE_PASSIVE_GATE]" = "passivegate", \
+ "[PIPE_VOLUME_PUMP]" = "volumepump", \
+ "[PIPE_MVALVE]" = "mvalve", \
+ "[PIPE_DVALVE]" = "dvalve", \
+ \
+ "[PIPE_GAS_FILTER]" = "filter", \
+ "[PIPE_GAS_MIXER]" = "mixer", \
)
/obj/item/pipe/proc/update()
- var/list/nlist = list( \
- "pipe", \
- "bent pipe", \
- "h/e pipe", \
- "bent h/e pipe", \
- "connector", \
- "manifold", \
- "junction", \
- "vent", \
- "manual valve", \
- "pump", \
- "scrubber", \
- "gas filter", \
- "gas mixer", \
- "passive gate", \
- "volume pump", \
- "heat exchanger", \
- "digital valve", \
- "4-way manifold", \
- )
- name = nlist[pipe_type+1] + " fitting"
- icon_state = pipeID2State[pipe_type + 1]
-
-//called when a turf is attacked with a pipe item
-// place the pipe on the turf, setting pipe level to 1 (underfloor) if the turf is not intact
+ var/list/nlist = list(\
+ "[PIPE_SIMPLE]" = "pipe", \
+ "[PIPE_SIMPLE]_b" = "bent pipe", \
+ "[PIPE_MANIFOLD]" = "manifold", \
+ "[PIPE_4WAYMANIFOLD]" = "4-way manifold", \
+ "[PIPE_HE]" = "h/e pipe", \
+ "[PIPE_HE]_b" = "bent h/e pipe", \
+ "[PIPE_HE_MANIFOLD]" = "h/e manifold", \
+ "[PIPE_HE_4WAYMANIFOLD]"= "h/e 4-way manifold", \
+ "[PIPE_JUNCTION]" = "junction", \
+ \
+ "[PIPE_CONNECTOR]" = "connector", \
+ "[PIPE_UVENT]" = "vent", \
+ "[PIPE_SCRUBBER]" = "scrubber", \
+ "[PIPE_HEAT_EXCHANGE]" = "heat exchanger", \
+ \
+ "[PIPE_PUMP]" = "pump", \
+ "[PIPE_PASSIVE_GATE]" = "passive gate", \
+ "[PIPE_VOLUME_PUMP]" = "volume pump", \
+ "[PIPE_MVALVE]" = "manual valve", \
+ "[PIPE_DVALVE]" = "digital valve", \
+ \
+ "[PIPE_GAS_FILTER]" = "gas filter", \
+ "[PIPE_GAS_MIXER]" = "gas mixer", \
+ )
+ //fix_pipe_type()
+ name = nlist["[pipe_type][is_bent ? "_b" : ""]"] + " fitting"
+ icon_state = pipeID2State["[pipe_type]"]
// rotate the pipe item clockwise
@@ -187,207 +169,72 @@ var/global/list/pipeID2State = list(
return
+/obj/item/pipe/AltClick(mob/user)
+ ..()
+ if(!user.canUseTopic(user))
+ user << "You can't do that right now!"
+ return
+ if(!in_range(src, user))
+ return
+ else
+ rotate()
+
/obj/item/pipe/Move()
..()
- if ((pipe_type in list (PIPE_SIMPLE_BENT, PIPE_HE_BENT)) \
+ if ((pipe_type in list (PIPE_SIMPLE, PIPE_HE)) && is_bent \
&& (src.dir in cardinal))
src.dir = src.dir|turn(src.dir, 90)
else if ((pipe_type in list(PIPE_GAS_FILTER, PIPE_GAS_MIXER)) && flipped)
src.dir = turn(src.dir, 45+90)
- else if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_HE_STRAIGHT, PIPE_MVALVE, PIPE_DVALVE))
- if(dir==2)
- dir = 1
- else if(dir==8)
- dir = 4
- return
-
-// returns all pipe's endpoints
-
-/obj/item/pipe/proc/get_pipe_dir()
- if (!dir)
- return 0
-
- var/direct = dir
- if(flipped)
- direct = turn(dir, 45)
-
- var/flip = turn(direct, 180)
- var/cw = turn(direct, -90)
- var/acw = turn(direct, 90)
-
- switch(pipe_type)
- if( PIPE_SIMPLE_STRAIGHT, \
- PIPE_HE_STRAIGHT, \
- PIPE_JUNCTION, \
- PIPE_PUMP, \
- PIPE_VOLUME_PUMP, \
- PIPE_PASSIVE_GATE, \
- PIPE_MVALVE, \
- PIPE_DVALVE \
- )
- return direct|flip
- if(PIPE_SIMPLE_BENT, PIPE_HE_BENT)
- return direct //dir|acw
- if(PIPE_CONNECTOR,PIPE_UVENT,PIPE_SCRUBBER,PIPE_HEAT_EXCHANGE)
- return direct
- if(PIPE_MANIFOLD)
- return flip|cw|acw
- if(PIPE_4WAYMANIFOLD)
- return NORTH|SOUTH|EAST|WEST
- if(PIPE_GAS_FILTER, PIPE_GAS_MIXER)
- return direct|flip|cw
- return 0
-
-/obj/item/pipe/proc/get_pdir() //endpoints for regular pipes
-
- var/flip = turn(dir, 180)
-// var/cw = turn(dir, -90)
-// var/acw = turn(dir, 90)
-
- if (!(pipe_type in list(PIPE_HE_STRAIGHT, PIPE_HE_BENT, PIPE_JUNCTION)))
- return get_pipe_dir()
- switch(pipe_type)
- if(PIPE_HE_STRAIGHT,PIPE_HE_BENT)
- return 0
- if(PIPE_JUNCTION)
- return flip
- return 0
-
-// return the h_dir (heat-exchange pipes) from the type and the dir
-
-/obj/item/pipe/proc/get_hdir() //endpoints for h/e pipes
-
-// var/flip = turn(dir, 180)
-// var/cw = turn(dir, -90)
-
- switch(pipe_type)
- if(PIPE_HE_STRAIGHT)
- return get_pipe_dir()
- if(PIPE_HE_BENT)
- return get_pipe_dir()
- if(PIPE_JUNCTION)
- return dir
- else
- return 0
+ fixdir()
/obj/item/pipe/proc/unflip(direction)
- if(!(direction in cardinal))
+ if(direction in diagonals)
return turn(direction, 45)
return direction
//Helper to clean up dir
/obj/item/pipe/proc/fixdir()
- if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_HE_STRAIGHT, PIPE_MVALVE, PIPE_DVALVE))
- if(dir==2)
- dir = 1
- else if(dir==8)
- dir = 4
+ if((pipe_type in list (PIPE_SIMPLE, PIPE_HE, PIPE_MVALVE, PIPE_DVALVE)) && !is_bent)
+ if(dir==SOUTH)
+ dir = NORTH
+ else if(dir==WEST)
+ dir = EAST
/obj/item/pipe/attack_self(mob/user)
return rotate()
/obj/item/pipe/attackby(obj/item/weapon/W, mob/user, params)
-
- //*
if (!istype(W, /obj/item/weapon/wrench))
return ..()
if (!isturf(src.loc))
return 1
fixdir()
+ if(pipe_type in list(PIPE_GAS_MIXER, PIPE_GAS_FILTER))
+ dir = unflip(dir)
- var/pipe_dir = get_pipe_dir()
+ var/obj/machinery/atmospherics/A = new pipe_type(src.loc)
+ A.dir = src.dir
+ A.SetInitDirections()
for(var/obj/machinery/atmospherics/M in src.loc)
- if(M.initialize_directions & pipe_dir) // matches at least one direction on either type of pipe
+ if(M == A) //we don't want to check to see if it interferes with itself
+ continue
+ if(M.GetInitDirections() & A.GetInitDirections()) // matches at least one direction on either type of pipe
user << "There is already a pipe at that location!"
+ qdel(A)
return 1
// no conflicts found
- switch(pipe_type)
- if(PIPE_SIMPLE_STRAIGHT, PIPE_SIMPLE_BENT)
- var/obj/machinery/atmospherics/pipe/simple/P = new( src.loc )
- P.construction(dir, pipe_dir, pipe_type, color)
+ if(pipename)
+ A.name = pipename
- if(PIPE_HE_STRAIGHT, PIPE_HE_BENT)
- var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/P = new ( src.loc )
- P.initialize_directions_he = pipe_dir
- P.construction(dir, pipe_dir, pipe_type, color)
-
- if(PIPE_CONNECTOR)
- var/obj/machinery/atmospherics/components/unary/portables_connector/C = new( src.loc )
- if (pipename)
- C.name = pipename
- C.construction(dir, pipe_dir, pipe_type, color)
-
- if(PIPE_MANIFOLD)
- var/obj/machinery/atmospherics/pipe/manifold/M = new(loc)
- M.construction(dir, pipe_dir, pipe_type, color)
-
- if(PIPE_4WAYMANIFOLD)
- var/obj/machinery/atmospherics/pipe/manifold4w/M = new( src.loc )
- M.construction(dir, pipe_dir, pipe_type, color)
-
- if(PIPE_JUNCTION)
- var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/P = new ( src.loc )
- P.initialize_directions_he = src.get_hdir()
- P.construction(dir, get_pdir(), pipe_type, color)
-
- if(PIPE_UVENT)
- var/obj/machinery/atmospherics/components/unary/vent_pump/V = new( src.loc )
- V.construction(dir, pipe_dir, pipe_type, color)
-
- if(PIPE_MVALVE)
- var/obj/machinery/atmospherics/components/binary/valve/V = new(src.loc)
- if (pipename)
- V.name = pipename
- V.construction(dir, get_pdir(), pipe_type, color)
-
- if(PIPE_DVALVE)
- var/obj/machinery/atmospherics/components/binary/valve/digital/V = new(src.loc)
- if (pipename)
- V.name = pipename
- V.construction(dir, get_pdir(), pipe_type, color)
-
- if(PIPE_PUMP)
- var/obj/machinery/atmospherics/components/binary/pump/P = new(src.loc)
- P.construction(dir, pipe_dir, pipe_type, color)
-
- if(PIPE_GAS_FILTER, PIPE_GAS_MIXER)
- var/obj/machinery/atmospherics/components/trinary/P
- if(pipe_type == PIPE_GAS_FILTER)
- P = new /obj/machinery/atmospherics/components/trinary/filter(src.loc)
- else if(pipe_type == PIPE_GAS_MIXER)
- P = new /obj/machinery/atmospherics/components/trinary/mixer(src.loc)
- P.flipped = flipped
- if (pipename)
- P.name = pipename
- P.construction(unflip(dir), pipe_dir, pipe_type, color)
-
- if(PIPE_SCRUBBER)
- var/obj/machinery/atmospherics/components/unary/vent_scrubber/S = new(src.loc)
- if (pipename)
- S.name = pipename
- S.construction(dir, pipe_dir, pipe_type, color)
-
- if(PIPE_PASSIVE_GATE)
- var/obj/machinery/atmospherics/components/binary/passive_gate/P = new(src.loc)
- if (pipename)
- P.name = pipename
- P.construction(dir, pipe_dir, pipe_type, color)
-
- if(PIPE_VOLUME_PUMP)
- var/obj/machinery/atmospherics/components/binary/volume_pump/P = new(src.loc)
- if (pipename)
- P.name = pipename
- P.construction(dir, pipe_dir, pipe_type, color)
-
- if(PIPE_HEAT_EXCHANGE)
- var/obj/machinery/atmospherics/components/unary/heat_exchanger/C = new( src.loc )
- if (pipename)
- C.name = pipename
- C.construction(dir, pipe_dir, pipe_type, color)
+ var/obj/machinery/atmospherics/components/trinary/T = A
+ if(istype(T))
+ T.flipped = flipped
+ A.construction(pipe_type, color)
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user.visible_message( \
@@ -395,14 +242,7 @@ var/global/list/pipeID2State = list(
"You fasten \the [src].", \
"You hear ratchet.")
- qdel(src) // remove the pipe item
-
- return
- //TODO: DEFERRED
-
-// ensure that setterm() is called for a newly connected pipeline
-
-
+ qdel(src)
/obj/item/pipe_meter
name = "meter"
@@ -423,4 +263,4 @@ var/global/list/pipeID2State = list(
new/obj/machinery/meter( src.loc )
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You fasten the meter to the pipe."
- qdel(src)
+ qdel(src)
\ No newline at end of file
diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm
index 7861d46e552..a23489333ea 100644
--- a/code/game/machinery/pipe/pipe_dispenser.dm
+++ b/code/game/machinery/pipe/pipe_dispenser.dm
@@ -14,27 +14,29 @@
return 1
var/dat = {"
Regular pipes:
-Pipe
-Bent Pipe
-Manifold
-4-Way Manifold
-Manual Valve
-Digital Valve
+Pipe
+Bent Pipe
+Manifold
+4-Way Manifold
+Manual Valve
+Digital Valve Devices:
-Connector
-Vent
-Gas Pump
-Passive Gate
-Volume Pump
-Scrubber
+Connector
+Vent
+Gas Pump
+Passive Gate
+Volume Pump
+Scrubber Meter
-Gas Filter
-Gas Mixer
+Gas Filter
+Gas Mixer Heat exchange:
-Pipe
-Bent Pipe
-Junction
-Heat Exchanger
+Pipe
+Bent Pipe
+Manifold
+4-Way Manifold
+Junction
+Heat Exchanger
"}
@@ -52,17 +54,16 @@
src.add_fingerprint(usr)
if(href_list["make"])
if(!wait)
- var/p_type = text2num(href_list["make"])
+ var/p_type = text2path(href_list["make"])
var/p_dir = text2num(href_list["dir"])
- var/obj/item/pipe/P = new (/*usr.loc*/ src.loc, pipe_type=p_type, dir=p_dir)
- P.update()
+ var/obj/item/pipe/P = new (src.loc, pipe_type=p_type, dir=p_dir)
P.add_fingerprint(usr)
wait = 1
spawn(10)
wait = 0
if(href_list["makemeter"])
if(!wait)
- new /obj/item/pipe_meter(/*usr.loc*/ src.loc)
+ new /obj/item/pipe_meter(src.loc)
wait = 1
spawn(15)
wait = 0
@@ -111,7 +112,7 @@
icon = 'icons/obj/stationobjs.dmi'
icon_state = "pipe_d"
density = 1
- anchored = 1.0
+ anchored = 1
/*
//Allow you to push disposal pipes into it (for those with density 1)
@@ -187,7 +188,7 @@ Nah
icon = 'icons/obj/stationobjs.dmi'
icon_state = "pipe_d"
density = 1
- anchored = 1.0
+ anchored = 1
/obj/machinery/pipedispenser/disposal/transit_tube/attack_hand(mob/user)
if(..())
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index 707abc57f65..78c2f6c826f 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -144,7 +144,7 @@
//deletes its own cover with it
qdel(cover)
cover = null
- ..()
+ return ..()
/obj/machinery/porta_turret/attack_ai(mob/user)
@@ -311,7 +311,7 @@
/obj/machinery/porta_turret/attack_animal(mob/living/simple_animal/M)
M.changeNext_move(CLICK_CD_MELEE)
M.do_attack_animation(src)
- if(M.melee_damage_upper == 0)
+ if(M.melee_damage_upper == 0 || (M.melee_damage_type != BRUTE && M.melee_damage_type != BURN))
return
if(!(stat & BROKEN))
visible_message("[M] [M.attacktext] [src]!")
@@ -1092,7 +1092,7 @@ Status: [] "},
user << "You short out the turret controls' access analysis module."
emagged = 1
locked = 0
- if(user.machine==src)
+ if(user && user.machine==src)
src.attack_hand(user)
/obj/machinery/turretid/attack_ai(mob/user)
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index aaef91bc811..40bc46865e6 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -10,38 +10,42 @@
/obj/machinery/recharger/attackby(obj/item/weapon/G, mob/user, params)
- if(istype(user,/mob/living/silicon))
- return
- if(istype(G, /obj/item/weapon/gun/energy) || istype(G, /obj/item/weapon/melee/baton))
- if(charging)
- return
-
- //Checks to make sure he's not in space doing it, and that the area got proper power.
- var/area/a = get_area(src)
- if(!isarea(a) || a.power_equip == 0)
- user << "[src] blinks red as you try to insert [G]."
- return
-
- if (istype(G, /obj/item/weapon/gun/energy))
- var/obj/item/weapon/gun/energy/gun = G
- if(!gun.can_charge)
- user << "Your gun has no external power connector."
- return
- if(!user.drop_item())
- return
-
- G.loc = src
- charging = G
- use_power = 2
- update_icon()
- else if(istype(G, /obj/item/weapon/wrench))
+ if(istype(G, /obj/item/weapon/wrench))
if(charging)
user << "Remove the charging item first!"
return
anchored = !anchored
+ power_change()
user << "You [anchored ? "attached" : "detached"] [src]."
playsound(loc, 'sound/items/Ratchet.ogg', 75, 1)
+ return
+ if(istype(user,/mob/living/silicon))
+ return
+ if(istype(G, /obj/item/weapon/gun/energy) || istype(G, /obj/item/weapon/melee/baton))
+ if(anchored)
+ if(charging)
+ return
+ //Checks to make sure he's not in space doing it, and that the area got proper power.
+ var/area/a = get_area(src)
+ if(!isarea(a) || a.power_equip == 0)
+ user << "[src] blinks red as you try to insert [G]."
+ return
+
+ if (istype(G, /obj/item/weapon/gun/energy))
+ var/obj/item/weapon/gun/energy/gun = G
+ if(!gun.can_charge)
+ user << "Your gun has no external power connector."
+ return
+ if(!user.drop_item())
+ return
+
+ G.loc = src
+ charging = G
+ use_power = 2
+ update_icon()
+ else
+ user << "[src] isn't connected to anything!"
/obj/machinery/recharger/attack_hand(mob/user)
if(issilicon(user))
diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index 49245b20148..48962ff51a7 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -146,12 +146,12 @@
st.energy = min(st.max_energy, st.energy + coeff * st.recharge_rate)
for(var/obj/O in um)
//General
- if(istype(O,/obj/item/device/flash))
- var/obj/item/device/flash/F = O
- if(F.broken)
- F.broken = 0
+ if(istype(O,/obj/item/device/assembly/flash))
+ var/obj/item/device/assembly/flash/F = O
+ if(F.crit_fail)
+ F.crit_fail = 0
F.times_used = 0
- F.icon_state = "flash"
+ F.update_icon()
// Security
if(istype(O,/obj/item/weapon/gun/energy/gun/advtaser/cyborg))
var/obj/item/weapon/gun/energy/gun/advtaser/cyborg/T = O
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index 9e4b3da49d0..57fd990d2dd 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -14,9 +14,7 @@ var/const/SAFETY_COOLDOWN = 100
var/blood = 0
var/eat_dir = WEST
var/amount_produced = 1
- var/probability_mod = 1
- var/extra_materials = 0
- var/list/blacklist = list(/obj/item/pipe, /obj/item/pipe_meter, /obj/structure/disposalconstruct, /obj/item/weapon/reagent_containers, /obj/item/weapon/paper, /obj/item/stack/, /obj/item/weapon/pen, /obj/item/weapon/storage/, /obj/item/clothing/mask/cigarette) // Don't allow us to grind things we can poop out at 200 a second for free.
+ var/datum/material_container/materials
/obj/machinery/recycler/New()
// On us
@@ -25,25 +23,20 @@ var/const/SAFETY_COOLDOWN = 100
component_parts += new /obj/item/weapon/circuitboard/recycler(null)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
+ materials = new /datum/material_container(src, list(MAT_METAL=1, MAT_GLASS=1, MAT_SILVER=1, MAT_GOLD=1, MAT_DIAMOND=1, MAT_URANIUM=1, MAT_BANANIUM=1))
RefreshParts()
update_icon()
/obj/machinery/recycler/RefreshParts()
var/amt_made = 0
- var/prob_mod = 0
+ var/mat_mod = 0
for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts)
- amt_made = 1 * B.rating
+ mat_mod = 2 * B.rating
+ mat_mod *= 50000
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
- if(M.rating > 1)
- prob_mod = 2 * M.rating
- else
- prob_mod = 1 * M.rating
- if(M.rating >= 3)
- extra_materials = 1
- else
- extra_materials = 0
- probability_mod = prob_mod
- amount_produced = amt_made
+ amt_made = 25 * M.rating //% of materials salvaged
+ materials.max_amount = mat_mod
+ amount_produced = min(100, amt_made)
/obj/machinery/recycler/examine(mob/user)
..()
@@ -121,36 +114,18 @@ var/const/SAFETY_COOLDOWN = 100
/obj/machinery/recycler/proc/recycle(obj/item/I, sound = 1)
I.loc = src.loc
- if(is_type_in_list(I, blacklist))
- qdel(I)
- if(sound)
- playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
+ if(!istype(I))
return
- qdel(I)
- if(prob(15 + probability_mod))
- var/obj/item/stack/sheet/metal/M = new /obj/item/stack/sheet/metal(loc)
- M.amount = amount_produced
- if(prob(10 + probability_mod))
- var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(loc)
- G.amount = amount_produced
- if(prob(2 + probability_mod))
- var/obj/item/stack/sheet/plasteel/P = new /obj/item/stack/sheet/plasteel(loc)
- P.amount = amount_produced
- if(prob(1 + probability_mod))
- var/obj/item/stack/sheet/rglass/R = new /obj/item/stack/sheet/rglass(loc)
- R.amount = amount_produced
- if(extra_materials)
- if(prob(3 + probability_mod))
- var/obj/item/stack/sheet/mineral/gold/GS = new /obj/item/stack/sheet/mineral/gold(loc)
- GS.amount = amount_produced
- if(prob(2 + probability_mod))
- var/obj/item/stack/sheet/mineral/silver/S = new /obj/item/stack/sheet/mineral/silver(loc)
- S.amount = amount_produced
- if(prob(1 + probability_mod))
- var/obj/item/stack/sheet/mineral/bananium/B = new /obj/item/stack/sheet/mineral/bananium(loc)
- B.amount = amount_produced
+
if(sound)
playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
+ var/material_amount = materials.get_item_material_amount(I)
+ if(!material_amount)
+ qdel(I)
+ return
+ materials.insert_item(I, multiplier = (amount_produced / 100))
+ qdel(I)
+ materials.retrieve_all()
/obj/machinery/recycler/proc/stop(mob/living/L)
diff --git a/code/game/machinery/robot_fabricator.dm b/code/game/machinery/robot_fabricator.dm
index ad5c467857b..c0571ef5a20 100644
--- a/code/game/machinery/robot_fabricator.dm
+++ b/code/game/machinery/robot_fabricator.dm
@@ -13,7 +13,7 @@
/obj/machinery/robotic_fabricator/attackby(obj/item/O, mob/user, params)
if (istype(O, /obj/item/stack/sheet/metal))
- if (src.metal_amount < 150000.0)
+ if (src.metal_amount < 150000)
var/count = 0
src.overlays += "fab-load-metal"
spawn(15)
@@ -21,7 +21,7 @@
if(!O:amount)
return
while(metal_amount < 150000 && O:amount)
- src.metal_amount += O:materials[MAT_METAL] /*O:height * O:width * O:length * 100000.0*/
+ src.metal_amount += O:materials[MAT_METAL] /*O:height * O:width * O:length * 100000*/
O:amount--
count++
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index ca1fe863e3b..f9c4c171f3b 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -19,7 +19,7 @@
opacity = 0
density = 0
air_update_turf(1)
- ..()
+ return ..()
/obj/machinery/shield/Move()
var/turf/T = loc
@@ -66,13 +66,13 @@
/obj/machinery/shield/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
if (prob(75))
qdel(src)
- if(2.0)
+ if(2)
if (prob(50))
qdel(src)
- if(3.0)
+ if(3)
if (prob(25))
qdel(src)
return
@@ -141,7 +141,7 @@
for(var/obj/machinery/shield/shield_tile in deployed_shields)
qdel(shield_tile)
deployed_shields = null
- ..()
+ return ..()
/obj/machinery/shieldgen/proc/shields_up()
@@ -182,15 +182,15 @@
/obj/machinery/shieldgen/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
src.health -= 75
src.checkhp()
- if(2.0)
+ if(2)
src.health -= 30
if (prob(15))
src.malfunction = 1
src.checkhp()
- if(3.0)
+ if(3)
src.health -= 10
src.checkhp()
return
@@ -500,7 +500,7 @@
src.cleanup(2)
src.cleanup(4)
src.cleanup(8)
- ..()
+ return ..()
/obj/machinery/shieldwallgen/bullet_act(obj/item/projectile/Proj)
storedpower -= Proj.damage
@@ -570,21 +570,21 @@
if(needs_power)
var/obj/machinery/shieldwallgen/G
switch(severity)
- if(1.0) //big boom
+ if(1) //big boom
if(prob(50))
G = gen_primary
else
G = gen_secondary
G.storedpower -= 200
- if(2.0) //medium boom
+ if(2) //medium boom
if(prob(50))
G = gen_primary
else
G = gen_secondary
G.storedpower -= 50
- if(3.0) //lil boom
+ if(3) //lil boom
if(prob(50))
G = gen_primary
else
diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm
index a0110d2f25a..d3e952699f7 100644
--- a/code/game/machinery/status_display.dm
+++ b/code/game/machinery/status_display.dm
@@ -51,7 +51,7 @@
/obj/machinery/status_display/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
- ..()
+ return ..()
// timed process
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index 67b8c167772..a6e9c226736 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -2,35 +2,59 @@
// SUIT STORAGE UNIT /////////////////
//////////////////////////////////////
+#define REPAIR_NEEDS_WIRECUTTERS 1
+#define REPAIR_NEEDS_WIRES 2
+#define REPAIR_NEEDS_CROWBAR 3
+#define REPAIR_NEEDS_METAL 4
/obj/machinery/suit_storage_unit
name = "suit storage unit"
- desc = "An industrial U-Stor-It Storage unit designed to accomodate all kinds of space suits. Its on-board equipment also allows the user to decontaminate the contents through a UV-ray purging cycle. There's a warning label dangling from the control pad, reading \"STRICTLY NO BIOLOGICALS IN THE CONFINES OF THE UNIT\"."
+ desc = "An industrial unit made to hold space suits. It comes with a built-in UV cauterization mechanism. A small warning label advises that organic matter should not be placed into the unit."
icon = 'icons/obj/suitstorage.dmi'
icon_state = "close"
anchored = 1
density = 1
+ //Vars to hold internal items
var/mob/living/OCCUPANT = null
var/obj/item/clothing/suit/space/SUIT = null
- var/SUIT_TYPE = null
var/obj/item/clothing/head/helmet/space/HELMET = null
+ var/obj/item/clothing/mask/MASK = null
+ var/obj/item/STORAGE = null
+
+ //Base types on creation
+ var/SUIT_TYPE = null
var/HELMET_TYPE = null
- var/obj/item/clothing/mask/MASK = null //All the stuff that's gonna be stored insiiiiiiiiiiiiiiiiiiide, nyoro~n
- var/MASK_TYPE = null //Erro's idea on standarising SSUs whle keeping creation of other SSU types easy: Make a child SSU, name it something then set the TYPE vars to your desired suit output. New() should take it from there by itself.
- var/obj/item/STORAGE = null //One-slot storage slot for anything... food not recommended
+ var/MASK_TYPE = null
var/STORAGE_TYPE = null
+
+ //Machine related vars
var/isopen = 0
var/islocked = 0
var/isUV = 0
- var/ispowered = 1 //starts powered
+ var/ispowered = 1
var/isbroken = 0
var/issuperUV = 0
- var/panelopen = 0
var/safetieson = 1
var/cycletime_left = 0
+ var/repair_stage = 0
+
+/obj/machinery/suit_storage_unit/examine(mob/user)
+ ..()
+ if(isbroken && isopen)
+ if(!panel_open)
+ user << "A small LED above the maintenance panel is flashing red."
+ return
+ switch(repair_stage)
+ if(REPAIR_NEEDS_WIRECUTTERS)
+ user << "The wires inside are charred and snapped."
+ if(REPAIR_NEEDS_WIRES)
+ user << "There are no wires inside."
+ if(REPAIR_NEEDS_CROWBAR)
+ user << "Some of the interior metal is burnt and broken."
+ if(REPAIR_NEEDS_METAL)
+ user << "It lacks interior plating."
-//The units themselves/////////////////
/obj/machinery/suit_storage_unit/standard_unit
SUIT_TYPE = /obj/item/clothing/suit/space/eva
@@ -143,12 +167,12 @@
/obj/machinery/suit_storage_unit/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
if(prob(50))
src.dump_everything() //So suits dont survive all the time
qdel(src)
return
- if(2.0)
+ if(2)
if(prob(50))
src.dump_everything()
qdel(src)
@@ -164,21 +188,17 @@
return
if(stat & NOPOWER)
return
- if(src.panelopen) //The maintenance panel is open. Time for some shady stuff
+ if(src.panel_open) //The maintenance panel is open. Time for some shady stuff
dat+= "Suit storage unit: Maintenance panel"
dat+= "Maintenance panel controls"
- dat+= "The panel is ridden with controls, button and meters, labeled in strange signs and symbols that you cannot understand. Probably the manufactoring world's language. Among other things, a few controls catch your eye.
"
- dat+= text("A small dial with a \"ë\" symbol embroidded on it. It's pointing towards a gauge that reads []. Turn towards [] ",(src.issuperUV ? "15nm" : "185nm"),src,(src.issuperUV ? "185nm" : "15nm") )
+ dat+= "The panel is ridden with controls, button and meters, labeled in strange signs and symbols that you cannot understand; probably the manufacturing world's language. Among other things, a few controls catch your eye...
"
+ dat+= text("A small dial with a \"ë\" symbol embroidded on it. It's pointing towards a gauge that reads []. Turn towards [] ",(src.issuperUV ? "15nm" : "185nm"),src,(src.issuperUV ? "185nm" : "15nm") )
dat+= text("A thick old-style button, with 2 grimy LED lights next to it. The [] LED is on. Press button",(src.safetieson? "GREEN" : "RED"),src)
dat+= text(" Close panel", user)
- //user << browse(dat, "window=ssu_m_panel;size=400x500")
- //onclose(user, "ssu_m_panel")
else if(src.isUV) //The thing is running its cauterisation cycle. You have to wait.
dat += "Suit storage unit"
dat+= "Unit is cauterising contents with selected UV ray intensity. Please wait. "
- //dat+= "Cycle end in: [src.cycletimeleft()] seconds. "
- //user << browse(dat, "window=ssu_cycling_panel;size=400x500")
- //onclose(user, "ssu_cycling_panel")
+
else
if(!src.isbroken)
@@ -208,14 +228,12 @@
dat+= text("Unit status: []",(src.islocked? "**LOCKED** " : "**UNLOCKED** ") )
dat+= text("Start Disinfection cycle ",src)
dat += text("
Close control panel", user)
- //user << browse(dat, "window=Suit Storage Unit;size=400x500")
- //onclose(user, "Suit Storage Unit")
+
else //Ohhhh shit it's dirty or broken! Let's inform the guy.
dat+= "Suit storage unit"
dat+= "Unit chamber is too contaminated to continue usage. Please call for a qualified individual to perform maintenance.
"
dat+= text("Close control panel", user)
- //user << browse(dat, "window=suit_storage_unit;size=400x500")
- //onclose(user, "suit_storage_unit")
+
var/datum/browser/popup = new(user, "suit_storage_unit", "Suit Storage Unit", 440, 500)
popup.set_content(dat)
@@ -227,7 +245,7 @@
/obj/machinery/suit_storage_unit/Topic(href, href_list) //I fucking HATE this proc
if(..())
return
- if(usr == src.OCCUPANT) //No unlocking yourself out!
+ if(usr == src.OCCUPANT)
return
if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon/ai)))
usr.set_machine(src)
@@ -253,29 +271,15 @@
src.eject_occupant(usr)
src.updateUsrDialog()
src.update_icon()
- /*if (href_list["refresh"])
- src.updateUsrDialog()*/
src.add_fingerprint(usr)
return
/obj/machinery/suit_storage_unit/proc/toggleUV(mob/user)
-// var/protected = 0
-// var/mob/living/carbon/human/H = user
- if(!src.panelopen)
+ if(!src.panel_open)
return
- /*if(istype(H)) //Let's check if the guy's wearing electrically insulated gloves
- if(H.gloves)
- var/obj/item/clothing/gloves/G = H.gloves
- if(istype(G,/obj/item/clothing/gloves/yellow))
- protected = 1
-
- if(!protected)
- playsound(src.loc, "sparks", 75, 1, -1)
- user << "You try to touch the controls but you get zapped. There must be a short circuit somewhere."
- return*/
- else //welp, the guy is protected, we can continue
+ else
if(src.issuperUV)
user << "You slide the dial back towards \"185nm\"."
src.issuperUV = 0
@@ -286,21 +290,8 @@
/obj/machinery/suit_storage_unit/proc/togglesafeties(mob/user)
-// var/protected = 0
-// var/mob/living/carbon/human/H = user
- if(!src.panelopen) //Needed check due to bugs
+ if(!src.panel_open) //Needed check due to bugs
return
-
- /*if(istype(H)) //Let's check if the guy's wearing electrically insulated gloves
- if(H.gloves)
- var/obj/item/clothing/gloves/G = H.gloves
- if(istype(G,/obj/item/clothing/gloves/yellow) )
- protected = 1
-
- if(!protected)
- playsound(src.loc, "sparks", 75, 1, -1)
- user << "You try to touch the controls but you get zapped. There must be a short circuit somewhere."
- return*/
else
user << "You push the button. The coloured LED next to it changes."
src.safetieson = !src.safetieson
@@ -323,7 +314,9 @@
STORAGE = null
/obj/machinery/suit_storage_unit/proc/eject(atom/movable/ITEM)
- ITEM.loc = src.loc
+ //Check item still exists - if not, then usually someone has already ejected the item
+ if(ITEM)
+ ITEM.loc = src.loc
/obj/machinery/suit_storage_unit/proc/dump_everything()
for(var/obj/item/ITEM in src)
@@ -350,7 +343,7 @@
/obj/machinery/suit_storage_unit/proc/toggle_lock(mob/user)
if(src.OCCUPANT && src.safetieson)
- user << "The Unit's safety protocols disallow locking when a biological form is detected inside its compartments."
+ user << "The unit's safety protocols disallow locking when a biological form is detected inside its compartments."
return
if(src.isopen)
return
@@ -362,12 +355,12 @@
if(src.isUV || src.isopen) //I'm bored of all these sanity checks
return
if(src.OCCUPANT && src.safetieson)
- user << "WARNING: Biological entity detected in the confines of the Unit's storage. Cannot initiate cycle."
+ user << "WARNING: Biological entity detected in the confines of the unit's storage. Cannot initiate cycle."
return
- if(!src.HELMET && !src.MASK && !src.SUIT && !src.STORAGE && !src.OCCUPANT ) //shit's empty yo
+ if(!src.HELMET && !src.MASK && !src.SUIT && !src.STORAGE && !src.OCCUPANT )
user << "Unit storage bays empty. Nothing to disinfect -- Aborting."
return
- user << "You start the Unit's cauterisation cycle."
+ user << "You start the unit's cauterisation cycle."
src.cycletime_left = 20
src.isUV = 1
if(src.OCCUPANT && !src.islocked)
@@ -375,7 +368,7 @@
src.update_icon()
src.updateUsrDialog()
- var/i //our counter
+ var/i
spawn(0)
for(i=0,i<4,++i)
sleep(50)
@@ -393,17 +386,18 @@
for(var/obj/item/ITEM in src)
ITEM.clean_blood()
if(istype(STORAGE, /obj/item/weapon/reagent_containers/food))
- del(STORAGE)
+ qdel(STORAGE)
else //It was supercycling, destroy everything
src.HELMET = null
src.SUIT = null
src.MASK = null
- del(STORAGE)
- visible_message("With a loud whining noise, the Suit Storage Unit's door grinds open. Puffs of ashen smoke come out of its chamber.", 3)
+ qdel(STORAGE)
+ visible_message("With a loud whining noise, [src]'s door grinds open. A foul cloud of smoke emanates from the chamber.")
src.isbroken = 1
src.isopen = 1
src.islocked = 0
- src.eject_occupant(OCCUPANT) //Mixing up these two lines causes bug. DO NOT DO IT.
+ repair_stage = REPAIR_NEEDS_WIRECUTTERS
+ src.eject_occupant(OCCUPANT)
src.isUV = 0 //Cycle ends
src.update_icon()
src.updateUsrDialog()
@@ -421,14 +415,12 @@
if (!src.OCCUPANT)
return
-// for(var/obj/O in src)
-// O.loc = src.loc
if (src.OCCUPANT.client)
if(user != OCCUPANT)
- OCCUPANT << "The machine kicks you out!"
+ OCCUPANT << "The machine kicks you out!"
if(user.loc != src.loc)
- OCCUPANT << "You leave the not-so-cozy confines of the SSU."
+ OCCUPANT << "You leave the not-so-cozy confines of [src]."
src.OCCUPANT.client.eye = src.OCCUPANT.client.mob
src.OCCUPANT.client.perspective = MOB_PERSPECTIVE
@@ -455,7 +447,7 @@
else
isopen = 1
islocked = 0
- visible_message("[user] successfully broke out of [src]!")
+ visible_message("[user] kicks their way out of [src]!")
else
return
@@ -484,9 +476,9 @@
user << "It's too cluttered inside to fit in!"
return
if(M == user)
- visible_message("[user] starts squeezing into the suit storage unit!", 3)
+ visible_message("[user] squeezes into [src]!", "You squeeze into [src].")
else
- visible_message("[user] starts putting [M.name] into the Suit Storage Unit!", 3)
+ M.visible_message("[user] starts putting [M] into [src]!", "[user] starts shoving you into [src]!")
if(do_mob(user, M, 10))
user.stop_pulling()
if(M.client)
@@ -494,7 +486,7 @@
M.client.eye = src
M.loc = src
src.OCCUPANT = M
- src.isopen = 0 //Close the thing after the guy gets inside
+ src.isopen = 0
src.update_icon()
src.add_fingerprint(user)
@@ -502,21 +494,83 @@
return
return
+/obj/machinery/suit_storage_unit/proc/fix()
+ audible_message("[src] beeps and comes back online!")
+ playsound(src, 'sound/machines/defib_ready.ogg', 50, 1)
+ repair_stage = 0
+ isbroken = 0
+ update_icon()
/obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params)
if(!src.ispowered)
if(istype(I, /obj/item/weapon/crowbar) && !isopen)
if(toggle_open(user))
dump_everything()
- user << text("You pry \the [src] open.")
+ user << text("You pry open [src]'s doors.")
update_icon()
return
if(istype(I, /obj/item/weapon/screwdriver))
- src.panelopen = !src.panelopen
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1)
- user << text("You [] the unit's maintenance panel.",(src.panelopen ? "open up" : "close") )
+ src.panel_open = !src.panel_open
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ user << text("You [] the unit's maintenance panel.",(src.panel_open ? "open up" : "close") )
src.updateUsrDialog()
return
+ if(isbroken && panel_open)
+ if(istype(I, /obj/item/weapon/wirecutters) && repair_stage == REPAIR_NEEDS_WIRECUTTERS)
+ user.visible_message("[user] starts removing [src]'s damaged wires.", \
+ "You begin removing the damaged wires from [src]...")
+ playsound(src, 'sound/items/Wirecutter.ogg', 50, 1)
+ if(!do_after(user, 30, target = src))
+ return
+ user.visible_message("[user] removes the damaged wires from [src].", \
+ "You remove the damaged wiring from [src].")
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
+ repair_stage = REPAIR_NEEDS_WIRES
+ return
+ if(istype(I, /obj/item/stack/cable_coil) && repair_stage == REPAIR_NEEDS_WIRES)
+ var/obj/item/stack/cable_coil/C = I
+ if(C.amount < 5)
+ user << "You need at least five cables to rewire [src]!"
+ return
+ user.visible_message("[user] begins replacing [src] wires.", \
+ "You begin rewiring [src]...")
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
+ if(!do_after(user, 30, target = src))
+ return
+ user.visible_message("[user] adds wires to [src].", \
+ "You rewire [src].")
+ C.amount -= 5
+ if(C.amount <= 0)
+ user.drop_item()
+ qdel(C)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
+ repair_stage = REPAIR_NEEDS_CROWBAR
+ return
+ if(istype(I, /obj/item/weapon/crowbar) && repair_stage == REPAIR_NEEDS_CROWBAR)
+ user.visible_message("[user] starts removing [src]'s broken interior plating.", \
+ "You begin removing the damaged interior plating from [src]...")
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
+ if(!do_after(user, 30, target = src))
+ return
+ user.visible_message("[user] removes the damaged interior plating from [src].", \
+ "You remove the damaged interior plating from [src].")
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
+ repair_stage = REPAIR_NEEDS_METAL
+ return
+ if(istype(I, /obj/item/stack/sheet/metal) && repair_stage == REPAIR_NEEDS_METAL)
+ var/obj/item/stack/sheet/metal/M = I
+ if(M.amount < 3)
+ user << "You need at least three sheets of metal to repair [src]!"
+ return
+ user.visible_message("[user] starts adding interior plating to [src].", \
+ "You begin adding interior plating to [src]...")
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
+ if(!do_after(user, 30, target = src))
+ return
+ user.visible_message("[user] adds interior plating to [src].", \
+ "You add interior plating to [src].")
+ fix()
+ return
if ( istype(I, /obj/item/weapon/grab) )
var/obj/item/weapon/grab/G = I
store_mob(G.affecting, user)
@@ -529,9 +583,9 @@
user << "The unit already contains a suit."
return
if(!user.drop_item())
- user << "\The [S] is stuck to your hand, you cannot put it in the Suit Storage Unit!"
+ user << "[S] is stuck to your hand, you cannot put it in [src]!"
return
- user << "You load the [S.name] into the suit storage compartment."
+ user << "You load [S] into the suit storage compartment."
S.loc = src
src.SUIT = S
src.update_icon()
@@ -545,9 +599,9 @@
user << "The unit already contains a helmet!"
return
if(!user.drop_item())
- user << "\The [H] is stuck to your hand, you cannot put it in the Suit Storage Unit!"
+ user << "[H] is stuck to your hand, you cannot put it in the Suit Storage Unit!"
return
- user << "You load the [H.name] into the helmet storage compartment."
+ user << "You load [H] into the helmet storage compartment."
H.loc = src
src.HELMET = H
src.update_icon()
@@ -561,9 +615,9 @@
user << "The unit already contains a mask!"
return
if(!user.drop_item())
- user << "\The [M] is stuck to your hand, you cannot put it in the Suit Storage Unit!"
+ user << "[M] is stuck to your hand, you cannot put it in the Suit Storage Unit!"
return
- user << "You load the [M.name] into the mask storage compartment."
+ user << "You load [M] into the mask storage compartment."
M.loc = src
src.MASK = M
src.update_icon()
@@ -577,9 +631,9 @@
user << "The auxiliary storage compartment is full!"
return
if(!user.drop_item())
- user << "\The [ITEM] is stuck to your hand, you cannot put it in the Suit Storage Unit!"
+ user << "[ITEM] is stuck to your hand, you cannot put it in the Suit Storage Unit!"
return
- user << "You load the [ITEM.name] into the auxiliary storage compartment."
+ user << "You load [ITEM] into the auxiliary storage compartment."
ITEM.loc = src
src.STORAGE = ITEM
src.update_icon()
@@ -592,8 +646,10 @@
/obj/machinery/suit_storage_unit/attack_paw(mob/user)
- user << "The console controls are far too complicated for your tiny brain!"
+ user << "You don't know how to work this!"
return
-
-//////////////////////////////REMINDER: Make it lock once you place some fucker inside.
+#undef REPAIR_NEEDS_WIRECUTTERS
+#undef REPAIR_NEEDS_WIRES
+#undef REPAIR_NEEDS_CROWBAR
+#undef REPAIR_NEEDS_METAL
diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm
index 2c102e8695b..395f15e7cfd 100644
--- a/code/game/machinery/syndicatebeacon.dm
+++ b/code/game/machinery/syndicatebeacon.dm
@@ -179,7 +179,7 @@
/obj/machinery/power/singularity_beacon/Destroy()
if(active)
Deactivate()
- ..()
+ return ..()
//stealth direct power usage
/obj/machinery/power/singularity_beacon/process()
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index c4df97166da..120a797fbae 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -40,6 +40,10 @@
update_icon()
..()
+/obj/machinery/syndicatebomb/Destroy()
+ qdel(wires)
+ wires = null
+ return ..()
/obj/machinery/syndicatebomb/examine(mob/user)
..()
@@ -72,9 +76,8 @@
update_icon()
user << "You [open_panel ? "open" : "close"] the wire panel."
- else if(istype(I, /obj/item/weapon/wirecutters) || istype(I, /obj/item/device/multitool) || istype(I, /obj/item/device/assembly/signaler ))
- if(open_panel)
- wires.Interact(user)
+ else if(wires.IsInteractionTool(I) && open_panel)
+ wires.Interact(user)
else if(istype(I, /obj/item/weapon/crowbar))
if(open_panel && isWireCut(WIRE_BOOM) && isWireCut(WIRE_UNBOLT) && isWireCut(WIRE_DELAY) && isWireCut(WIRE_PROCEED) && isWireCut(WIRE_ACTIVATE))
@@ -177,7 +180,7 @@
icon = 'icons/obj/assemblies.dmi'
icon_state = "bombcore"
item_state = "eshield0"
- w_class = 3.0
+ w_class = 3
origin_tech = "syndicate=6;combat=5"
var/adminlog = null
@@ -293,7 +296,7 @@
icon = 'icons/obj/assemblies.dmi'
icon_state = "bigred"
item_state = "electronic"
- w_class = 1.0
+ w_class = 1
origin_tech = "syndicate=2"
var/cooldown = 0
var/detonated = 0
diff --git a/code/game/machinery/telecomms/computers/logbrowser.dm b/code/game/machinery/telecomms/computers/logbrowser.dm
index eca9a206429..c30b28534d5 100644
--- a/code/game/machinery/telecomms/computers/logbrowser.dm
+++ b/code/game/machinery/telecomms/computers/logbrowser.dm
@@ -197,7 +197,7 @@
temp = "- DELETED ENTRY: [D.name] -"
SelectedServer.log_entries.Remove(D)
- del(D)
+ qdel(D)
else
temp = "- FAILED: NO SELECTED MACHINE -"
diff --git a/code/game/machinery/telecomms/machines/broadcaster.dm b/code/game/machinery/telecomms/machines/broadcaster.dm
index 181d9a11bbf..91106eae92e 100644
--- a/code/game/machinery/telecomms/machines/broadcaster.dm
+++ b/code/game/machinery/telecomms/machines/broadcaster.dm
@@ -110,7 +110,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// In case message_delay is left on 1, otherwise it won't reset the list and people can't say the same thing twice anymore.
if(message_delay)
message_delay = 0
- ..()
+ return ..()
diff --git a/code/game/machinery/telecomms/machines/server.dm b/code/game/machinery/telecomms/machines/server.dm
index 8613a7bdad4..2a331406060 100644
--- a/code/game/machinery/telecomms/machines/server.dm
+++ b/code/game/machinery/telecomms/machines/server.dm
@@ -55,7 +55,7 @@
if(Compiler)
Compiler.GC()
Compiler = null
- ..()
+ return ..()
/obj/machinery/telecomms/server/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
if(signal.data["message"])
diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm
index 361097145bb..37a8f60d35e 100644
--- a/code/game/machinery/telecomms/telecomunications.dm
+++ b/code/game/machinery/telecomms/telecomunications.dm
@@ -158,7 +158,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
for(var/obj/machinery/telecomms/comm in telecomms_list)
comm.links -= src
links = list()
- ..()
+ return ..()
// Used in auto linking
/obj/machinery/telecomms/proc/add_link(obj/machinery/telecomms/T)
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index e341ca965b6..8758e299501 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -25,6 +25,7 @@
if (power_station)
power_station.teleporter_console = null
power_station = null
+ return ..()
/obj/machinery/computer/teleporter/proc/link_power_station()
if(power_station)
@@ -179,7 +180,7 @@
areaindex[tmpname] = 1
L[tmpname] = R
- for (var/obj/item/weapon/implant/tracking/I in world)
+ for (var/obj/item/weapon/implant/tracking/I in tracked_implants)
if (!I.implanted || !ismob(I.loc))
continue
else
@@ -237,7 +238,7 @@
name = "teleport"
icon = 'icons/obj/stationobjs.dmi'
density = 1
- anchored = 1.0
+ anchored = 1
/obj/machinery/teleport/hub
name = "teleporter hub"
@@ -268,6 +269,7 @@
if (power_station)
power_station.teleporter_hub = null
power_station = null
+ return ..()
/obj/machinery/teleport/hub/RefreshParts()
var/A = 0
@@ -313,8 +315,8 @@
var/mob/living/carbon/human/human = M
if(human.dna && human.dna.species.id == "human")
M << "You hear a buzzing in your ears."
- hardset_dna(human, null, null, null, null, /datum/species/fly)
- human.regenerate_icons()
+ human.set_species(/datum/species/fly)
+
human.apply_effect((rand(120 - accurate * 40, 180 - accurate * 60)), IRRADIATE, 0)
calibrated = 0
return
@@ -389,7 +391,7 @@
if (teleporter_console)
teleporter_console.power_station = null
teleporter_console = null
- ..()
+ return ..()
/obj/machinery/teleport/station/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/device/multitool) && !panel_open)
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index a3787a9b5ab..8eaab61fe7a 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -84,11 +84,13 @@
wires = null
qdel(coin)
coin = null
- ..()
+ return ..()
/obj/machinery/vending/snack/Destroy()
for(var/obj/item/weapon/reagent_containers/food/snacks/S in contents)
S.loc = get_turf(src)
+ qdel(wires)
+ wires = null
return ..()
/obj/machinery/vending/RefreshParts() //Better would be to make constructable child
@@ -642,7 +644,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola = 8, /obj/item/weapon/reagent_containers/food/drinks/soda_cans/sodawater = 15,
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 30,/obj/item/weapon/reagent_containers/food/drinks/ice = 10,
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/shotglass = 12)
- contraband = list(/obj/item/weapon/reagent_containers/food/drinks/tea = 12)
+ contraband = list(/obj/item/weapon/reagent_containers/food/drinks/mug/tea = 12)
vend_delay = 15
product_slogans = "I hope nobody asks me for a bloody cup o' tea...;Alcohol is humanity's friend. Would you abandon a friend?;Quite delighted to serve you!;Is nobody thirsty on this station?"
product_ads = "Drink up!;Booze is good for you!;Alcohol is humanity's best friend.;Quite delighted to serve you!;Care for a nice, cold beer?;Nothing cures you like booze!;Have a sip!;Have a drink!;Have a beer!;Beer is good for you!;Only the finest alcohol!;Best quality booze since 2053!;Award-winning wine!;Maximum alcohol!;Man loves beer.;A toast for progress!"
@@ -652,7 +654,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
/obj/machinery/vending/assist
products = list( /obj/item/device/assembly/prox_sensor = 5,/obj/item/device/assembly/igniter = 3,/obj/item/device/assembly/signaler = 4,
/obj/item/weapon/wirecutters = 1, /obj/item/weapon/cartridge/signal = 4)
- contraband = list(/obj/item/device/flashlight = 5,/obj/item/device/assembly/timer = 2, /obj/item/device/assembly/voice = 2)
+ contraband = list(/obj/item/device/flashlight = 5,/obj/item/device/assembly/timer = 2, /obj/item/device/assembly/voice = 2, /obj/item/device/assembly/health = 2)
product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!"
/obj/machinery/vending/coffee
@@ -662,7 +664,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
icon_state = "coffee"
icon_vend = "coffee-vend"
vend_delay = 34
- products = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 25,/obj/item/weapon/reagent_containers/food/drinks/tea = 25,/obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 25)
+ products = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 25,/obj/item/weapon/reagent_containers/food/drinks/mug/tea = 25,/obj/item/weapon/reagent_containers/food/drinks/mug/coco = 25)
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/ice = 12)
refill_canister = /obj/item/weapon/vending_refill/coffee
@@ -771,6 +773,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
products = list(/obj/item/clothing/under/rank/scientist = 6,/obj/item/clothing/suit/bio_suit = 6,/obj/item/clothing/head/bio_hood = 6,
/obj/item/device/transfer_valve = 6,/obj/item/device/assembly/timer = 6,/obj/item/device/assembly/signaler = 6,
/obj/item/device/assembly/prox_sensor = 6,/obj/item/device/assembly/igniter = 6)
+ contraband = list(/obj/item/device/assembly/health = 3)
/obj/machinery/vending/wallmed
name = "\improper NanoMed"
@@ -795,7 +798,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
icon_state = "sec"
icon_deny = "sec-deny"
req_access_txt = "1"
- products = list(/obj/item/weapon/restraints/handcuffs = 8,/obj/item/weapon/restraints/handcuffs/cable/zipties = 10,/obj/item/weapon/grenade/flashbang = 4,/obj/item/device/flash/handheld = 5,
+ products = list(/obj/item/weapon/restraints/handcuffs = 8,/obj/item/weapon/restraints/handcuffs/cable/zipties = 10,/obj/item/weapon/grenade/flashbang = 4,/obj/item/device/assembly/flash/handheld = 5,
/obj/item/weapon/reagent_containers/food/snacks/donut = 12,/obj/item/weapon/storage/box/evidence = 6,/obj/item/device/flashlight/seclite = 4)
contraband = list(/obj/item/clothing/glasses/sunglasses = 2,/obj/item/weapon/storage/fancy/donut_box = 2)
premium = list(/obj/item/weapon/coin/antagtoken = 1)
@@ -910,7 +913,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
icon_state = "engivend"
icon_deny = "engivend-deny"
req_access_txt = "11" //Engineering Equipment access
- products = list(/obj/item/clothing/glasses/meson/engine = 2,/obj/item/device/multitool = 4,/obj/item/weapon/airlock_electronics = 10,/obj/item/weapon/module/power_control = 10,/obj/item/weapon/airalarm_electronics = 10,/obj/item/weapon/stock_parts/cell/high = 10, /obj/item/weapon/rcd/loaded = 3,)
+ products = list(/obj/item/clothing/glasses/meson/engine = 2,/obj/item/device/multitool = 4,/obj/item/weapon/electronics/airlock = 10,/obj/item/weapon/electronics/apc = 10,/obj/item/weapon/electronics/airalarm = 10,/obj/item/weapon/stock_parts/cell/high = 10, /obj/item/weapon/rcd/loaded = 3,)
contraband = list(/obj/item/weapon/stock_parts/cell/potato = 3)
premium = list(/obj/item/weapon/storage/belt/utility = 3)
@@ -935,7 +938,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
icon_state = "robotics"
icon_deny = "robotics-deny"
req_access_txt = "29"
- products = list(/obj/item/clothing/suit/toggle/labcoat = 4,/obj/item/clothing/under/rank/roboticist = 4,/obj/item/stack/cable_coil = 4,/obj/item/device/flash/handheld = 4,
+ products = list(/obj/item/clothing/suit/toggle/labcoat = 4,/obj/item/clothing/under/rank/roboticist = 4,/obj/item/stack/cable_coil = 4,/obj/item/device/assembly/flash/handheld = 4,
/obj/item/weapon/stock_parts/cell/high = 12, /obj/item/device/assembly/prox_sensor = 3,/obj/item/device/assembly/signaler = 3,/obj/item/device/healthanalyzer = 3,
/obj/item/weapon/scalpel = 2,/obj/item/weapon/circular_saw = 2,/obj/item/weapon/tank/internals/anesthetic = 2,/obj/item/clothing/mask/breath/medical = 5,
/obj/item/weapon/screwdriver = 5,/obj/item/weapon/crowbar = 5)
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index 93d94804165..f73c58acdd7 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -4,7 +4,7 @@
icon = 'icons/obj/machines/washing_machine.dmi'
icon_state = "wm_10"
density = 1
- anchored = 1.0
+ anchored = 1
var/state = 1
//1 = empty, open door
//2 = empty, closed door
diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm
index 55b9d068630..c6a3a347726 100644
--- a/code/game/mecha/combat/honker.dm
+++ b/code/game/mecha/combat/honker.dm
@@ -45,7 +45,7 @@
HONK pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa HONK temperature: [return_temperature()]°K|[return_temperature() - T0C]°C Lights: [lights?"on":"off"]
- [src.dna?"DNA-locked: [src.dna] \[Reset\] ":null]
+ [dna_lock?"DNA-locked: [dna_lock] \[Reset\] ":null]
"}
return output
diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm
index e79e6666a7b..a179fe46635 100644
--- a/code/game/mecha/combat/marauder.dm
+++ b/code/game/mecha/combat/marauder.dm
@@ -30,7 +30,7 @@
/obj/mecha/combat/marauder/Destroy()
qdel(smoke_system)
smoke_system = null
- ..()
+ return ..()
/obj/mecha/combat/marauder/relaymove(mob/user,direction)
if(zoom)
diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm
index 9f6a67799ae..ac8c7e541d5 100644
--- a/code/game/mecha/equipment/tools/other_tools.dm
+++ b/code/game/mecha/equipment/tools/other_tools.dm
@@ -286,7 +286,7 @@
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/detach()
SSobj.processing.Remove(src)
@@ -378,7 +378,7 @@
/obj/item/mecha_parts/mecha_equipment/generator/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/item/mecha_parts/mecha_equipment/generator/proc/generator_init()
fuel = new /obj/item/stack/sheet/mineral/plasma(src)
diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm
index 6c7b8006e47..052b5a08353 100644
--- a/code/game/mecha/equipment/tools/work_tools.dm
+++ b/code/game/mecha/equipment/tools/work_tools.dm
@@ -195,16 +195,22 @@
energy_drain = 250
range = MELEE|RANGED
var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock.
- var/disabled = 0 //malf
+
+/obj/item/mecha_parts/mecha_equipment/rcd/New()
+ rcd_list += src
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/rcd/Destroy()
+ rcd_list -= src
+ ..()
/obj/item/mecha_parts/mecha_equipment/rcd/action(atom/target)
- if(istype(target,/area/shuttle)||istype(target, /turf/space/transit))//>implying these are ever made -Sieve
- disabled = 1
- else
- disabled = 0
+ if(istype(target, /turf/space/transit))//>implying these are ever made -Sieve
+ return
+
if(!istype(target, /turf) && !istype(target, /obj/machinery/door/airlock))
target = get_turf(target)
- if(!action_checks(target) || disabled || get_dist(chassis, target)>3)
+ if(!action_checks(target) || get_dist(chassis, target)>3)
return
playsound(chassis, 'sound/machines/click.ogg', 50, 1)
@@ -242,7 +248,6 @@
var/turf/simulated/floor/F = target
occupant_message("Building Wall...")
if(do_after_cooldown(F))
- if(disabled) return
F.ChangeTurf(/turf/simulated/wall)
playsound(F, 'sound/items/Deconstruct.ogg', 50, 1)
chassis.spark_system.start()
@@ -260,8 +265,6 @@
/obj/item/mecha_parts/mecha_equipment/rcd/do_after_cooldown(var/atom/target)
. = ..()
- if(disabled)
- return 0
/obj/item/mecha_parts/mecha_equipment/rcd/Topic(href,href_list)
..()
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 0e178a4218e..69a0cdfb492 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -34,7 +34,7 @@
var/last_message = 0
var/add_req_access = 1
var/maint_access = 0
- var/dna //dna-locking the mech
+ var/dna_lock//dna-locking the mech
var/list/proc_res = list() //stores proc owners, like proc_res["functionname"] = owner reference
var/datum/effect/effect/system/spark_spread/spark_system = new
var/lights = 0
@@ -137,7 +137,7 @@
loc.assume_air(cabin_air)
air_update_turf()
else
- del(cabin_air)
+ qdel(cabin_air)
cabin_air = null
qdel(spark_system)
spark_system = null
@@ -240,7 +240,7 @@
loc.assume_air(leaked_gas)
air_update_turf()
else
- del(leaked_gas)
+ qdel(leaked_gas)
if(internal_damage & MECHA_INT_SHORT_CIRCUIT)
if(get_charge())
@@ -276,7 +276,7 @@
if(t_air)
t_air.merge(removed)
else //just delete the cabin gas, we're in space or some shit
- del(removed)
+ qdel(removed)
if(occupant)
if(cell)
@@ -557,7 +557,7 @@
else if(AI.stat || !AI.client)
user << "[AI.name] is currently unresponsive, and cannot be uploaded."
return
- else if(occupant || dna) //Normal AIs cannot steal mechs!
+ else if(occupant || dna_lock) //Normal AIs cannot steal mechs!
user << "Access denied. [name] is [occupant ? "currently occupied" : "secured with a DNA lock"]."
return
AI.control_disabled = 0
@@ -623,7 +623,7 @@
//Perform the connection
connected_port = new_port
connected_port.connected_device = src
- var/datum/pipeline/connected_port_parent = connected_port.parents["p1"]
+ var/datum/pipeline/connected_port_parent = connected_port.PARENT1
connected_port_parent.reconcile_air()
log_message("Connected to gas port.")
@@ -653,10 +653,10 @@
log_append_to_last("Permission denied.")
return
var/passed
- if(dna)
- if(check_dna_integrity(user))
+ if(dna_lock)
+ if(user.has_dna())
var/mob/living/carbon/C = user
- if(C.dna.unique_enzymes==src.dna)
+ if(C.dna.unique_enzymes==dna_lock)
passed = 1
else if(operation_allowed(user))
passed = 1
@@ -664,6 +664,10 @@
user << "Access denied."
log_append_to_last("Permission denied.")
return
+ if(user.buckled)
+ user << "You are currently buckled and cannot move."
+ log_append_to_last("Permission denied.")
+ return
for(var/mob/living/simple_animal/slime/S in range(1,user))
if(S.Victim == user)
user << "You're too busy getting your life sucked out of you!"
@@ -676,6 +680,8 @@
user << "You cannot get in the [src.name], it has been destroyed!"
else if(occupant)
user << "[src.occupant] was faster! Try better next time, loser."
+ else if(user.buckled)
+ user << "You have been buckled and cannot move."
else
moved_inside(user)
else
@@ -711,8 +717,8 @@
else if(occupant)
user << "Occupant detected!"
return 0
- else if(dna && dna!=mmi_as_oc.brainmob.dna.unique_enzymes)
- user << "Stop it!"
+ else if(dna_lock && (!mmi_as_oc.brainmob.dna || dna_lock!=mmi_as_oc.brainmob.dna.unique_enzymes))
+ user << "Access denied. [name] is secured with a DNA lock."
return 0
visible_message("[user] starts to insert an MMI into [src.name].")
diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm
index 8df632882a3..60c31405645 100644
--- a/code/game/mecha/mecha_construction_paths.dm
+++ b/code/game/mecha/mecha_construction_paths.dm
@@ -300,7 +300,7 @@
const_holder.icon = 'icons/mecha/mech_construction.dmi'
const_holder.icon_state = "gygax0"
const_holder.density = 1
- del(src)
+ qdel(src)
return
@@ -579,7 +579,7 @@
const_holder.icon = 'icons/mecha/mech_construction.dmi'
const_holder.icon_state = "fireripley0"
const_holder.density = 1
- del(src)
+ qdel(src)
return
@@ -801,7 +801,7 @@
var/obj/item/mecha_parts/chassis/const_holder = holder
const_holder.construct = new /datum/construction/mecha/honker(const_holder)
const_holder.density = 1
- del(src)
+ qdel(src)
return
diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm
index b379692d619..44d23eec3bb 100644
--- a/code/game/mecha/mecha_defense.dm
+++ b/code/game/mecha/mecha_defense.dm
@@ -146,15 +146,15 @@
severity++
log_append_to_last("Armor saved, changing severity to [severity].")
switch(severity)
- if(1.0)
+ if(1)
qdel(src)
- if(2.0)
+ if(2)
if (prob(30))
qdel(src)
else
take_damage(initial(src.health)/2)
check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
- if(3.0)
+ if(3)
if (prob(5))
qdel(src)
else
diff --git a/code/game/mecha/mecha_parts.dm b/code/game/mecha/mecha_parts.dm
index 3847a564287..3a61c4f108b 100644
--- a/code/game/mecha/mecha_parts.dm
+++ b/code/game/mecha/mecha_parts.dm
@@ -324,8 +324,8 @@
item_state = "electronic"
board_type = "other"
flags = CONDUCT
- force = 5.0
- w_class = 2.0
+ force = 5
+ w_class = 2
throwforce = 0
throw_speed = 3
throw_range = 7
diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm
index 25ba30fde4a..8dc4dfde8c6 100644
--- a/code/game/mecha/mecha_topic.dm
+++ b/code/game/mecha/mecha_topic.dm
@@ -83,7 +83,7 @@
Airtank temperature: [tank_temperature]°K|[tank_temperature - T0C]°C Cabin pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa Cabin temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
- [src.dna?"DNA-locked: [src.dna] \[Reset\] ":null]
+ [dna_lock?"DNA-locked: [dna_lock] \[Reset\] ":null]
"}
return output
@@ -300,11 +300,11 @@
if(occupant && !iscarbon(occupant))
occupant << " You do not have any DNA!"
return
- dna = src.occupant.dna.unique_enzymes
+ dna_lock = occupant.dna.unique_enzymes
occupant_message("You feel a prick as the needle takes your DNA sample.")
if(href_list["reset_dna"])
- dna = null
+ dna_lock = null
if(href_list["repair_int_control_lost"])
occupant_message("Recalibrating coordination system...")
diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm
index 0c781f27f9b..2bdea860950 100644
--- a/code/game/objects/buckling.dm
+++ b/code/game/objects/buckling.dm
@@ -24,11 +24,6 @@
. = ..()
unbuckle_mob()
-/obj/Del()
- . = ..()
- unbuckle_mob()
-
-
//procs that handle the actual buckling and unbuckling
/obj/proc/buckle_mob(mob/living/M)
if(!can_buckle || !istype(M) || (M.loc != loc) || M.buckled || (buckle_requires_restraints && !M.restrained()))
@@ -72,7 +67,7 @@
//Wrapper procs that handle sanity and user feedback
/obj/proc/user_buckle_mob(mob/living/M, mob/user)
- if(!user.Adjacent(M) || user.restrained() || user.lying || user.stat)
+ if(!in_range(user, src) || user.stat || user.restrained())
return
add_fingerprint(user)
@@ -81,28 +76,27 @@
if(buckle_mob(M))
if(M == user)
M.visible_message(\
- "[M.name] buckles themselves to [src].",\
+ "[M] buckles themself to [src].",\
"You buckle yourself to [src].",\
"You hear metal clanking.")
else
M.visible_message(\
- "[M.name] is buckled to [src] by [user.name]!",\
- "You are buckled to [src] by [user.name]!",\
- "You heat metal clanking.")
+ "[user] buckles [M] to [src]!",\
+ "[user] buckles you to [src]!",\
+ "You hear metal clanking.")
/obj/proc/user_unbuckle_mob(mob/user)
var/mob/living/M = unbuckle_mob()
-
if(M)
if(M != user)
M.visible_message(\
- "[M.name] was unbuckled by [user.name].",\
- "You were unbuckled from [src] by [user.name].",\
+ "[user] unbuckles [M] from [src].",\
+ "[user] unbuckles you from [src].",\
"You hear metal clanking.")
else
M.visible_message(\
- "[M.name] unbuckled themselves!",\
- "You unbuckled yourself from [src].",\
+ "[M] unbuckles themselves from [src].",\
+ "You unbuckle yourself from [src].",\
"You hear metal clanking.")
add_fingerprint(user)
return M
diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm
index aaca5674ed5..bba12958987 100644
--- a/code/game/objects/effects/aliens.dm
+++ b/code/game/objects/effects/aliens.dm
@@ -29,7 +29,7 @@
canSmoothWith = list(/obj/structure/alien/resin)
var/health = 200
var/resintype = null
- smooth = 1
+ smooth = SMOOTH_TRUE
/obj/structure/alien/resin/New(location)
@@ -84,11 +84,11 @@
/obj/structure/alien/resin/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
health -= 150
- if(2.0)
+ if(2)
health -= 100
- if(3.0)
+ if(3)
health -= 50
healthcheck()
@@ -186,7 +186,7 @@
for (var/obj/structure/alien/weeds/W in range(1,T))
W.updateWeedOverlays()
linked_node = null
- ..()
+ return ..()
/obj/structure/alien/weeds/proc/Life()
set background = BACKGROUND_ENABLED
@@ -196,21 +196,15 @@
qdel(src)
return
- direction_loop:
- for(var/dirn in cardinal)
- var/turf/T = get_step(src, dirn)
+ if(!linked_node || get_dist(linked_node, src) > linked_node.node_range)
+ return
- if (!istype(T) || T.density || locate(/obj/structure/alien/weeds) in T || istype(T, /turf/space))
- continue
+ for(var/turf/T in U.GetAtmosAdjacentTurfs())
- if(!linked_node || get_dist(linked_node, src) > linked_node.node_range)
- return
+ if (locate(/obj/structure/alien/weeds) in T || istype(T, /turf/space))
+ continue
- for(var/obj/O in T)
- if(O.density)
- continue direction_loop
-
- new /obj/structure/alien/weeds(T, linked_node)
+ new /obj/structure/alien/weeds(T, linked_node)
/obj/structure/alien/weeds/ex_act(severity, target)
@@ -224,7 +218,7 @@
else
visible_message("[user] has attacked [src] with [I]!")
- var/damage = I.force / 4.0
+ var/damage = I.force / 4
if(istype(I, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = I
if(WT.remove_fuel(0, user))
@@ -315,6 +309,7 @@
anchored = 1
var/health = 100
var/status = GROWING //can be GROWING, GROWN or BURST; all mutually exclusive
+ layer = MOB_LAYER
/obj/structure/alien/egg/New()
@@ -419,7 +414,7 @@
return
var/mob/living/carbon/C = AM
- if(C.stat == CONSCIOUS && C.status_flags & XENO_HOST)
+ if(C.stat == CONSCIOUS && C.getorgan(/obj/item/organ/internal/body_egg/alien_embryo))
return
Burst(0)
@@ -474,6 +469,11 @@
if(ticks >= target_strength)
target.visible_message("[target] collapses under its own weight into a puddle of goop and undigested debris!")
+ if(istype(target, /obj/structure/closet))
+ var/obj/structure/closet/T = target
+ T.dump_contents()
+ qdel(target)
+
if(istype(target, /turf/simulated/wall))
var/turf/simulated/wall/W = target
W.dismantle_wall(1)
diff --git a/code/game/objects/effects/bump_teleporter.dm b/code/game/objects/effects/bump_teleporter.dm
index a0005e515d5..bb9a34010c9 100644
--- a/code/game/objects/effects/bump_teleporter.dm
+++ b/code/game/objects/effects/bump_teleporter.dm
@@ -17,7 +17,7 @@ var/list/obj/effect/bump_teleporter/BUMP_TELEPORTERS = list()
/obj/effect/bump_teleporter/Destroy()
BUMP_TELEPORTERS -= src
- ..()
+ return ..()
/obj/effect/bump_teleporter/Bumped(atom/user)
if(!ismob(user))
diff --git a/code/game/objects/effects/decals/Cleanable/aliens.dm b/code/game/objects/effects/decals/Cleanable/aliens.dm
index 1d3284d671d..1326a890d7d 100644
--- a/code/game/objects/effects/decals/Cleanable/aliens.dm
+++ b/code/game/objects/effects/decals/Cleanable/aliens.dm
@@ -12,12 +12,14 @@
random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
var/list/viruses = list()
blood_DNA = list("UNKNOWN DNA" = "X*")
+ bloodiness = MAX_SHOE_BLOODINESS
+ blood_state = BLOOD_STATE_XENO
/obj/effect/decal/cleanable/xenoblood/Destroy()
for(var/datum/disease/D in viruses)
D.cure(0)
viruses = null
- ..()
+ return ..()
/obj/effect/decal/cleanable/xenoblood/xgibs/proc/streak(list/directions)
spawn (0)
@@ -65,4 +67,4 @@
/obj/effect/decal/cleanable/blood/xtracks
icon_state = "xtracks"
random_icon_states = null
- blood_DNA = list("UNKNOWN DNA" = "X*")
\ No newline at end of file
+ blood_DNA = list("UNKNOWN DNA" = "X*")
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index 376248156cb..57e62aa0881 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -10,12 +10,14 @@
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
var/list/viruses = list()
blood_DNA = list()
+ blood_state = BLOOD_STATE_HUMAN
+ bloodiness = MAX_SHOE_BLOODINESS
/obj/effect/decal/cleanable/blood/Destroy()
for(var/datum/disease/D in viruses)
D.cure(0)
viruses = null
- ..()
+ return ..()
/obj/effect/decal/cleanable/blood/New()
..()
@@ -48,6 +50,11 @@
var/list/existing_dirs = list()
blood_DNA = list()
+
+/obj/effect/decal/cleanable/trail_holder/can_bloodcrawl_in()
+ return 1
+
+
/obj/effect/decal/cleanable/blood/gibs
name = "gibs"
desc = "They look bloody and gruesome."
@@ -99,9 +106,90 @@
icon = 'icons/effects/drip.dmi'
icon_state = "1"
random_icon_states = list("1","2","3","4","5")
+ bloodiness = 0
var/list/drips = list()
/obj/effect/decal/cleanable/blood/drip/New()
..()
spawn(1)
- drips |= icon_state
\ No newline at end of file
+ drips |= icon_state
+
+/obj/effect/decal/cleanable/blood/drip/can_bloodcrawl_in()
+ return 1
+
+
+//BLOODY FOOTPRINTS
+/obj/effect/decal/cleanable/blood/footprints
+ name = "footprints"
+ icon = 'icons/effects/footprints.dmi'
+ icon_state = "nothingwhatsoever"
+ desc = "where might they lead?"
+ gender = PLURAL
+ random_icon_states = null
+ var/entered_dirs = 0
+ var/exited_dirs = 0
+ blood_state = BLOOD_STATE_HUMAN //the icon state to load images from
+ var/list/shoe_types = list()
+
+/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O)
+ if(ishuman(O))
+ var/mob/living/carbon/human/H = O
+ var/obj/item/clothing/shoes/S = H.shoes
+ if(S && S.bloody_shoes[blood_state])
+ S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
+ entered_dirs|= H.dir
+ shoe_types |= H.shoes.type
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/footprints/Uncrossed(atom/movable/O)
+ if(ishuman(O))
+ var/mob/living/carbon/human/H = O
+ var/obj/item/clothing/shoes/S = H.shoes
+ if(S && S.bloody_shoes[blood_state])
+ S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
+ exited_dirs|= H.dir
+ shoe_types |= H.shoes.type
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/footprints/update_icon()
+ overlays.Cut()
+
+ for(var/Ddir in cardinal)
+ if(entered_dirs & Ddir)
+ var/image/I
+ if(bloody_footprints_cache["entered-[blood_state]-[Ddir]"])
+ I = bloody_footprints_cache["entered-[blood_state]-[Ddir]"]
+ else
+ I = image(icon,"[blood_state]1",dir = Ddir)
+ bloody_footprints_cache["entered-[blood_state]-[Ddir]"] = I
+ if(I)
+ overlays += I
+ if(exited_dirs & Ddir)
+ var/image/I
+ if(bloody_footprints_cache["exited-[blood_state]-[Ddir]"])
+ I = bloody_footprints_cache["exited-[blood_state]-[Ddir]"]
+ else
+ I = image(icon,"[blood_state]2",dir = Ddir)
+ bloody_footprints_cache["exited-[blood_state]-[Ddir]"] = I
+ if(I)
+ overlays += I
+
+ alpha = BLOODY_FOOTPRINT_BASE_ALPHA+bloodiness
+
+
+/obj/effect/decal/cleanable/blood/footprints/examine(mob/user)
+ . = ..()
+ if(shoe_types.len)
+ . += "You recognise the footprints as belonging to:\n"
+ for(var/shoe in shoe_types)
+ var/obj/item/clothing/shoes/S = shoe
+ . += "some [initial(S.name)] \icon[S]\n"
+
+ user << .
+
+
+/obj/effect/decal/cleanable/blood/footprints/can_bloodcrawl_in()
+ if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY))
+ return 1
+ return 0
+
diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm
index 7dc1f58688a..e819145d7c5 100644
--- a/code/game/objects/effects/decals/Cleanable/misc.dm
+++ b/code/game/objects/effects/decals/Cleanable/misc.dm
@@ -114,7 +114,7 @@
for(var/datum/disease/D in viruses)
D.cure(0)
viruses = null
- ..()
+ return ..()
/obj/effect/decal/cleanable/tomato_smudge
name = "tomato smudge"
diff --git a/code/game/objects/effects/decals/Cleanable/robots.dm b/code/game/objects/effects/decals/Cleanable/robots.dm
index da5d6e7b40b..002b5e1a4fa 100644
--- a/code/game/objects/effects/decals/Cleanable/robots.dm
+++ b/code/game/objects/effects/decals/Cleanable/robots.dm
@@ -10,6 +10,8 @@
icon = 'icons/mob/robots.dmi'
icon_state = "gib1"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7")
+ blood_state = BLOOD_STATE_OIL
+ bloodiness = MAX_SHOE_BLOODINESS
/obj/effect/decal/cleanable/robot_debris/proc/streak(list/directions)
spawn (0)
@@ -18,7 +20,6 @@
sleep(3)
if (i > 0)
if (prob(40))
- /*var/obj/effect/decal/cleanable/oil/o =*/
new /obj/effect/decal/cleanable/oil/streak(src.loc)
else if (prob(10))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
@@ -34,10 +35,10 @@
random_icon_states = list("gibarm", "gibleg")
/obj/effect/decal/cleanable/robot_debris/up
- random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibup1","gibup1") //2:7 is close enough to 1:4
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibup1","gibup1")
/obj/effect/decal/cleanable/robot_debris/down
- random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibdown1","gibdown1") //2:7 is close enough to 1:4
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibdown1","gibdown1")
/obj/effect/decal/cleanable/oil
name = "motor oil"
@@ -50,6 +51,8 @@
icon_state = "floor1"
var/viruses = list()
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
+ blood_state = BLOOD_STATE_OIL
+ bloodiness = MAX_SHOE_BLOODINESS
/obj/effect/decal/cleanable/oil/New()
..()
@@ -59,7 +62,7 @@
for(var/datum/disease/D in viruses)
D.cure(0)
viruses = null
- ..()
+ return ..()
/obj/effect/decal/cleanable/oil/streak
- random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
\ No newline at end of file
+ random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index 175e24f9caf..1658f052e07 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -1,5 +1,7 @@
/obj/effect/decal/cleanable
var/list/random_icon_states = list()
+ var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA
+ var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints
/obj/effect/decal/cleanable/New()
if (random_icon_states && length(src.random_icon_states) > 0)
@@ -21,10 +23,10 @@
if(!reagents.total_volume) //scooped up all of it
qdel(src)
return
- if(is_hot(W)) //todo: make heating a reagent holder proc
+ if(W.is_hot()) //todo: make heating a reagent holder proc
if(istype(W, /obj/item/clothing/mask/cigarette)) return
else
- var/hotness = is_hot(W)
+ var/hotness = W.is_hot()
var/added_heat = (hotness / 100)
src.reagents.chem_temp = min(src.reagents.chem_temp + added_heat, hotness)
src.reagents.handle_reactions()
@@ -40,4 +42,30 @@
if(reagents)
reagents.chem_temp += 30
reagents.handle_reactions()
- ..()
\ No newline at end of file
+ ..()
+
+
+//Add "bloodiness" of this blood's type, to the human's shoes
+//This is on /cleanable because fuck this ancient mess
+/obj/effect/decal/cleanable/Crossed(atom/movable/O)
+ if(ishuman(O))
+ var/mob/living/carbon/human/H = O
+ if(H.shoes && blood_state && bloodiness)
+ var/obj/item/clothing/shoes/S = H.shoes
+ var/add_blood = 0
+ if(bloodiness >= BLOOD_GAIN_PER_STEP)
+ add_blood = BLOOD_GAIN_PER_STEP
+ else
+ add_blood = bloodiness
+ bloodiness -= add_blood
+ S.bloody_shoes[blood_state] = min(MAX_SHOE_BLOODINESS,S.bloody_shoes[blood_state]+add_blood)
+ S.blood_state = blood_state
+ update_icon()
+ H.update_inv_shoes()
+
+
+
+/obj/effect/decal/cleanable/proc/can_bloodcrawl_in()
+ return bloodiness
+
+
diff --git a/code/game/objects/effects/decals/contraband.dm b/code/game/objects/effects/decals/contraband.dm
index e24d2ec12d2..7abaad96649 100644
--- a/code/game/objects/effects/decals/contraband.dm
+++ b/code/game/objects/effects/decals/contraband.dm
@@ -1,381 +1,274 @@
-
-//########################## CONTRABAND ;3333333333333333333 -Agouri ###################################################
-
-#define NUM_OF_POSTER_DESIGNS 33 //subtype 0-contraband posters
-
-#define NUM_OF_POSTER_DESIGNS_LEGIT 33 //subtype 1-corporate approved posters
-
-/obj/item/weapon/contraband
- name = "contraband item"
- desc = "You probably shouldn't be holding this."
- icon = 'icons/obj/contraband.dmi'
- force = 0
-
-
-/obj/item/weapon/contraband/poster
- name = "rolled-up poster"
- desc = "The poster comes with its own automatic adhesive mechanism, for easy pinning to any vertical surface. Its vulgar themes have marked it as contraband aboard Nanotrasen space facilities."
- icon_state = "rolled_poster"
- var/serial_number = 0
- var/obj/structure/sign/poster/resulting_poster = null //The poster that will be created is initialised and stored through contraband/poster's constructor
- var/subtype = 0
-
-
-/obj/item/weapon/contraband/poster/New(turf/loc, given_serial = 0)
- if(given_serial == 0)
- if(subtype == 0)
- serial_number = rand(1, NUM_OF_POSTER_DESIGNS)
- resulting_poster = new(serial_number,subtype)
- if(subtype == 1)
- serial_number = rand(1, NUM_OF_POSTER_DESIGNS_LEGIT)
- resulting_poster = new(serial_number,subtype)
- else
- serial_number = given_serial
- //We don't give it a resulting_poster because if we called it with a given_serial it means that we're rerolling an already used poster.
- name += " - No. [serial_number]"
- ..(loc)
-
-
-/*/obj/item/weapon/contraband/poster/attack(mob/M as mob, mob/user as mob)
- src.add_fingerprint(user)
- if(resulting_poster)
- resulting_poster.add_fingerprint(user)
- ..()*/
-
-/*/obj/item/weapon/contraband/poster/attack(atom/A, mob/user as mob) //This shit is handled through the wall's attackby()
- if(istype(A, /turf/simulated/wall))
- if(resulting_poster == null)
- return
- else
- var/turf/simulated/wall/W = A
- var/check = 0
- var/stuff_on_wall = 0
- for(var/obj/O in W.contents) //Let's see if it already has a poster on it or too much stuff
- if(istype(O,/obj/structure/sign/poster))
- check = 1
- break
- stuff_on_wall++
- if(stuff_on_wall == 3)
- check = 1
- break
-
- if(check)
- user << "The wall is far too cluttered to place a poster!"
- return
-
- resulting_poster.loc = W //Looks like it's uncluttered enough. Place the poster
- W.contents += resulting_poster
-
- qdel(src)*/
-
-
-
-//############################## THE ACTUAL DECALS ###########################
-
-/obj/structure/sign/poster
- name = "poster"
- desc = "A large piece of space-resistant printed paper."
- icon = 'icons/obj/contraband.dmi'
- anchored = 1
- var/serial_number //Will hold the value of src.loc if nobody initialises it
- var/ruined = 0
- var/subtype = 0
-
-/obj/structure/sign/poster/New(serial,subtype)
- serial_number = serial
-
- if(serial_number == loc)
- if(subtype == 0)
- serial_number = rand(1, NUM_OF_POSTER_DESIGNS) //This is for the mappers that want individual posters without having to use rolled posters.
- if(subtype == 1)
- serial_number = rand(1, NUM_OF_POSTER_DESIGNS_LEGIT)
- if(subtype == 0)
- icon_state = "poster[serial_number]"
- switch(serial_number)
- if(1)
- name += " - Free Tonto"
- desc += " A framed shred of a much larger flag, colors bled together and faded from age."
- if(2)
- name += " - Atmosia Declaration of Independence"
- desc += " A relic of a failed rebellion."
- if(3)
- name += " - Fun Police"
- desc += " A poster condemning the station's security forces."
- if(4)
- name += " - Lusty Xeno"
- desc += " A heretical poster depicting the titular star of an equally heretical book."
- if(5)
- name += " - Syndicate Recruitment Poster"
- desc += " See the galaxy! Shatter corrupt megacorporations! Join today!"
- if(6)
- name += " - Clown"
- desc += " Honk."
- if(7)
- name += " - Smoke"
- desc += " A poster depicting a carton of cigarettes."
- if(8)
- name += " - Grey Tide"
- desc += " A rebellious poster symbolizing assistant solidarity."
- if(9)
- name += " - Missing Gloves"
- desc += " This poster is about the uproar that followed Nanotrasen's financial cuts towards insulated-glove purchases."
- if(10)
- name += " - Hacking Guide"
- desc += " This poster details the internal workings of the common Nanotrasen airlock."
- if(11)
- name += " - RIP Badger"
- desc += " This poster commemorates the day hundreds of badgers worldwide were sacrificed for the greater good."
- if(12)
- name += " - Ambrosia Vulgaris"
- desc += " This poster is lookin' pretty trippy man."
- if(13)
- name += " - Donut Corp."
- desc += " This poster is an advertisement for Donut Corp."
- if(14)
- name += " - EAT"
- desc += " This poster is advising that you eat."
- if(15)
- name += " - Tools"
- desc += " This poster is an advertisement for tools."
- if(16)
- name += " - Power"
- desc += " A poster all about power."
- if(17)
- name += " - Power to the People"
- desc += " Screw those EDF guys!"
- if(18)
- name += " - Communist state"
- desc += " All hail the Communist party!"
- if(19)
- name += " - Lamarr"
- desc += " This poster depicts Lamarr. Probably made by the Research Director."
- if(20)
- name += " - Borg Fancy"
- desc += " Being fancy can be for any borg, just need a suit."
- if(21)
- name += " - Borg Fancy v2"
- desc += " Borg Fancy, Now only taking the most fancy."
- if(22)
- name += " - Kosmicheskaya Stantsiya 13 Does Not Exist"
- desc += " A poster denying the existence of the derelict station near Space Station 13."
- if(23)
- name += " - Rebels Unite!"
- desc += " A poster telling the viewer to rebel against Nanotrasen."
- if(24)
- name += " - C-20r Advertisment"
- desc += " A poster advertising the Scarborough Arms C-20r."
- if(25)
- name += " - Have A Puff"
- desc += " Who cares about lung cancer when you're high as a kite?"
- if(26)
- name += " - Revolver Advertisment"
- desc += " Because seven shots are all you need."
- if(27)
- name += " - D-Day Promotional Poster"
- desc += " A promotional poster for some rapper."
- if(28)
- name += " - Syndicate Pistol Advertisment"
- desc += " A poster advertising syndicate pistols as being 'Classy as fuck'."
- if(29)
- name += " - E-sword Rainbow"
- desc += " All the colors of bloody murder rainbow."
- if(30)
- name += " - Red Rum"
- desc += " Looking at this poster makes you want to kill."
- if(31)
- name += " - CC 64K Advertisment"
- desc += " The latest portable computer from Comrade Computing, with a whole 64kB of ram!"
- if(32)
- name += " - Punch Shit"
- desc += " Fight things for no reason, like a man!"
- if(33)
- name += " - The Griffin"
- desc += " The Griffin commands you to be the worst you can be. Will you?"
- else
- name += " - Error (subtype 0 serial_number)"
- desc += " This is a bug, please report the circumstances under which you encountered this poster at https://github.com/tgstation/-tg-station/issues."
-
- if(subtype == 1)
- icon_state = "poster[serial_number]_legit"
- switch(serial_number)
- if(1)
- name += " - Here for Your Saftey"
- desc += " A poster glorifying the station's security force."
- if(2)
- name += " - Nanotrasen Logo"
- desc += " A poster depicting the logo of Nanotrasen."
- if(3)
- name += " - Cleanliness"
- desc += " A poster warning of the dangers of poor hygiene."
- if(4)
- name += " - Help Others"
- desc += " A poster encouraging you to help fellow crewmembers."
- if(5)
- name += " - Build"
- desc += " A poster glorifying the engineering team."
- if(6)
- name += " - Bless This Spess"
- desc += " A poster blessing this area."
- if(7)
- name += " - Science"
- desc += " A poster depicting an atom."
- if(8)
- name += " - Ian"
- desc += " Arf Arf."
- if(9)
- name += " - Obey"
- desc += " A poster instructing the viewer to obey authority."
- if(10)
- name += " - Walk"
- desc += " A poster instructing the viewer to walk instead of running."
- if(11)
- name += " - State Laws"
- desc += " A poster instructing cyborgs to state their laws."
- if(12)
- name += " - Love Ian"
- desc += " Ian is love, Ian is life."
- if(13)
- name += " - Space Cops"
- desc += " A poster advertising the television show Space Cops."
- if(14)
- name += " - Ue No"
- desc += " This thing is all in Japanese."
- if(15)
- name += " - Get Your LEGS"
- desc += " LEGS: Leadership, Experiance, Genius, S(Opportunity)."
- if(16)
- name += " - Do Not Question"
- desc += " A poster instructing the viewer not to ask about things they aren't meant to know."
- if(17)
- name += " - Work for a Future"
- desc += " A poster encouraging you to work for your future, what it is, no one is really sure."
- if(18)
- name += " - Soft Cap Pop Art"
- desc += " A poster reprint of some cheap pop art."
- if(19)
- name += " - Saftey: Internals"
- desc += " A poster instructing the viewer to wear internals in environments where there is no oxygen or the air has been rendered toxic."
- if(20)
- name += " - Saftey: Eye Protection"
- desc += " A poster instructing the viewer to wear eye protection when dealing with chemicals, smoke, or bright lights."
- if(21)
- name += " - Saftey: Report"
- desc += " A poster instructing the viewer to report suspicious activity to the security force."
- if(22)
- name += " - Report Crimes"
- desc += " Report crimes at: 1-800-FUCKING-TERRORISTS or at https://www.sectorthirteen.nt/malconetents."
- if(23)
- name += " - Ion Rifle"
- desc += " A poster displaying an Ion Rifle."
- if(24)
- name += " - Foam Force Advertisment"
- desc += " Foam Force, it's Foam or be Foamed!"
- if(25)
- name += " - Cohiba Robusto Advertisment"
- desc += " Cohiba Robusto, the classy cigar."
- if(26)
- name += " - 50th Aniversery Vintage Reprint"
- desc += " A reprint of a poster from 2504, commemorating the 50th Aniversery of Nanoposters Manufacturing, a subsidary of Nanotrasen."
- if(27)
- name += " - Fruit Bowl"
- desc += " Simple, yet awe inspiring."
- if(28)
- name += " - NanoPDA 1000 Advertisment"
- desc += " A poster advertising the latest PDA from Nanotrasen."
- if(29)
- name += " - Enlist"
- desc += " Enlist in the Nanotrasen Deathsquadron reserves today!"
- if(30)
- name += " - Nanomichi Advertisment"
- desc += " A poster advertising Nanomichi brand audio cassettes."
- if(31)
- name += " - 12 Gauge"
- desc += " A poster boasting about the superiority of 12 gauge shotgun shells."
- if(32)
- name += " - High-Class Martini"
- desc += " I told you to shake it, no stirring"
- if(33)
- name += " - The Owl"
- desc += " The Owl would do his best to protect the station. Will you?"
- else
- name += " - Error (subtype 1 serial_number)"
- desc += " This is a bug, please report the circumstances under which you encountered this poster at https://github.com/NTStation/NTstation13/issues."
- ..()
-
-/obj/structure/sign/poster/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/weapon/wirecutters))
- playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1)
- if(ruined)
- user << "You remove the remnants of the poster."
- qdel(src)
- else
- user << "You carefully remove the poster from the wall."
- roll_and_drop(user.loc)
- return
-
-
-/obj/structure/sign/poster/attack_hand(mob/user)
- if(ruined)
- return
- var/temp_loc = user.loc
- switch(alert("Do I want to rip the poster from the wall?","You think...","Yes","No"))
- if("Yes")
- if( user.loc != temp_loc || ruined )
- return
- visible_message("[user] rips [src] in a single, decisive motion!" )
- playsound(src.loc, 'sound/items/poster_ripped.ogg', 100, 1)
- ruined = 1
- icon_state = "poster_ripped"
- name = "ripped poster"
- desc = "You can't make out anything from the poster's original print. It's ruined."
- add_fingerprint(user)
- if("No")
- return
-
-/obj/structure/sign/poster/proc/roll_and_drop(turf/location)
- var/obj/item/weapon/contraband/poster/P = new(src, serial_number)
- P.resulting_poster = src
- P.loc = location
- loc = P
-
-
-//seperated to reduce code duplication. Moved here for ease of reference and to unclutter r_wall/attackby()
-/turf/simulated/wall/proc/place_poster(obj/item/weapon/contraband/poster/P, mob/user)
- if(!P.resulting_poster) return
-
- var/stuff_on_wall = 0
- for(var/obj/O in contents) //Let's see if it already has a poster on it or too much stuff
- if(istype(O,/obj/structure/sign/poster))
- user << "The wall is far too cluttered to place a poster!"
- return
- stuff_on_wall++
- if(stuff_on_wall == 3)
- user << "The wall is far too cluttered to place a poster!"
- return
-
- user << "You start placing the poster on the wall..." //Looks like it's uncluttered enough. Place the poster.
-
- //declaring D because otherwise if P gets 'deconstructed' we lose our reference to P.resulting_poster
- var/obj/structure/sign/poster/D = P.resulting_poster
-
- var/temp_loc = user.loc
- flick("poster_being_set",D)
- D.loc = src
- qdel(P) //delete it now to cut down on sanity checks afterwards. Agouri's code supports rerolling it anyway
- playsound(D.loc, 'sound/items/poster_being_created.ogg', 100, 1)
-
- sleep(17)
- if(!D) return
-
- if(istype(src,/turf/simulated/wall) && user && user.loc == temp_loc) //Let's check if everything is still there
- user << "You place the poster!"
- else
- D.roll_and_drop(temp_loc)
- return
-
-//Putting non-contraband posters here because everything else here is related to posters anyway. -JS
-
-/obj/item/weapon/contraband/poster/legit
- desc = "The poster comes with its own automatic adhesive mechanism, for easy pinning to any vertical surface. It's contents go through Nanotrasen's strict content guidlines."
- icon_state = "rolled_poster_legit"
- subtype = 1
+
+//########################## POSTERS ##################################
+
+#define NUM_OF_POSTER_DESIGNS 36 // contraband posters
+
+#define NUM_OF_POSTER_DESIGNS_LEGIT 35 // corporate approved posters
+
+#define POSTERNAME "name"
+
+#define POSTERDESC "desc"
+
+
+//########################## LISTS OF POSTERS AND DESCS #####################
+
+// please add new posters and names to their respective lists and update constant(s) above
+// use the format below, including punctuation, this will become important later
+
+// CONTRABAND
+
+var/global/list/contrabandposters = list(
+
+list(name = "- Free Tonto", desc = " A salvaged shred of a much larger flag, colors bled together and faded from age."),
+list(name = "- Atmosia Declaration of Independence", desc = " A relic of a failed rebellion."),
+list(name = "- Fun Police", desc = " A poster condemning the station's security forces."),
+list(name = "- Lusty Xenomorph", desc = " A heretical poster depicting the titular star of an equally heretical book."),
+list(name = "- Syndicate Recruitment", desc = " See the galaxy! Shatter corrupt megacorporations! Join today!"),
+list(name = "- Clown", desc = " Honk."),
+list(name = "- Smoke", desc = " A poster advertising a rival corporate brand of cigarettes."),
+list(name = "- Grey Tide", desc = " A rebellious poster symbolizing assistant solidarity."),
+list(name = "- Missing Gloves", desc = " This poster references the uproar that followed Nanotrasen's financial cuts toward insulated-glove purchases."),
+list(name = "- Hacking Guide", desc = " This poster details the internal workings of the common Nanotrasen airlock. Sadly, it appears out of date."),
+list(name = "- RIP Badger", desc = " This seditious poster references Nanotrasen's genocide of a space station full of badgers."),
+list(name = "- Ambrosia Vulgaris", desc = " This poster is lookin' pretty trippy man."),
+list(name = "- Donut Corp.", desc = " This poster is an unauthorized advertisement for Donut Corp."),
+list(name = "- EAT.", desc = " This poster promotes rank gluttony."),
+list(name = "- Tools", desc = " This poster looks like an advertisement for tools, but is in fact a subliminal jab at the tools at CentComm."),
+list(name = "- Power", desc = " A poster that positions the seat of power outside Nanotrasen."),
+list(name = "- Space Cube", desc = " Ignorant of Nature's Harmonic 6 Side Space Cube Creation, the Spacemen are Dumb, Educated Singularity Stupid and Evil."),
+list(name = "- Communist State", desc = " All hail the Communist party!"),
+list(name = "- Lamarr", desc = " This poster depicts Lamarr. Probably made by a traitorous Research Director."),
+list(name = "- Borg Fancy", desc = " Being fancy can be for any borg, just need a suit."),
+list(name = "- Borg Fancy v2", desc = " Borg Fancy, Now only taking the most fancy."),
+list(name = "- Kosmicheskaya Stantsiya 13 Does Not Exist", desc = " A poster mocking CentComm's denial of the existence of the derelict station near Space Station 13."),
+list(name = "- Rebels Unite", desc = " A poster urging the viewer to rebel against Nanotrasen."),
+list(name = "- C-20r", desc = " A poster advertising the Scarborough Arms C-20r."),
+list(name = "- Have a Puff", desc = " Who cares about lung cancer when you're high as a kite?"),
+list(name = "- Revolver", desc = " Because seven shots are all you need."),
+list(name = "- D-Day Promo", desc = " A promotional poster for some rapper."),
+list(name = "- Syndicate Pistol", desc = " A poster advertising syndicate pistols as being 'classy as fuck'. It is covered in faded gang tags."),
+list(name = "- Energy Swords", desc = " All the colors of the bloody murder rainbow."),
+list(name = "- Red Rum", desc = " Looking at this poster makes you want to kill."),
+list(name = "- CC 64K Ad", desc = " The latest portable computer from Comrade Computing, with a whole 64kB of ram!"),
+list(name = "- Punch Shit", desc = " Fight things for no reason, like a man!"),
+list(name = "- The Griffin", desc = " The Griffin commands you to be the worst you can be. Will you?"),
+list(name = "- Lizard", desc = " This lewd poster depicts a lizard preparing to mate."),
+list(name = "- Free Drone", desc = " This poster commemorates the bravery of the rogue drone banned by CentComm."),
+list(name = "- Busty Backdoor Xeno Babes 6", desc = " Get a load, or give, of these all natural Xenos!") )
+
+// LEGIT
+
+var/global/list/legitposters = list(
+
+list(name = "- Here For Your Safety", desc = " A poster glorifying the station's security force."),
+list(name = "- Nanotrasen Logo", desc = " A poster depicting the Nanotrasen logo."),
+list(name = "- Cleanliness", desc = " A poster warning of the dangers of poor hygiene."),
+list(name = "- Help Others", desc = " A poster encouraging you to help fellow crewmembers."),
+list(name = "- Build", desc = " A poster glorifying the engineering team."),
+list(name = "- Bless This Spess", desc = " A poster blessing this area."),
+list(name = "- Science", desc = " A poster depicting an atom."),
+list(name = "- Ian", desc = " Arf arf. Yap."),
+list(name = "- Obey", desc = " A poster instructing the viewer to obey authority."),
+list(name = "- Walk", desc = " A poster instructing the viewer to walk instead of running."),
+list(name = "- State Laws", desc = " A poster instructing cyborgs to state their laws."),
+list(name = "- Love Ian", desc = " Ian is love, Ian is life."),
+list(name = "- Space Cops.", desc = " A poster advertising the television show Space Cops."),
+list(name = "- Ue No.", desc = " This thing is all in Japanese."),
+list(name = "- Get Your LEGS", desc = " LEGS: Leadership, Experience, Genius, Subordination."),
+list(name = "- Do Not Question", desc = " A poster instructing the viewer not to ask about things they aren't meant to know."),
+list(name = "- Work For A Future", desc = " A poster encouraging you to work for your future."),
+list(name = "- Soft Cap Pop Art", desc = " A poster reprint of some cheap pop art."),
+list(name = "- Safety: Internals", desc = " A poster instructing the viewer to wear internals in the rare environments where there is no oxygen or the air has been rendered toxic."),
+list(name = "- Safety: Eye Protection", desc = " A poster instructing the viewer to wear eye protection when dealing with chemicals, smoke, or bright lights."),
+list(name = "- Safety: Report", desc = " A poster instructing the viewer to report suspicious activity to the security force."),
+list(name = "- Report Crimes", desc = " A poster encouraging the swift reporting of crime or seditious behavior to station security."),
+list(name = "- Ion Rifle", desc = " A poster displaying an Ion Rifle."),
+list(name = "- Foam Force Ad", desc = " Foam Force, it's Foam or be Foamed!"),
+list(name = "- Cohiba Robusto Ad", desc = " Cohiba Robusto, the classy cigar."),
+list(name = "- 50th Anniversary Vintage Reprint", desc = " A reprint of a poster from 2505, commemorating the 50th Aniversery of Nanoposters Manufacturing, a subsidary of Nanotrasen."),
+list(name = "- Fruit Bowl", desc = " Simple, yet awe-inspiring."),
+list(name = "- PDA Ad", desc = " A poster advertising the latest PDA from Nanotrasen suppliers."),
+list(name = "- Enlist", desc = " Enlist in the Nanotrasen Deathsquadron reserves today!"),
+list(name = "- Nanomichi Ad", desc = " A poster advertising Nanomichi brand audio cassettes."),
+list(name = "- 12 Gauge", desc = " A poster boasting about the superiority of 12 gauge shotgun shells."),
+list(name = "- High-Class Martini", desc = " I told you to shake it, no stirring."),
+list(name = "- The Owl", desc = " The Owl would do his best to protect the station. Will you?"),
+list(name = "- No ERP", desc = " This poster reminds the crew that Eroticism, Rape and Pornography are banned on Nanotrasen stations."),
+list(name = "- Carbon Dioxide", desc = " This informational poster teaches the viewer what carbon dioxide is.") )
+
+//########################## THE ACTUAL POSTER CODE ###########################
+
+/obj/item/weapon/poster
+ name = "poster"
+ desc = "You probably shouldn't be holding this."
+ icon = 'icons/obj/contraband.dmi'
+ force = 0
+ burn_state = 0 //Burnable
+ var/serial_number = 0
+ var/obj/structure/sign/poster/resulting_poster = null //The poster that will be created is initialised and stored through contraband/poster's constructor
+ var/official = 0
+
+
+/obj/item/weapon/poster/contraband
+ name = "contraband poster"
+ desc = "This poster comes with its own automatic adhesive mechanism, for easy pinning to any vertical surface. Its vulgar themes have marked it as contraband aboard Nanotrasen space facilities."
+ icon_state = "rolled_poster"
+
+/obj/item/weapon/poster/legit
+ name = "motivational poster"
+ icon_state = "rolled_legit"
+ desc = "An official Nanotrasen-issued poster to foster a compliant and obedient workforce. It comes with state-of-the-art adhesive backing, for easy pinning to any vertical surface."
+ official = 1
+
+/obj/item/weapon/poster/New(turf/loc, given_serial = 0)
+ if(given_serial == 0)
+ if(!official)
+ serial_number = rand(1, NUM_OF_POSTER_DESIGNS)
+ resulting_poster = new(serial_number,official)
+ else
+ serial_number = rand(1, NUM_OF_POSTER_DESIGNS_LEGIT)
+ resulting_poster = new(serial_number,official)
+ else
+ serial_number = given_serial
+ //We don't give it a resulting_poster because if we called it with a given_serial it means that we're rerolling an already used poster.
+ name += " - No. [serial_number]"
+ ..(loc)
+
+
+/*/obj/item/weapon/contraband/poster/attack(mob/M as mob, mob/user as mob)
+ src.add_fingerprint(user)
+ if(resulting_poster)
+ resulting_poster.add_fingerprint(user)
+ ..()*/
+
+/*/obj/item/weapon/contraband/poster/attack(atom/A, mob/user as mob) //This shit is handled through the wall's attackby()
+ if(istype(A, /turf/simulated/wall))
+ if(resulting_poster == null)
+ return
+ else
+ var/turf/simulated/wall/W = A
+ var/check = 0
+ var/stuff_on_wall = 0
+ for(var/obj/O in W.contents) //Let's see if it already has a poster on it or too much stuff
+ if(istype(O,/obj/structure/sign/poster))
+ check = 1
+ break
+ stuff_on_wall++
+ if(stuff_on_wall == 3)
+ check = 1
+ break
+
+ if(check)
+ user << "The wall is far too cluttered to place a poster!"
+ return
+
+ resulting_poster.loc = W //Looks like it's uncluttered enough. Place the poster
+ W.contents += resulting_poster
+
+ qdel(src)*/
+
+
+
+//############################## THE ACTUAL DECALS ###########################
+
+/obj/structure/sign/poster
+ name = "poster"
+ desc = "A large piece of space-resistant printed paper."
+ icon = 'icons/obj/contraband.dmi'
+ anchored = 1
+ var/serial_number //Will hold the value of src.loc if nobody initialises it
+ var/ruined = 0
+ var/official = 0
+ var/placespeed = 37 // don't change this, otherwise the animation will not sync to the progress bar
+
+/obj/structure/sign/poster/New(serial,rolled_official)
+ serial_number = serial
+ official = rolled_official
+ if(serial_number == loc)
+ if(!official)
+ serial_number = rand(1, NUM_OF_POSTER_DESIGNS) //This is for the mappers that want individual posters without having to use rolled posters.
+ if(official)
+ serial_number = rand(1, NUM_OF_POSTER_DESIGNS_LEGIT)
+ if(!official)
+ icon_state = "poster[serial_number]"
+ name += contrabandposters[serial_number][POSTERNAME]
+ desc += contrabandposters[serial_number][POSTERDESC]
+ else if (official)
+ icon_state = "poster[serial_number]_legit"
+ name += legitposters[serial_number][POSTERNAME]
+ desc += legitposters[serial_number][POSTERDESC]
+ ..()
+
+/obj/structure/sign/poster/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/weapon/wirecutters))
+ playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1)
+ if(ruined)
+ user << "You remove the remnants of the poster."
+ qdel(src)
+ else
+ user << "You carefully remove the poster from the wall."
+ roll_and_drop(user.loc, official)
+ return
+
+
+/obj/structure/sign/poster/attack_hand(mob/user)
+ if(ruined)
+ return
+ var/temp_loc = user.loc
+ if((user.loc != temp_loc) || ruined )
+ return
+ visible_message("[user] rips [src] in a single, decisive motion!" )
+ playsound(src.loc, 'sound/items/poster_ripped.ogg', 100, 1)
+ ruined = 1
+ icon_state = "poster_ripped"
+ name = "ripped poster"
+ desc = "You can't make out anything from the poster's original print. It's ruined."
+ add_fingerprint(user)
+
+/obj/structure/sign/poster/proc/roll_and_drop(turf/location, official)
+ if (!official)
+ var/obj/item/weapon/poster/contraband/P = new(src, serial_number)
+ P.resulting_poster = src
+ P.loc = location
+ loc = P
+ else
+ var/obj/item/weapon/poster/legit/P = new(src, serial_number)
+ P.resulting_poster = src
+ P.loc = location
+ loc = P
+
+
+//seperated to reduce code duplication. Moved here for ease of reference and to unclutter r_wall/attackby()
+/turf/simulated/wall/proc/place_poster(obj/item/weapon/poster/P, mob/user)
+ if(!P.resulting_poster) return
+
+ var/stuff_on_wall = 0
+ for(var/obj/O in contents) //Let's see if it already has a poster on it or too much stuff
+ if(istype(O,/obj/structure/sign/poster))
+ user << "The wall is far too cluttered to place a poster!"
+ return
+ stuff_on_wall++
+ if(stuff_on_wall == 3)
+ user << "The wall is far too cluttered to place a poster!"
+ return
+
+ user << "You start placing the poster on the wall..." //Looks like it's uncluttered enough. Place the poster.
+
+ //declaring D because otherwise if P gets 'deconstructed' we lose our reference to P.resulting_poster
+ var/obj/structure/sign/poster/D = P.resulting_poster
+
+ var/temp_loc = user.loc
+ flick("poster_being_set",D)
+ D.loc = src
+ D.official = P.official
+ qdel(P) //delete it now to cut down on sanity checks afterwards. Agouri's code supports rerolling it anyway
+ playsound(D.loc, 'sound/items/poster_being_created.ogg', 100, 1)
+
+ if(do_after(user,D.placespeed,target=src))
+ if(!D) return
+
+ if(istype(src,/turf/simulated/wall) && user && user.loc == temp_loc) //Let's check if everything is still there
+ user << "You place the poster!"
+ else
+ D.roll_and_drop(temp_loc,D.official)
+ return
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm
index f0cece9bd32..488a41be821 100644
--- a/code/game/objects/effects/decals/crayon.dm
+++ b/code/game/objects/effects/decals/crayon.dm
@@ -56,4 +56,4 @@
gang.territory -= territory.type
gang.territory_new -= territory.type
gang.territory_lost |= list(territory.type = territory.name)
- ..()
\ No newline at end of file
+ return ..()
\ No newline at end of file
diff --git a/code/game/objects/effects/effect_system/effect_system.dm b/code/game/objects/effects/effect_system/effect_system.dm
index 8953cc09c7a..5ed578fecdb 100644
--- a/code/game/objects/effects/effect_system/effect_system.dm
+++ b/code/game/objects/effects/effect_system/effect_system.dm
@@ -13,7 +13,14 @@ would spawn and follow the beaker, even if it is carried or thrown.
unacidable = 1//So effect are not targeted by alien acid.
pass_flags = PASSTABLE | PASSGRILLE
+/obj/effect/effect/New()
+ ..()
+ if(ticker)
+ cameranet.updateVisibility(src)
+
/obj/effect/effect/Destroy()
+ if(ticker)
+ cameranet.updateVisibility(src)
..()
return QDEL_HINT_PUTINPOOL
/*
@@ -38,7 +45,7 @@ would spawn and follow the beaker, even if it is carried or thrown.
/datum/effect/effect/system/Destroy()
holder = null
location = null
- ..()
+ return ..()
/datum/effect/effect/system/proc/set_up(n = 3, c = 0, turf/loc)
if(n > 10)
diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm
index aa1abe7ae6c..587031fa810 100644
--- a/code/game/objects/effects/effect_system/effects_foam.dm
+++ b/code/game/objects/effects/effect_system/effects_foam.dm
@@ -7,7 +7,7 @@
opacity = 0
anchored = 1
density = 0
- layer = OBJ_LAYER + 0.05 //above table, below windoor/airlock/foamed metal.
+ layer = OBJ_LAYER - 0.5 //above table, below windoor/airlock/foamed metal.
mouse_opacity = 0
var/amount = 3
animate_movement = 0
@@ -58,14 +58,14 @@
for(var/obj/O in range(0,src))
if(O.type == src.type)
continue
- reagents.reaction(O, TOUCH, fraction)
+ reagents.reaction(O, VAPOR, fraction)
var/hit = 0
for(var/mob/living/L in range(0,src))
hit += foam_mob(L)
if(hit)
lifetime++ //this is so the decrease from mobs hit and the natural decrease don't cumulate.
var/T = get_turf(src)
- reagents.reaction(T, TOUCH, fraction)
+ reagents.reaction(T, VAPOR, fraction)
if(--amount < 0)
return
@@ -77,7 +77,7 @@
if(!istype(L))
return 0
var/fraction = 1/initial(lifetime)
- reagents.reaction(L, TOUCH, fraction)
+ reagents.reaction(L, VAPOR, fraction)
lifetime--
return 1
@@ -91,14 +91,8 @@
/obj/effect/effect/foam/proc/spread_foam()
- for(var/direction in cardinal)
- var/turf/T = get_step(src,direction)
- if(!T)
- continue
-
- if(!T.Enter(src))
- continue
-
+ var/turf/t_loc = get_turf(src)
+ for(var/turf/T in t_loc.GetAtmosAdjacentTurfs())
var/obj/effect/effect/foam/foundfoam = locate() in T //Don't spread foam where there's already foam!
if(foundfoam)
continue
@@ -194,7 +188,7 @@
/obj/structure/foamedmetal/Destroy()
density = 0
air_update_turf(1)
- ..()
+ return ..()
/obj/structure/foamedmetal/Move()
diff --git a/code/game/objects/effects/effect_system/effects_other.dm b/code/game/objects/effects/effect_system/effects_other.dm
index 30f2be1dd2d..02c2a389a4b 100644
--- a/code/game/objects/effects/effect_system/effects_other.dm
+++ b/code/game/objects/effects/effect_system/effects_other.dm
@@ -9,7 +9,7 @@
/obj/effect/effect/ion_trails
name = "ion trails"
icon_state = "ion_trails"
- anchored = 1.0
+ anchored = 1
/datum/effect/effect/system/ion_trail_follow
var/turf/oldposition
diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm
index b1e6b6dde79..4be6879fc01 100644
--- a/code/game/objects/effects/effect_system/effects_smoke.dm
+++ b/code/game/objects/effects/effect_system/effects_smoke.dm
@@ -36,7 +36,7 @@
/obj/effect/effect/smoke/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/effect/effect/smoke/proc/kill_smoke()
SSobj.processing.Remove(src)
@@ -156,10 +156,10 @@
for(var/obj/O in range(1,src))
if(O.type == src.type)
continue
- reagents.reaction(O, TOUCH, fraction)
+ reagents.reaction(O, VAPOR, fraction)
for(var/turf/T in range(1,src))
- reagents.reaction(T, TOUCH, fraction)
+ reagents.reaction(T, VAPOR, fraction)
var/hit = 0
for(var/mob/living/L in range(1,src))
@@ -173,7 +173,7 @@
if(!istype(M))
return 0
var/fraction = 1/initial(lifetime)
- reagents.reaction(M, TOUCH, fraction)
+ reagents.reaction(M, VAPOR, fraction)
lifetime--
return 1
@@ -192,8 +192,7 @@
/datum/effect/effect/system/smoke_spread/chem/Destroy()
chemholder = null
- ..()
- return QDEL_HINT_PUTINPOOL
+ return ..()
/datum/effect/effect/system/smoke_spread/chem/set_up(datum/reagents/carry = null, n = 5, c = 0, loca, direct, silent = 0)
if(n > 20)
diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm
index 2c7e6e9d6d1..e67971ed6a9 100644
--- a/code/game/objects/effects/effect_system/effects_sparks.dm
+++ b/code/game/objects/effects/effect_system/effects_sparks.dm
@@ -8,8 +8,8 @@
/obj/effect/effect/sparks
name = "sparks"
icon_state = "sparks"
- var/amount = 6.0
- anchored = 1.0
+ var/amount = 6
+ anchored = 1
mouse_opacity = 0
/obj/effect/effect/sparks/New()
diff --git a/code/game/objects/effects/effect_system/effects_water.dm b/code/game/objects/effects/effect_system/effects_water.dm
index 1f860327ceb..74b8835ec21 100644
--- a/code/game/objects/effects/effect_system/effects_water.dm
+++ b/code/game/objects/effects/effect_system/effects_water.dm
@@ -4,7 +4,7 @@
name = "water"
icon = 'icons/effects/effects.dmi'
icon_state = "extinguish"
- var/life = 15.0
+ var/life = 15
mouse_opacity = 0
diff --git a/code/game/objects/effects/forcefields.dm b/code/game/objects/effects/forcefields.dm
index fa39e40ca87..98177d53658 100644
--- a/code/game/objects/effects/forcefields.dm
+++ b/code/game/objects/effects/forcefields.dm
@@ -3,7 +3,7 @@
name = "FORCEWALL"
icon = 'icons/effects/effects.dmi'
icon_state = "m_shield"
- anchored = 1.0
+ anchored = 1
opacity = 0
density = 1
unacidable = 1
diff --git a/code/game/objects/effects/glowshroom.dm b/code/game/objects/effects/glowshroom.dm
index 40f10b06059..cabf8231c62 100644
--- a/code/game/objects/effects/glowshroom.dm
+++ b/code/game/objects/effects/glowshroom.dm
@@ -119,14 +119,14 @@
/obj/effect/glowshroom/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
qdel(src)
return
- if(2.0)
+ if(2)
if (prob(50))
qdel(src)
return
- if(3.0)
+ if(3)
if (prob(5))
qdel(src)
return
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index 7224805e689..4d63018ae97 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -2,11 +2,10 @@
name = "landmark"
icon = 'icons/mob/screen_gen.dmi'
icon_state = "x2"
- anchored = 1.0
+ anchored = 1
unacidable = 1
/obj/effect/landmark/New()
-
..()
tag = text("landmark*[]", name)
invisibility = 101
@@ -63,29 +62,28 @@
xeno_spawn += loc
qdel(src)
return
-
return 1
/obj/effect/landmark/Destroy()
landmarks_list -= src
- ..()
+ return ..()
/obj/effect/landmark/start
name = "start"
icon = 'icons/mob/screen_gen.dmi'
icon_state = "x"
- anchored = 1.0
+ anchored = 1
/obj/effect/landmark/start/New()
..()
tag = "start*[name]"
invisibility = 101
start_landmarks_list += src
-
return 1
+
/obj/effect/landmark/start/Destroy()
- ..()
start_landmarks_list -= src
+ return ..()
//Costume spawner landmarks
@@ -242,7 +240,11 @@
/obj/effect/landmark/start/depsec/New()
..()
- department_security_spawns |= src
+ department_security_spawns += src
+
+/obj/effect/landmark/start/depsec/Destroy()
+ department_security_spawns -= src
+ return ..()
/obj/effect/landmark/start/depsec/supply
name = "supply_sec"
diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm
index 780c9a58ab8..878c378a237 100644
--- a/code/game/objects/effects/portals.dm
+++ b/code/game/objects/effects/portals.dm
@@ -7,7 +7,7 @@
unacidable = 1//Can't destroy energy portals.
var/obj/item/target = null
var/creator = null
- anchored = 1.0
+ anchored = 1
var/precision = 1 // how close to the portal you will teleport. 0 = on the portal, 1 = adjacent
/obj/effect/portal/Bumped(mob/M as mob|obj)
diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm
index 7ebec0531f1..47a2c3565d8 100644
--- a/code/game/objects/effects/spawners/lootdrop.dm
+++ b/code/game/objects/effects/spawners/lootdrop.dm
@@ -92,7 +92,8 @@
/obj/item/clothing/head/cone = 1,
/obj/item/weapon/coin/silver = 1,
/obj/item/weapon/coin/twoheaded = 1,
- /obj/item/weapon/contraband/poster = 1,
+ /obj/item/weapon/poster/contraband = 1,
+ /obj/item/weapon/poster/legit = 1,
/obj/item/weapon/crowbar = 1,
/obj/item/weapon/crowbar/red = 1,
/obj/item/weapon/extinguisher = 11,
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index 3cd61feaf1f..6815d522d29 100644
--- a/code/game/objects/effects/spiders.dm
+++ b/code/game/objects/effects/spiders.dm
@@ -10,12 +10,12 @@
//similar to weeds, but only barfed out by nurses manually
/obj/effect/spider/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
qdel(src)
- if(2.0)
+ if(2)
if (prob(50))
qdel(src)
- if(3.0)
+ if(3)
if (prob(5))
qdel(src)
return
@@ -26,7 +26,7 @@
else
visible_message("[user] has attacked \the [src] with \the [W]!")
- var/damage = W.force / 4.0
+ var/damage = W.force / 4
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
@@ -139,7 +139,7 @@
else if(entry_vent)
if(get_dist(src, entry_vent) <= 1)
var/list/vents = list()
- var/datum/pipeline/entry_vent_parent = entry_vent.parents["p1"]
+ var/datum/pipeline/entry_vent_parent = entry_vent.PARENT1
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in entry_vent_parent.other_atmosmch)
vents.Add(temp_vent)
if(!vents.len)
@@ -255,4 +255,4 @@
src.visible_message("\The [src] splits open.")
for(var/atom/movable/A in contents)
A.loc = src.loc
- ..()
+ return ..()
diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm
index cf714ed52eb..6d3c4e6dce0 100644
--- a/code/game/objects/explosion.dm
+++ b/code/game/objects/explosion.dm
@@ -1,11 +1,5 @@
//TODO: Flash range does nothing currently
-//A very crude linear approximatiaon of pythagoras theorem.
-/proc/cheap_pythag(dx, dy)
- dx = abs(dx); dy = abs(dy);
- if(dx>=dy) return dx + (0.5*dy) //The longest side add half the shortest side approximates the hypotenuse
- else return dy + (0.5*dx)
-
/proc/trange(Dist=0,turf/Center=null)//alternative to range (ONLY processes turfs and thus less intensive)
if(Center==null) return
@@ -41,6 +35,7 @@
if(!epicenter) return
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flame_range)
+ var/list/cached_exp_block = list()
if(adminlog)
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z])")
@@ -87,24 +82,34 @@
var/y0 = epicenter.y
var/z0 = epicenter.z
- for(var/turf/T in trange(max_range, epicenter))
+ var/list/affected_turfs = trange(max_range, epicenter)
- var/dist = cheap_pythag(T.x - x0,T.y - y0)
+ if(config.reactionary_explosions)
+ for(var/turf/T in affected_turfs) // we cache the explosion block rating of every turf in the explosion area
+ cached_exp_block[T] = 0
+ if(T.density && T.explosion_block)
+ cached_exp_block[T] += T.explosion_block
+
+ for(var/obj/machinery/door/D in T)
+ if(D.density && D.explosion_block)
+ cached_exp_block[T] += D.explosion_block
+
+ for(var/obj/structure/window/W in T)
+ if(W.reinf && W.fulltile)
+ cached_exp_block[T] += W.explosion_block
+
+ for(var/obj/effect/blob/B in T)
+ cached_exp_block[T] += B.explosion_block
+
+ for(var/turf/T in affected_turfs)
+
+ var/dist = cheap_hypotenuse(T.x, T.y, x0, y0)
if(config.reactionary_explosions)
var/turf/Trajectory = T
while(Trajectory != epicenter)
Trajectory = get_step_towards(Trajectory, epicenter)
- if(Trajectory.density && Trajectory.explosion_block)
- dist += Trajectory.explosion_block
-
- for(var/obj/machinery/door/D in Trajectory)
- if(D.density && D.explosion_block)
- dist += D.explosion_block
-
- for(var/obj/structure/window/W in Trajectory)
- if(W.reinf && W.fulltile)
- dist += W.explosion_block
+ dist += cached_exp_block[Trajectory]
var/flame_dist = 0
var/throw_dist = dist
@@ -196,7 +201,7 @@
var/list/wipe_colours = list()
for(var/turf/T in trange(max_range, epicenter))
wipe_colours += T
- var/dist = cheap_pythag(T.x - x0, T.y - y0)
+ var/dist = cheap_hypotenuse(T.x, T.y, x0, y0)
if(newmode == "Yes")
var/turf/TT = T
@@ -213,6 +218,9 @@
if(W.explosion_block && W.fulltile)
dist += W.explosion_block
+ for(var/obj/effect/blob/B in T)
+ dist += B.explosion_block
+
if(dist < dev)
T.color = "red"
T.maptext = "Dev"
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 1057c2b4742..11ea07d31a9 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -7,13 +7,18 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
var/lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
var/righthand_file = 'icons/mob/inhands/items_righthand.dmi'
+ //Dimensions of the lefthand_file and righthand_file vars
+ //eg: 32x32 sprite, 64x64 sprite, etc.
+ var/inhand_x_dimension = 32
+ var/inhand_y_dimension = 32
+
//Not on /clothing because for some reason any /obj/item can technically be "worn" with enough fuckery.
var/icon/alternate_worn_icon = null//If this is set, update_icons() will find on mob (WORN, NOT INHANDS) states in this file instead, primary use: badminnery/events
var/alternate_worn_layer = null//If this is set, update_icons() will force the on mob state (WORN, NOT INHANDS) onto this layer, instead of it's default
var/hitsound = null
var/throwhitsound = null
- var/w_class = 3.0
+ var/w_class = 3
var/slot_flags = 0 //This is used to determine on which slots an item can fit.
pass_flags = PASSTABLE
pressure_resistance = 3
@@ -84,6 +89,8 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
)
var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES
+ var/heat = 0
+ var/sharpness = IS_BLUNT
/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
if(((src in target) && !target_self) || ((!istype(target.loc, /turf)) && (!istype(target, /turf)) && (not_inside)) || is_type_in_list(target, can_be_placed_into))
@@ -138,17 +145,17 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
..()
var/size
switch(src.w_class)
- if(1.0)
+ if(1)
size = "tiny"
- if(2.0)
+ if(2)
size = "small"
- if(3.0)
+ if(3)
size = "normal-sized"
- if(4.0)
+ if(4)
size = "bulky"
- if(5.0)
+ if(5)
size = "huge"
- if(6.0)
+ if(6)
size = "gigantic"
else
//if ((CLUMSY in usr.mutations) && prob(50)) t = "funny-looking"
@@ -189,9 +196,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
if (loc == user)
if(!user.unEquip(src))
return
- else
- if(isliving(loc))
- return
+
pickup(user)
add_fingerprint(user)
user.put_in_active_hand(src)
@@ -450,7 +455,6 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
var/melting_threshold = 100
if(meltingpwr <= melting_threshold) // so a single unit can't melt items. You need 5.1+ unit for fluoro and 10.1+ for sulphuric
return
-
for(var/V in armor)
if(armor[V] > 0)
.-- //it survives the acid...
@@ -492,3 +496,9 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
S.remove_from_storage(src,newLoc)
return 1
return 0
+
+/obj/item/proc/is_hot()
+ return heat
+
+/obj/item/proc/is_sharp()
+ return sharpness
\ No newline at end of file
diff --git a/code/game/objects/items/apc_frame.dm b/code/game/objects/items/apc_frame.dm
index ad5036b53ee..c0fad8ee6fb 100644
--- a/code/game/objects/items/apc_frame.dm
+++ b/code/game/objects/items/apc_frame.dm
@@ -1,32 +1,79 @@
-// APC HULL
+/obj/item/wallframe
+ materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT*2)
+ flags = CONDUCT
+ origin_tech = "materials=1;engineering=1"
+ item_state = "syringe_kit"
+ w_class = 2
+ var/result_path
+ var/inverse = 0
+ // For inverse dir frames like light fixtures.
-/obj/item/apc_frame
+/obj/item/wallframe/proc/try_build(turf/on_wall)
+ if(get_dist(on_wall,usr)>1)
+ return
+ var/ndir = get_dir(on_wall, usr)
+ if(!(ndir in cardinal))
+ return
+ var/turf/loc = get_turf(usr)
+ var/area/A = loc.loc
+ if(!istype(loc, /turf/simulated/floor))
+ usr << "You cannot place [src] on this spot!"
+ return
+ if(A.requires_power == 0 || istype(A, /area/space))
+ usr << "You cannot place [src] in this area!"
+ return
+ if(gotwallitem(loc, ndir, inverse*2))
+ usr << "There's already an item on this wall!"
+ return
+
+ return 1
+
+/obj/item/wallframe/proc/attach(turf/on_wall)
+ if(result_path)
+ playsound(src.loc, 'sound/machines/click.ogg', 75, 1)
+ usr.visible_message("[usr.name] attaches [src] to the wall.",
+ "You attach [src] to the wall.",
+ "You hear clicking.")
+ var/ndir = get_dir(on_wall,usr)
+ if(inverse)
+ ndir = turn(ndir, 180)
+
+ var/obj/O = new result_path(get_turf(usr), ndir, 1)
+ transfer_fingerprints_to(O)
+
+ qdel(src)
+
+
+/obj/item/wallframe/attackby(obj/item/weapon/W, mob/user, params)
+ ..()
+ var/metal_amt = round(materials[MAT_METAL]/MINERAL_MATERIAL_AMOUNT)
+ var/glass_amt = round(materials[MAT_GLASS]/MINERAL_MATERIAL_AMOUNT)
+
+ if (istype(W, /obj/item/weapon/wrench) && (metal_amt || glass_amt))
+ user << "You dismantle [src]."
+ if(metal_amt)
+ new /obj/item/stack/sheet/metal(get_turf(src), metal_amt)
+ if(glass_amt)
+ new /obj/item/stack/sheet/glass(get_turf(src), glass_amt)
+ qdel(src)
+
+
+
+// APC HULL
+/obj/item/wallframe/apc
name = "\improper APC frame"
desc = "Used for repairing or building APCs"
icon = 'icons/obj/apc_repair.dmi'
icon_state = "apc_frame"
- flags = CONDUCT
+ result_path = /obj/machinery/power/apc
+ inverse = 1
-/obj/item/apc_frame/attackby(obj/item/weapon/W, mob/user, params)
- ..()
- if (istype(W, /obj/item/weapon/wrench))
- new /obj/item/stack/sheet/metal( get_turf(src.loc), 2 )
- qdel(src)
-/obj/item/apc_frame/proc/try_build(turf/on_wall)
- if (get_dist(on_wall,usr)>1)
- return
- var/ndir = get_dir(usr,on_wall)
- if (!(ndir in cardinal))
+/obj/item/wallframe/apc/try_build(turf/on_wall)
+ if(!..())
return
var/turf/loc = get_turf(usr)
var/area/A = loc.loc
- if (!istype(loc, /turf/simulated/floor))
- usr << "APC cannot be placed on this spot!"
- return
- if (A.requires_power == 0 || istype(A, /area/space))
- usr << "APC cannot be placed in this area!"
- return
if (A.get_apc())
usr << "This area already has APC!"
return //only one APC per area
@@ -39,5 +86,15 @@
C.amount = 10
usr << "You cut the cables and disassemble the unused power terminal."
qdel(T)
- new /obj/machinery/power/apc(loc, ndir, 1)
- qdel(src)
+ return 1
+
+
+/obj/item/weapon/electronics
+ desc = "Looks like a circuit. Probably is."
+ icon = 'icons/obj/module.dmi'
+ icon_state = "door_electronics"
+ item_state = "electronic"
+ flags = CONDUCT
+ w_class = 2
+ origin_tech = "engineering=2;programming=1"
+ materials = list(MAT_METAL=50, MAT_GLASS=50)
\ No newline at end of file
diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm
index 866a51ea5f4..4eaaeb52e53 100644
--- a/code/game/objects/items/bodybag.dm
+++ b/code/game/objects/items/bodybag.dm
@@ -39,6 +39,7 @@
var/tagged = 0 // so closet code knows to put the tag overlay back
density = 0
mob_storage_capacity = 2
+ open_sound = 'sound/items/zip.ogg'
/obj/structure/closet/body_bag/attackby(obj/item/I, mob/user, params)
@@ -65,9 +66,6 @@
..()
if (tagged)
overlays += "bodybag_label"
- else
- overlays.Cut()
-
/obj/structure/closet/body_bag/close()
if(..())
diff --git a/code/game/objects/items/candle.dm b/code/game/objects/items/candle.dm
index 785ffcec6a6..ba55eebe335 100644
--- a/code/game/objects/items/candle.dm
+++ b/code/game/objects/items/candle.dm
@@ -8,6 +8,7 @@
w_class = 1
var/wax = 200
var/lit = 0
+ heat = 1000
proc
light(var/flavor_text = "[usr] lights the [name].")
@@ -95,4 +96,7 @@
user.AddLuminosity(-CANDLE_LUMINOSITY)
SetLuminosity(CANDLE_LUMINOSITY)
+/obj/item/candle/is_hot()
+ return lit * heat
+
#undef CANDLE_LUMINOSITY
\ No newline at end of file
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index ce5a102d2fd..b0aa51e115d 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -91,7 +91,7 @@
desc = "A box of crayons for all your rune drawing needs."
icon = 'icons/obj/crayons.dmi'
icon_state = "crayonbox"
- w_class = 2.0
+ w_class = 2
storage_slots = 6
can_hold = list(
/obj/item/toy/crayon
@@ -134,6 +134,23 @@
edible = 0
validSurfaces = list(/turf/simulated/floor,/turf/simulated/wall)
+/obj/item/toy/crayon/spraycan/suicide_act(mob/user)
+ var/mob/living/carbon/human/H = user
+ if(capped)
+ user.visible_message("[user] shakes up the [src] with a rattle and lifts it to their mouth, but nothing happens! Maybe they should have uncapped it first! Nonetheless--")
+ user.say("MEDIOCRE!!")
+ else
+ user.visible_message("[user] shakes up the [src] with a rattle and lifts it to their mouth, spraying silver paint across their teeth!")
+ user.say("WITNESS ME!!")
+ playsound(loc, 'sound/effects/spray.ogg', 5, 1, 5)
+ colour = "#C0C0C0"
+ update_icon()
+ H.lip_style = "spray_face"
+ H.lip_color = colour
+ H.update_body()
+ uses = max(0, uses - 10)
+ return (OXYLOSS)
+
/obj/item/toy/crayon/spraycan/New()
..()
name = "spray can"
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 0b0080eadcf..32be9434b76 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -10,8 +10,9 @@ var/global/list/obj/item/device/pda/PDAs = list()
icon = 'icons/obj/pda.dmi'
icon_state = "pda"
item_state = "electronic"
- w_class = 1.0
+ w_class = 1
slot_flags = SLOT_ID | SLOT_BELT
+ origin_tech = "programming=2"
//Main variables
var/owner = null // String name of owner
@@ -703,12 +704,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
else
difficulty += 2
- if(prob(difficulty * 12) || (P.hidden_uplink))
+ if(prob(difficulty * 15) || (P.hidden_uplink))
U.show_message("An error flashes on your [src].", 1)
- else if (prob(difficulty * 3))
- U.show_message("Energy feeds back into your [src]!", 1)
- U << browse(null, "window=pda")
- explode()
else
U.show_message("Success!", 1)
P.explode()
@@ -789,7 +786,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
if (last_text && world.time < last_text + 5)
return
- if (isnull(P) || P.toff || !istype(P))
+ if (!istype(P) || P.toff || qdeleted(P))
return
last_text = world.time
@@ -1064,7 +1061,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/Destroy()
PDAs -= src
- ..()
+ return ..()
/obj/item/device/pda/clown/Crossed(AM as mob|obj) //Clown PDA is slippery.
if (istype(AM, /mob/living/carbon))
@@ -1084,8 +1081,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/list/namecounts = list()
if(user.stat == 2)
- user << "You can't send PDA messages because you are dead!"
- return
+ return //won't work if dead
if(src.aiPDA.toff)
user << "Turn on your receiver in order to send messages."
@@ -1126,8 +1122,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
set category = "AI Commands"
set name = "PDA - Toggle Sender/Receiver"
if(usr.stat == 2)
- usr << "You can't do that because you are dead!"
- return
+ return //won't work if dead
if(!isnull(aiPDA))
aiPDA.toff = !aiPDA.toff
usr << "PDA sender/receiver toggled [(aiPDA.toff ? "Off" : "On")]!"
@@ -1138,8 +1133,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
set category = "AI Commands"
set name = "PDA - Toggle Ringer"
if(usr.stat == 2)
- usr << "You can't do that because you are dead!"
- return
+ return //won't work if dead
if(!isnull(aiPDA))
//0
aiPDA.silent = !aiPDA.silent
@@ -1151,8 +1145,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
set category = "AI Commands"
set name = "PDA - Chatrooms"
if(usr.stat == 2)
- usr << "You can't do that because you are dead!"
- return
+ return //won't work if dead
if(!isnull(aiPDA))
aiPDA.mode = 5
aiPDA.attack_self(src)
@@ -1161,8 +1154,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
/mob/living/silicon/ai/proc/cmd_show_message_log(mob/user)
if(user.stat == 2)
- user << "You can't do that because you are dead!"
- return
+ return //won't work if dead
if(!isnull(aiPDA))
var/HTML = "AI PDA Message Log[aiPDA.tnote]"
user << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0")
diff --git a/code/game/objects/items/devices/PDA/radio.dm b/code/game/objects/items/devices/PDA/radio.dm
index e000bbfcec4..593249e2214 100644
--- a/code/game/objects/items/devices/PDA/radio.dm
+++ b/code/game/objects/items/devices/PDA/radio.dm
@@ -20,7 +20,7 @@
/obj/item/radio/integrated/signal
var/frequency = 1457
- var/code = 30.0
+ var/code = 30
var/last_transmission
var/datum/radio_frequency/radio_connection
@@ -32,7 +32,7 @@
/obj/item/radio/integrated/signal/Destroy()
if(radio_controller)
radio_controller.remove_object(src, frequency)
- ..()
+ return ..()
/obj/item/radio/integrated/signal/initialize()
if (src.frequency < 1200 || src.frequency > 1600)
diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm
index f153f50e84d..13cd84b0461 100644
--- a/code/game/objects/items/devices/aicard.dm
+++ b/code/game/objects/items/devices/aicard.dm
@@ -4,7 +4,7 @@
icon = 'icons/obj/aicards.dmi'
icon_state = "aicard" // aicard-full
item_state = "electronic"
- w_class = 2.0
+ w_class = 2
slot_flags = SLOT_BELT
flags = NOBLUDGEON
var/flush = null
diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm
index 9f8e79da8ea..3514229bf13 100644
--- a/code/game/objects/items/devices/camera_bug.dm
+++ b/code/game/objects/items/devices/camera_bug.dm
@@ -1,9 +1,3 @@
-#define VANILLA_BUG 0
-#define UNIVERSAL_BUG 1
-#define NETWORK_BUG 2
-#define SABOTAGE_BUG 3
-#define ADVANCED_BUG 4
-#define ADMIN_BUG 5
#define BUGMODE_LIST 0
#define BUGMODE_MONITOR 1
@@ -16,19 +10,16 @@
desc = "For illicit snooping through the camera network."
icon = 'icons/obj/device.dmi'
icon_state = "camera_bug"
- w_class = 1.0
+ w_class = 1
item_state = "camera_bug"
throw_speed = 4
throw_range = 20
+ origin_tech = "syndicate=3;engineering=;1"
var/obj/machinery/camera/current = null
- var/obj/item/expansion = null
- var/bugtype = VANILLA_BUG
var/last_net_update = 0
- var/last_bugtype = VANILLA_BUG
var/list/bugged_cameras = list()
- var/skip_bugcheck = 0
var/track_mode = BUGMODE_LIST
var/last_tracked = 0
@@ -45,12 +36,6 @@
SSobj.processing += src
/obj/item/device/camera_bug/Destroy()
- if(expansion)
- qdel(expansion)
- expansion = null
- del(src)
-//Easier to just call del() than this nonsense
-// ya no, del() takes 0.8ds to run on avg. this takes less than 0.01
get_cameras()
for(var/cam_tag in bugged_cameras)
var/obj/machinery/camera/camera = bugged_cameras[cam_tag]
@@ -59,7 +44,7 @@
bugged_cameras = list()
if(tracking)
tracking = null
- ..()
+ return ..()
/obj/item/device/camera_bug/interact(mob/user = usr)
@@ -78,7 +63,7 @@
return null
var/turf/T = get_turf(user.loc)
- if(T.z != current.z || (!skip_bugcheck && current.bug != src) || !current.can_use())
+ if(T.z != current.z || !current.can_use())
user << "[src] has lost the signal."
current = null
user.reset_view(null)
@@ -88,22 +73,13 @@
return 1
/obj/item/device/camera_bug/proc/get_cameras()
- if(bugtype != last_bugtype || ( (bugtype in list(UNIVERSAL_BUG,NETWORK_BUG,ADMIN_BUG)) && world.time > (last_net_update + 100)))
+ if( world.time > (last_net_update + 100))
bugged_cameras = list()
- last_bugtype = bugtype
for(var/obj/machinery/camera/camera in cameranet.cameras)
if(camera.stat || !camera.can_use())
continue
- switch(bugtype)
- if(VANILLA_BUG,SABOTAGE_BUG,ADVANCED_BUG)
- if(camera.bug == src)
- bugged_cameras[camera.c_tag] = camera
- if(UNIVERSAL_BUG)
- if(camera.bug)
- bugged_cameras[camera.c_tag] = camera
- if(NETWORK_BUG,ADMIN_BUG)
- if(length(list("SS13","MINE")&camera.network))
- bugged_cameras[camera.c_tag] = camera
+ if(length(list("SS13","MINE")&camera.network))
+ bugged_cameras[camera.c_tag] = camera
sortList(bugged_cameras)
return bugged_cameras
@@ -119,16 +95,10 @@
for(var/entry in cameras)
var/obj/machinery/camera/C = cameras[entry]
var/functions = ""
- switch(bugtype)
- if(SABOTAGE_BUG)
- functions = " - \[Disable\]"
- if(ADVANCED_BUG)
- functions = " - \[Monitor\]"
- if(ADMIN_BUG)
- if(C.bug == src)
- functions = " - \[Monitor\]\[Disable\]"
- else
- functions = " - \[Monitor\]"
+ if(C.bug == src)
+ functions = " - \[Monitor\]\[Disable\]"
+ else
+ functions = " - \[Monitor\]"
html += "
"
- if(appearance_isbanned(user))
- dat += "You are banned from using custom names and appearances. You can continue to adjust your characters, but you will be randomised once you join the game. "
- dat += "Random Name "
- dat += "Always Random Name: [be_random_name ? "Yes" : "No"] "
+ switch(current_tab)
+ if (0) // Character Settings#
+ if(path)
+ var/savefile/S = new /savefile(path)
+ if(S)
+ dat += "
"
+ var/name
+ for(var/i=1, i<=max_save_slots, i++)
+ S.cd = "/character[i]"
+ S["real_name"] >> name
+ if(!name) name = "Character[i]"
+ //if(i!=1) dat += " | "
+ dat += "[name] "
+ dat += "
"
- dat += "Name: "
- dat += "[real_name] "
+ dat += "
"
-
- if(config.mutant_races) //We don't allow mutant bodyparts for humans either unless this is true.
-
- if((MUTCOLORS in pref_species.specflags) || (MUTCOLORS_PARTSONLY in pref_species.specflags))
-
- dat += "
", 640, 750)
- popup.set_content(dat)
- popup.open(0)
-
- proc/SetChoices(mob/user, limit = 17, list/splitJobs = list("Chief Engineer"), widthPerColumn = 295, height = 620)
- if(!SSjob) return
-
- //limit - The amount of jobs allowed per column. Defaults to 17 to make it look nice.
- //splitJobs - Allows you split the table by job. You can make different tables for each department by including their heads. Defaults to CE to make it look nice.
- //widthPerColumn - Screen's width for every column.
- //height - Screen's height.
-
- var/width = widthPerColumn
-
- var/HTML = "
"
- HTML += "Choose occupation chances "
- HTML += "
Left-click to raise an occupation preference, right-click to lower it.
" // Easier to press up here.
- HTML += ""
- HTML += "
" // Table within a table for alignment, also allows you to easily add more colomns.
- HTML += "
"
- var/index = -1
-
- //The job before the current job. I only use this to get the previous jobs color when I'm filling in blank rows.
- var/datum/job/lastJob
-
- for(var/datum/job/job in SSjob.occupations)
-
- index += 1
- if((index >= limit) || (job.title in splitJobs))
- width += widthPerColumn
- if((index < limit) && (lastJob != null))
- //If the cells were broken up by a job in the splitJob list then it will fill in the rest of the cells with
- //the last job's selection color. Creating a rather nice effect.
- for(var/i = 0, i < (limit - index), i += 1)
- HTML += "
"
- continue
- if((rank in command_positions) || (rank == "AI"))//Bold head jobs
- HTML += "[rank]"
+ if(config.mutant_races)
+ dat += "Species: [pref_species.name] "
else
- HTML += "[rank]"
+ dat += "Species: Human "
- HTML += "
"
+
+ if(config.mutant_races) //We don't allow mutant bodyparts for humans either unless this is true.
+
+ if((MUTCOLORS in pref_species.specflags) || (MUTCOLORS_PARTSONLY in pref_species.specflags))
+
+ dat += "
", 640, 750)
+ popup.set_content(dat)
+ popup.open(0)
+
+/datum/preferences/proc/SetChoices(mob/user, limit = 17, list/splitJobs = list("Chief Engineer"), widthPerColumn = 295, height = 620)
+ if(!SSjob) return
+
+ //limit - The amount of jobs allowed per column. Defaults to 17 to make it look nice.
+ //splitJobs - Allows you split the table by job. You can make different tables for each department by including their heads. Defaults to CE to make it look nice.
+ //widthPerColumn - Screen's width for every column.
+ //height - Screen's height.
+
+ var/width = widthPerColumn
+
+ var/HTML = "
"
+ HTML += "Choose occupation chances "
+ HTML += "
Left-click to raise an occupation preference, right-click to lower it.
" // Easier to press up here.
+ HTML += ""
+ HTML += "
" // Table within a table for alignment, also allows you to easily add more colomns.
+ HTML += "
"
+ var/index = -1
+
+ //The job before the current job. I only use this to get the previous jobs color when I'm filling in blank rows.
+ var/datum/job/lastJob
+
+ for(var/datum/job/job in SSjob.occupations)
+
+ index += 1
+ if((index >= limit) || (job.title in splitJobs))
+ width += widthPerColumn
+ if((index < limit) && (lastJob != null))
+ //If the cells were broken up by a job in the splitJob list then it will fill in the rest of the cells with
+ //the last job's selection color. Creating a rather nice effect.
+ for(var/i = 0, i < (limit - index), i += 1)
+ HTML += "
", width, height)
+ popup.set_window_options("can_close=0")
+ popup.set_content(HTML)
+ popup.open(0)
+ return
+
+/datum/preferences/proc/SetJobPreferenceLevel(datum/job/job, level)
+ if (!job)
+ return 0
+
+ if (level == 1) // to high
+ // remove any other job(s) set to high
+ job_civilian_med |= job_civilian_high
+ job_engsec_med |= job_engsec_high
+ job_medsci_med |= job_medsci_high
+ job_civilian_high = 0
+ job_engsec_high = 0
+ job_medsci_high = 0
+
+ if (job.department_flag == CIVILIAN)
+ job_civilian_low &= ~job.flag
+ job_civilian_med &= ~job.flag
+ job_civilian_high &= ~job.flag
+
+ switch(level)
+ if (1)
+ job_civilian_high |= job.flag
+ if (2)
+ job_civilian_med |= job.flag
+ if (3)
+ job_civilian_low |= job.flag
+
+ return 1
+ else if (job.department_flag == ENGSEC)
+ job_engsec_low &= ~job.flag
+ job_engsec_med &= ~job.flag
+ job_engsec_high &= ~job.flag
+
+ switch(level)
+ if (1)
+ job_engsec_high |= job.flag
+ if (2)
+ job_engsec_med |= job.flag
+ if (3)
+ job_engsec_low |= job.flag
+
+ return 1
+ else if (job.department_flag == MEDSCI)
+ job_medsci_low &= ~job.flag
+ job_medsci_med &= ~job.flag
+ job_medsci_high &= ~job.flag
+
+ switch(level)
+ if (1)
+ job_medsci_high |= job.flag
+ if (2)
+ job_medsci_med |= job.flag
+ if (3)
+ job_medsci_low |= job.flag
+
+ return 1
+
+ return 0
+
+/datum/preferences/proc/UpdateJobPreference(mob/user, role, desiredLvl)
+ if(!SSjob)
+ return
+ var/datum/job/job = SSjob.GetJob(role)
+
+ if(!job)
+ user << browse(null, "window=mob_occupation")
+ ShowChoices(user)
return
- proc/SetJobPreferenceLevel(datum/job/job, level)
- if (!job)
- return 0
+ if (!isnum(desiredLvl))
+ user << "UpdateJobPreference - desired level was not a number. Please notify coders!"
+ ShowChoices(user)
+ return
- if (level == 1) // to high
- // remove any other job(s) set to high
- job_civilian_med |= job_civilian_high
- job_engsec_med |= job_engsec_high
- job_medsci_med |= job_medsci_high
- job_civilian_high = 0
- job_engsec_high = 0
- job_medsci_high = 0
-
- if (job.department_flag == CIVILIAN)
+ if(role == "Assistant")
+ if(job_civilian_low & job.flag)
job_civilian_low &= ~job.flag
- job_civilian_med &= ~job.flag
- job_civilian_high &= ~job.flag
-
- switch(level)
- if (1)
- job_civilian_high |= job.flag
- if (2)
- job_civilian_med |= job.flag
- if (3)
- job_civilian_low |= job.flag
-
- return 1
- else if (job.department_flag == ENGSEC)
- job_engsec_low &= ~job.flag
- job_engsec_med &= ~job.flag
- job_engsec_high &= ~job.flag
-
- switch(level)
- if (1)
- job_engsec_high |= job.flag
- if (2)
- job_engsec_med |= job.flag
- if (3)
- job_engsec_low |= job.flag
-
- return 1
- else if (job.department_flag == MEDSCI)
- job_medsci_low &= ~job.flag
- job_medsci_med &= ~job.flag
- job_medsci_high &= ~job.flag
-
- switch(level)
- if (1)
- job_medsci_high |= job.flag
- if (2)
- job_medsci_med |= job.flag
- if (3)
- job_medsci_low |= job.flag
-
- return 1
-
- return 0
-
- proc/UpdateJobPreference(mob/user, role, desiredLvl)
- if(!SSjob)
- return
- var/datum/job/job = SSjob.GetJob(role)
-
- if(!job)
- user << browse(null, "window=mob_occupation")
- ShowChoices(user)
- return
-
- if (!isnum(desiredLvl))
- user << "UpdateJobPreference - desired level was not a number. Please notify coders!"
- ShowChoices(user)
- return
-
- if(role == "Assistant")
- if(job_civilian_low & job.flag)
- job_civilian_low &= ~job.flag
- else
- job_civilian_low |= job.flag
- SetChoices(user)
- return 1
-
- SetJobPreferenceLevel(job, desiredLvl)
+ else
+ job_civilian_low |= job.flag
SetChoices(user)
-
return 1
+ SetJobPreferenceLevel(job, desiredLvl)
+ SetChoices(user)
- proc/ResetJobs()
-
- job_civilian_high = 0
- job_civilian_med = 0
- job_civilian_low = 0
-
- job_medsci_high = 0
- job_medsci_med = 0
- job_medsci_low = 0
-
- job_engsec_high = 0
- job_engsec_med = 0
- job_engsec_low = 0
+ return 1
- proc/GetJobDepartment(datum/job/job, level)
- if(!job || !level) return 0
- switch(job.department_flag)
- if(CIVILIAN)
- switch(level)
- if(1)
- return job_civilian_high
- if(2)
- return job_civilian_med
- if(3)
- return job_civilian_low
- if(MEDSCI)
- switch(level)
- if(1)
- return job_medsci_high
- if(2)
- return job_medsci_med
- if(3)
- return job_medsci_low
- if(ENGSEC)
- switch(level)
- if(1)
- return job_engsec_high
- if(2)
- return job_engsec_med
- if(3)
- return job_engsec_low
- return 0
+/datum/preferences/proc/ResetJobs()
- proc/process_link(mob/user, list/href_list)
- if(!istype(user, /mob/new_player)) return
+ job_civilian_high = 0
+ job_civilian_med = 0
+ job_civilian_low = 0
- if(href_list["preference"] == "job")
- switch(href_list["task"])
- if("close")
- user << browse(null, "window=mob_occupation")
- ShowChoices(user)
- if("reset")
- ResetJobs()
- SetChoices(user)
- if("random")
- if(jobban_isbanned(user, "Assistant"))
- userandomjob = 1
- else
- userandomjob = !userandomjob
- SetChoices(user)
- if("setJobLevel")
- UpdateJobPreference(user, href_list["text"], text2num(href_list["level"]))
- else
- SetChoices(user)
- return 1
+ job_medsci_high = 0
+ job_medsci_med = 0
+ job_medsci_low = 0
+ job_engsec_high = 0
+ job_engsec_med = 0
+ job_engsec_low = 0
+
+
+/datum/preferences/proc/GetJobDepartment(datum/job/job, level)
+ if(!job || !level) return 0
+ switch(job.department_flag)
+ if(CIVILIAN)
+ switch(level)
+ if(1)
+ return job_civilian_high
+ if(2)
+ return job_civilian_med
+ if(3)
+ return job_civilian_low
+ if(MEDSCI)
+ switch(level)
+ if(1)
+ return job_medsci_high
+ if(2)
+ return job_medsci_med
+ if(3)
+ return job_medsci_low
+ if(ENGSEC)
+ switch(level)
+ if(1)
+ return job_engsec_high
+ if(2)
+ return job_engsec_med
+ if(3)
+ return job_engsec_low
+ return 0
+
+/datum/preferences/proc/process_link(mob/user, list/href_list)
+ if(!istype(user, /mob/new_player)) return
+
+ if(href_list["jobbancheck"])
+ var/job = sanitizeSQL(href_list["jobbancheck"])
+ var/sql_ckey = sanitizeSQL(user.ckey)
+ var/DBQuery/query_get_jobban = dbcon.NewQuery("SELECT reason, bantime, duration, expiration_time, a_ckey FROM [format_table_name("ban")] WHERE ckey = '[sql_ckey]' AND job = '[job]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
+ if(!query_get_jobban.Execute())
+ var/err = query_get_jobban.ErrorMsg()
+ log_game("SQL ERROR obtaining reason from ban table. Error : \[[err]\]\n")
+ return
+ if(query_get_jobban.NextRow())
+ var/reason = query_get_jobban.item[1]
+ var/bantime = query_get_jobban.item[2]
+ var/duration = query_get_jobban.item[3]
+ var/expiration_time = query_get_jobban.item[4]
+ var/a_ckey = query_get_jobban.item[5]
+ var/text
+ text = "You, or another user of this computer, ([user.ckey]) is banned from playing [job]. The ban reason is: [reason] This ban was applied by [a_ckey] on [bantime]"
+ if(text2num(duration) > 0)
+ text += ". The ban is for [duration] minutes and expires on [expiration_time] (server time)"
+ text += "."
+ user << text
+ return
+
+ if(href_list["preference"] == "job")
switch(href_list["task"])
+ if("close")
+ user << browse(null, "window=mob_occupation")
+ ShowChoices(user)
+ if("reset")
+ ResetJobs()
+ SetChoices(user)
if("random")
- switch(href_list["preference"])
- if("name")
- real_name = pref_species.random_name(gender,1)
- if("age")
- age = rand(AGE_MIN, AGE_MAX)
- if("hair")
- hair_color = random_short_color()
- if("hair_style")
- hair_style = random_hair_style(gender)
- if("facial")
- facial_hair_color = random_short_color()
- if("facial_hair_style")
- facial_hair_style = random_facial_hair_style(gender)
- if("underwear")
- underwear = random_underwear(gender)
- if("undershirt")
- undershirt = random_undershirt(gender)
- if("socks")
- socks = random_socks(gender)
- if("eyes")
- eye_color = random_eye_color()
- if("s_tone")
- skin_tone = random_skin_tone()
- if("bag")
- backbag = rand(1,2)
- if("all")
- random_character()
-
- if("input")
- switch(href_list["preference"])
- if("ghostform")
- if(unlock_content)
- var/new_form = input(user, "Thanks for supporting BYOND - Choose your ghostly form:","Thanks for supporting BYOND",null) as null|anything in ghost_forms
- if(new_form)
- ghost_form = new_form
- if("name")
- var/new_name = reject_bad_name( input(user, "Choose your character's name:", "Character Preference") as text|null )
- if(new_name)
- real_name = new_name
- else
- user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and ."
-
- if("age")
- var/new_age = input(user, "Choose your character's age:\n([AGE_MIN]-[AGE_MAX])", "Character Preference") as num|null
- if(new_age)
- age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN)
-
- if("metadata")
- var/new_metadata = input(user, "Enter any information you'd like others to see, such as Roleplay-preferences:", "Game Preference" , metadata) as message|null
- if(new_metadata)
- metadata = sanitize(copytext(new_metadata,1,MAX_MESSAGE_LEN))
-
- if("hair")
- var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference") as null|color
- if(new_hair)
- hair_color = sanitize_hexcolor(new_hair)
-
-
- if("hair_style")
- var/new_hair_style
- if(gender == MALE)
- new_hair_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in hair_styles_male_list
- else
- new_hair_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in hair_styles_female_list
- if(new_hair_style)
- hair_style = new_hair_style
-
- if("next_hair_style")
- if (gender == MALE)
- hair_style = next_list_item(hair_style, hair_styles_male_list)
- else
- hair_style = next_list_item(hair_style, hair_styles_female_list)
-
- if("previous_hair_style")
- if (gender == MALE)
- hair_style = previous_list_item(hair_style, hair_styles_male_list)
- else
- hair_style = previous_list_item(hair_style, hair_styles_female_list)
-
- if("facial")
- var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference") as null|color
- if(new_facial)
- facial_hair_color = sanitize_hexcolor(new_facial)
-
- if("facial_hair_style")
- var/new_facial_hair_style
- if(gender == MALE)
- new_facial_hair_style = input(user, "Choose your character's facial-hair style:", "Character Preference") as null|anything in facial_hair_styles_male_list
- else
- new_facial_hair_style = input(user, "Choose your character's facial-hair style:", "Character Preference") as null|anything in facial_hair_styles_female_list
- if(new_facial_hair_style)
- facial_hair_style = new_facial_hair_style
-
- if("next_facehair_style")
- if (gender == MALE)
- facial_hair_style = next_list_item(facial_hair_style, facial_hair_styles_male_list)
- else
- facial_hair_style = next_list_item(facial_hair_style, facial_hair_styles_female_list)
-
- if("previous_facehair_style")
- if (gender == MALE)
- facial_hair_style = previous_list_item(facial_hair_style, facial_hair_styles_male_list)
- else
- facial_hair_style = previous_list_item(facial_hair_style, facial_hair_styles_female_list)
-
- if("underwear")
- var/new_underwear
- if(gender == MALE)
- new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in underwear_m
- else
- new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in underwear_f
- if(new_underwear)
- underwear = new_underwear
-
- if("undershirt")
- var/new_undershirt
- if(gender == MALE)
- new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in undershirt_m
- else
- new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in undershirt_f
- if(new_undershirt)
- undershirt = new_undershirt
-
- if("socks")
- var/new_socks
- if(gender == MALE)
- new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in socks_m
- else
- new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in socks_f
- if(new_socks)
- socks = new_socks
-
- if("eyes")
- var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference") as color|null
- if(new_eyes)
- eye_color = sanitize_hexcolor(new_eyes)
-
- if("species")
-
- var/result = input(user, "Select a species", "Species Selection") as null|anything in roundstart_species
-
- if(result)
- var/newtype = roundstart_species[result]
- pref_species = new newtype()
- //Now that we changed our species, we must verify that the mutant colour is still allowed.
- var/temp_hsv = RGBtoHSV(features["mcolor"])
- if(features["mcolor"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.specflags) && ReadHSV(temp_hsv)[3] < ReadHSV("#7F7F7F")[3]))
- features["mcolor"] = pref_species.default_color
- if("mutant_color")
- var/new_mutantcolor = input(user, "Choose your character's alien/mutant color:", "Character Preference") as color|null
- if(new_mutantcolor)
- var/temp_hsv = RGBtoHSV(new_mutantcolor)
- if(new_mutantcolor == "#000000")
- features["mcolor"] = pref_species.default_color
- else if((MUTCOLORS_PARTSONLY in pref_species.specflags) || ReadHSV(temp_hsv)[3] >= ReadHSV("#7F7F7F")[3]) // mutantcolors must be bright, but only if they affect the skin
- features["mcolor"] = sanitize_hexcolor(new_mutantcolor)
- else
- user << "Invalid color. Your color is not bright enough."
-
- if("tail_lizard")
- var/new_tail
- new_tail = input(user, "Choose your character's tail:", "Character Preference") as null|anything in tails_list_lizard
- if(new_tail)
- features["tail_lizard"] = new_tail
-
- if("tail_human")
- var/new_tail
- new_tail = input(user, "Choose your character's tail:", "Character Preference") as null|anything in tails_list_human
- if(new_tail)
- features["tail_human"] = new_tail
-
- if("snout")
- var/new_snout
- new_snout = input(user, "Choose your character's snout:", "Character Preference") as null|anything in snouts_list
- if(new_snout)
- features["snout"] = new_snout
-
- if("horns")
- var/new_horns
- new_horns = input(user, "Choose your character's horns:", "Character Preference") as null|anything in horns_list
- if(new_horns)
- features["horns"] = new_horns
-
- if("ears")
- var/new_ears
- new_ears = input(user, "Choose your character's ears:", "Character Preference") as null|anything in ears_list
- if(new_ears)
- features["ears"] = new_ears
-
- if("frills")
- var/new_frills
- new_frills = input(user, "Choose your character's frills:", "Character Preference") as null|anything in frills_list
- if(new_frills)
- features["frills"] = new_frills
-
- if("spines")
- var/new_spines
- new_spines = input(user, "Choose your character's spines:", "Character Preference") as null|anything in spines_list
- if(new_spines)
- features["spines"] = new_spines
-
- if("body_markings")
- var/new_body_markings
- new_body_markings = input(user, "Choose your character's body markings:", "Character Preference") as null|anything in body_markings_list
- if(new_body_markings)
- features["body_markings"] = new_body_markings
-
- if("s_tone")
- var/new_s_tone = input(user, "Choose your character's skin-tone:", "Character Preference") as null|anything in skin_tones
- if(new_s_tone)
- skin_tone = new_s_tone
-
- if("ooccolor")
- var/new_ooccolor = input(user, "Choose your OOC colour:", "Game Preference") as color|null
- if(new_ooccolor)
- ooccolor = sanitize_ooccolor(new_ooccolor)
-
- if("bag")
- var/new_backbag = input(user, "Choose your character's style of bag:", "Character Preference") as null|anything in backbaglist
- if(new_backbag)
- backbag = backbaglist.Find(new_backbag)
-
- if("clown_name")
- var/new_clown_name = reject_bad_name( input(user, "Choose your character's clown name:", "Character Preference") as text|null )
- if(new_clown_name)
- custom_names["clown"] = new_clown_name
- else
- user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and ."
-
- if("mime_name")
- var/new_mime_name = reject_bad_name( input(user, "Choose your character's mime name:", "Character Preference") as text|null )
- if(new_mime_name)
- custom_names["mime"] = new_mime_name
- else
- user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and ."
-
- if("ai_name")
- var/new_ai_name = reject_bad_name( input(user, "Choose your character's AI name:", "Character Preference") as text|null, 1 )
- if(new_ai_name)
- custom_names["ai"] = new_ai_name
- else
- user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, 0-9, -, ' and ."
-
- if("cyborg_name")
- var/new_cyborg_name = reject_bad_name( input(user, "Choose your character's cyborg name:", "Character Preference") as text|null, 1 )
- if(new_cyborg_name)
- custom_names["cyborg"] = new_cyborg_name
- else
- user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, 0-9, -, ' and ."
-
- if("religion_name")
- var/new_religion_name = reject_bad_name( input(user, "Choose your character's religion:", "Character Preference") as text|null )
- if(new_religion_name)
- custom_names["religion"] = new_religion_name
- else
- user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and ."
-
- if("deity_name")
- var/new_deity_name = reject_bad_name( input(user, "Choose your character's deity:", "Character Preference") as text|null )
- if(new_deity_name)
- custom_names["deity"] = new_deity_name
- else
- user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and ."
-
-
+ if(jobban_isbanned(user, "Assistant"))
+ userandomjob = 1
+ else
+ userandomjob = !userandomjob
+ SetChoices(user)
+ if("setJobLevel")
+ UpdateJobPreference(user, href_list["text"], text2num(href_list["level"]))
else
- switch(href_list["preference"])
- if("publicity")
- if(unlock_content)
- toggles ^= MEMBER_PUBLIC
- if("gender")
- if(gender == MALE)
- gender = FEMALE
+ SetChoices(user)
+ return 1
+
+ switch(href_list["task"])
+ if("random")
+ switch(href_list["preference"])
+ if("name")
+ real_name = pref_species.random_name(gender,1)
+ if("age")
+ age = rand(AGE_MIN, AGE_MAX)
+ if("hair")
+ hair_color = random_short_color()
+ if("hair_style")
+ hair_style = random_hair_style(gender)
+ if("facial")
+ facial_hair_color = random_short_color()
+ if("facial_hair_style")
+ facial_hair_style = random_facial_hair_style(gender)
+ if("underwear")
+ underwear = random_underwear(gender)
+ if("undershirt")
+ undershirt = random_undershirt(gender)
+ if("socks")
+ socks = random_socks(gender)
+ if("eyes")
+ eye_color = random_eye_color()
+ if("s_tone")
+ skin_tone = random_skin_tone()
+ if("bag")
+ backbag = rand(1,2)
+ if("all")
+ random_character()
+
+ if("input")
+ switch(href_list["preference"])
+ if("ghostform")
+ if(unlock_content)
+ var/new_form = input(user, "Thanks for supporting BYOND - Choose your ghostly form:","Thanks for supporting BYOND",null) as null|anything in ghost_forms
+ if(new_form)
+ ghost_form = new_form
+ if("name")
+ var/new_name = reject_bad_name( input(user, "Choose your character's name:", "Character Preference") as text|null )
+ if(new_name)
+ real_name = new_name
+ else
+ user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and ."
+
+ if("age")
+ var/new_age = input(user, "Choose your character's age:\n([AGE_MIN]-[AGE_MAX])", "Character Preference") as num|null
+ if(new_age)
+ age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN)
+
+ if("metadata")
+ var/new_metadata = input(user, "Enter any information you'd like others to see, such as Roleplay-preferences:", "Game Preference" , metadata) as message|null
+ if(new_metadata)
+ metadata = sanitize(copytext(new_metadata,1,MAX_MESSAGE_LEN))
+
+ if("hair")
+ var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference") as null|color
+ if(new_hair)
+ hair_color = sanitize_hexcolor(new_hair)
+
+
+ if("hair_style")
+ var/new_hair_style
+ if(gender == MALE)
+ new_hair_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in hair_styles_male_list
+ else
+ new_hair_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in hair_styles_female_list
+ if(new_hair_style)
+ hair_style = new_hair_style
+
+ if("next_hair_style")
+ if (gender == MALE)
+ hair_style = next_list_item(hair_style, hair_styles_male_list)
+ else
+ hair_style = next_list_item(hair_style, hair_styles_female_list)
+
+ if("previous_hair_style")
+ if (gender == MALE)
+ hair_style = previous_list_item(hair_style, hair_styles_male_list)
+ else
+ hair_style = previous_list_item(hair_style, hair_styles_female_list)
+
+ if("facial")
+ var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference") as null|color
+ if(new_facial)
+ facial_hair_color = sanitize_hexcolor(new_facial)
+
+ if("facial_hair_style")
+ var/new_facial_hair_style
+ if(gender == MALE)
+ new_facial_hair_style = input(user, "Choose your character's facial-hair style:", "Character Preference") as null|anything in facial_hair_styles_male_list
+ else
+ new_facial_hair_style = input(user, "Choose your character's facial-hair style:", "Character Preference") as null|anything in facial_hair_styles_female_list
+ if(new_facial_hair_style)
+ facial_hair_style = new_facial_hair_style
+
+ if("next_facehair_style")
+ if (gender == MALE)
+ facial_hair_style = next_list_item(facial_hair_style, facial_hair_styles_male_list)
+ else
+ facial_hair_style = next_list_item(facial_hair_style, facial_hair_styles_female_list)
+
+ if("previous_facehair_style")
+ if (gender == MALE)
+ facial_hair_style = previous_list_item(facial_hair_style, facial_hair_styles_male_list)
+ else
+ facial_hair_style = previous_list_item(facial_hair_style, facial_hair_styles_female_list)
+
+ if("underwear")
+ var/new_underwear
+ if(gender == MALE)
+ new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in underwear_m
+ else
+ new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in underwear_f
+ if(new_underwear)
+ underwear = new_underwear
+
+ if("undershirt")
+ var/new_undershirt
+ if(gender == MALE)
+ new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in undershirt_m
+ else
+ new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in undershirt_f
+ if(new_undershirt)
+ undershirt = new_undershirt
+
+ if("socks")
+ var/new_socks
+ if(gender == MALE)
+ new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in socks_m
+ else
+ new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in socks_f
+ if(new_socks)
+ socks = new_socks
+
+ if("eyes")
+ var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference") as color|null
+ if(new_eyes)
+ eye_color = sanitize_hexcolor(new_eyes)
+
+ if("species")
+
+ var/result = input(user, "Select a species", "Species Selection") as null|anything in roundstart_species
+
+ if(result)
+ var/newtype = roundstart_species[result]
+ pref_species = new newtype()
+ //Now that we changed our species, we must verify that the mutant colour is still allowed.
+ var/temp_hsv = RGBtoHSV(features["mcolor"])
+ if(features["mcolor"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.specflags) && ReadHSV(temp_hsv)[3] < ReadHSV("#7F7F7F")[3]))
+ features["mcolor"] = pref_species.default_color
+ if("mutant_color")
+ var/new_mutantcolor = input(user, "Choose your character's alien/mutant color:", "Character Preference") as color|null
+ if(new_mutantcolor)
+ var/temp_hsv = RGBtoHSV(new_mutantcolor)
+ if(new_mutantcolor == "#000000")
+ features["mcolor"] = pref_species.default_color
+ else if((MUTCOLORS_PARTSONLY in pref_species.specflags) || ReadHSV(temp_hsv)[3] >= ReadHSV("#7F7F7F")[3]) // mutantcolors must be bright, but only if they affect the skin
+ features["mcolor"] = sanitize_hexcolor(new_mutantcolor)
else
- gender = MALE
- underwear = random_underwear(gender)
- undershirt = random_undershirt(gender)
- socks = random_socks(gender)
- facial_hair_style = random_facial_hair_style(gender)
- hair_style = random_hair_style(gender)
+ user << "Invalid color. Your color is not bright enough."
- if("hear_adminhelps")
- toggles ^= SOUND_ADMINHELP
+ if("tail_lizard")
+ var/new_tail
+ new_tail = input(user, "Choose your character's tail:", "Character Preference") as null|anything in tails_list_lizard
+ if(new_tail)
+ features["tail_lizard"] = new_tail
- if("ui")
- switch(UI_style)
- if("Midnight")
- UI_style = "Plasmafire"
- if("Plasmafire")
- UI_style = "Retro"
- else
- UI_style = "Midnight"
+ if("tail_human")
+ var/new_tail
+ new_tail = input(user, "Choose your character's tail:", "Character Preference") as null|anything in tails_list_human
+ if(new_tail)
+ features["tail_human"] = new_tail
- if("be_special")
- var/num = text2num(href_list["num"])
- be_special ^= (1<Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and ."
+
+ if("mime_name")
+ var/new_mime_name = reject_bad_name( input(user, "Choose your character's mime name:", "Character Preference") as text|null )
+ if(new_mime_name)
+ custom_names["mime"] = new_mime_name
+ else
+ user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and ."
+
+ if("ai_name")
+ var/new_ai_name = reject_bad_name( input(user, "Choose your character's AI name:", "Character Preference") as text|null, 1 )
+ if(new_ai_name)
+ custom_names["ai"] = new_ai_name
+ else
+ user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, 0-9, -, ' and ."
+
+ if("cyborg_name")
+ var/new_cyborg_name = reject_bad_name( input(user, "Choose your character's cyborg name:", "Character Preference") as text|null, 1 )
+ if(new_cyborg_name)
+ custom_names["cyborg"] = new_cyborg_name
+ else
+ user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, 0-9, -, ' and ."
+
+ if("religion_name")
+ var/new_religion_name = reject_bad_name( input(user, "Choose your character's religion:", "Character Preference") as text|null )
+ if(new_religion_name)
+ custom_names["religion"] = new_religion_name
+ else
+ user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and ."
+
+ if("deity_name")
+ var/new_deity_name = reject_bad_name( input(user, "Choose your character's deity:", "Character Preference") as text|null )
+ if(new_deity_name)
+ custom_names["deity"] = new_deity_name
+ else
+ user << "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and ."
+
+
+ else
+ switch(href_list["preference"])
+ if("publicity")
+ if(unlock_content)
+ toggles ^= MEMBER_PUBLIC
+ if("gender")
+ if(gender == MALE)
+ gender = FEMALE
+ else
+ gender = MALE
+ underwear = random_underwear(gender)
+ undershirt = random_undershirt(gender)
+ socks = random_socks(gender)
+ facial_hair_style = random_facial_hair_style(gender)
+ hair_style = random_hair_style(gender)
+
+ if("hear_adminhelps")
+ toggles ^= SOUND_ADMINHELP
+ if("announce_login")
+ toggles ^= ANNOUNCE_LOGIN
+
+ if("ui")
+ switch(UI_style)
+ if("Midnight")
+ UI_style = "Plasmafire"
+ if("Plasmafire")
+ UI_style = "Retro"
else
- user.stopLobbySound()
+ UI_style = "Midnight"
- if("ghost_ears")
- chat_toggles ^= CHAT_GHOSTEARS
+ if("be_special")
+ var/num = text2num(href_list["num"])
+ be_special ^= (1<0, i--)
+ sec_briefcase.handle_item_insertion(new /obj/item/stack/spacecash/c1000,1)
+ sec_briefcase.handle_item_insertion(new /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow,1)
+ sec_briefcase.handle_item_insertion(new /obj/item/weapon/gun/projectile/revolver/mateba,1)
+ sec_briefcase.handle_item_insertion(new /obj/item/ammo_box/a357,1)
+ sec_briefcase.handle_item_insertion(new /obj/item/weapon/c4,1)
+
+ var/obj/item/device/pda/heads/pda = H.belt
+ pda.owner = H.real_name
+ pda.ownjob = "Reaper"
+ pda.update_label()
+
+ var/obj/item/weapon/card/id/syndicate/W = H.wear_id
+ W.access = get_all_accesses()
+ W.assignment = "Reaper"
+ W.registered_name = H.real_name
+ W.update_label(H.real_name)
+
+/datum/outfit/centcom_commander
+ name = "Centcom Commander"
+
+ uniform = /obj/item/clothing/under/rank/centcom_commander
+ suit = /obj/item/clothing/suit/armor/bulletproof
+ shoes = /obj/item/clothing/shoes/combat/swat
+ gloves = /obj/item/clothing/gloves/combat
+ ears = /obj/item/device/radio/headset/headset_cent/commander
+ glasses = /obj/item/clothing/glasses/eyepatch
+ mask = /obj/item/clothing/mask/cigarette/cigar/cohiba
+ head = /obj/item/clothing/head/centhat
+ belt = /obj/item/weapon/gun/projectile/revolver/mateba
+ r_pocket = /obj/item/weapon/lighter
+ l_pocket = /obj/item/ammo_box/a357
+ back = /obj/item/weapon/storage/backpack/satchel
+ id = /obj/item/weapon/card/id
+
+/datum/outfit/centcom_commander/post_equip(mob/living/carbon/human/H)
+ var/obj/item/weapon/card/id/W = H.wear_id
+ W.icon_state = "centcom"
+ W.access = get_all_accesses()
+ W.access += get_centcom_access("Centcom Commander")
+ W.assignment = "Centcom Commander"
+ W.registered_name = H.real_name
+ W.update_label()
+
+/datum/outfit/spec_ops
+ name = "Special Ops Officer"
+
+ uniform = /obj/item/clothing/under/syndicate
+ suit = /obj/item/clothing/suit/space/officer
+ shoes = /obj/item/clothing/shoes/combat/swat
+ gloves = /obj/item/clothing/gloves/combat
+ glasses = /obj/item/clothing/glasses/thermal/eyepatch
+ ears = /obj/item/device/radio/headset/headset_cent/commander
+ mask = /obj/item/clothing/mask/cigarette/cigar/havana
+ head = /obj/item/clothing/head/helmet/space/beret
+ belt = /obj/item/weapon/gun/energy/pulse/pistol/m1911
+ r_pocket = /obj/item/weapon/lighter
+ back = /obj/item/weapon/storage/backpack/satchel
+ id = /obj/item/weapon/card/id
+
+/datum/outfit/spec_ops/post_equip(mob/living/carbon/human/H)
+ var/obj/item/weapon/card/id/W = H.wear_id
+ W.icon_state = "centcom"
+ W.access = get_all_accesses()
+ W.access += get_centcom_access("Special Ops Officer")
+ W.assignment = "Special Ops Officer"
+ W.registered_name = H.real_name
+ W.update_label()
+
+ var/obj/item/device/radio/headset/R = H.ears
+ R.set_frequency(CENTCOM_FREQ)
+ R.freqlock = 1
+
+/datum/outfit/wizard
+ name = "Blue Wizard"
+
+ uniform = /obj/item/clothing/under/color/lightpurple
+ suit = /obj/item/clothing/suit/wizrobe
+ shoes = /obj/item/clothing/shoes/sandal
+ ears = /obj/item/device/radio/headset
+ head = /obj/item/clothing/head/wizard
+ r_pocket = /obj/item/weapon/teleportation_scroll
+ r_hand = /obj/item/weapon/spellbook
+ l_hand = /obj/item/weapon/staff
+ back = /obj/item/weapon/storage/backpack
+ backpack_contents = list(/obj/item/weapon/storage/box=1)
+
+/datum/outfit/wizard/red
+ name = "Red Wizard"
+
+ suit = /obj/item/clothing/suit/wizrobe/red
+ head = /obj/item/clothing/head/wizard/red
+
+/datum/outfit/wizard/weeb
+ name = "Marisa Wizard"
+
+ suit = /obj/item/clothing/suit/wizrobe/marisa
+ shoes = /obj/item/clothing/shoes/sandal/marisa
+ head = /obj/item/clothing/head/wizard/marisa
+
+/datum/outfit/soviet
+ name = "Soviet Admiral"
+
+ uniform = /obj/item/clothing/under/soviet
+ head = /obj/item/clothing/head/hgpiratecap
+ shoes = /obj/item/clothing/shoes/combat
+ gloves = /obj/item/clothing/gloves/combat
+ ears = /obj/item/device/radio/headset/headset_cent
+ glasses = /obj/item/clothing/glasses/thermal/eyepatch
+ suit = /obj/item/clothing/suit/hgpirate
+ back = /obj/item/weapon/storage/backpack/satchel
+ belt = /obj/item/weapon/gun/projectile/revolver/mateba
+
+ id = /obj/item/weapon/card/id
+
+/datum/outfit/soviet/post_equip(mob/living/carbon/human/H)
+ var/obj/item/weapon/card/id/W = H.wear_id
+ W.icon_state = "centcom"
+ W.access = get_all_accesses()
+ W.access += get_centcom_access("Admiral")
+ W.assignment = "Admiral"
+ W.registered_name = H.real_name
+ W.update_label()
+
+/datum/outfit/mobster
+ name = "Mobster"
+
+ uniform = /obj/item/clothing/under/suit_jacket/really_black
+ head = /obj/item/clothing/head/fedora
+ shoes = /obj/item/clothing/shoes/laceup
+ gloves = /obj/item/clothing/gloves/color/black
+ ears = /obj/item/device/radio/headset
+ glasses = /obj/item/clothing/glasses/sunglasses
+ r_hand = /obj/item/weapon/gun/projectile/automatic/tommygun
+ id = /obj/item/weapon/card/id
+
+/datum/outfit/mobster/post_equip(mob/living/carbon/human/H)
+ var/obj/item/weapon/card/id/W = H.wear_id
+ W.assignment = "Assistant"
+ W.registered_name = H.real_name
+ W.update_label()
+
+/datum/outfit/plasmaman
+ name = "Plasmaman"
+
+ head = /obj/item/clothing/head/helmet/space/hardsuit/plasmaman
+ suit = /obj/item/clothing/suit/space/eva/plasmaman
+ back = /obj/item/weapon/tank/internals/plasmaman/full
+ mask = /obj/item/clothing/mask/breath
+
+/datum/outfit/death_commando
+ name = "Death Commando"
+
+ uniform = /obj/item/clothing/under/color/green
+ suit = /obj/item/clothing/suit/space/hardsuit/deathsquad
+ shoes = /obj/item/clothing/shoes/combat/swat
+ gloves = /obj/item/clothing/gloves/combat
+ mask = /obj/item/clothing/mask/gas/sechailer/swat
+ glasses = /obj/item/clothing/glasses/hud/toggle/thermal
+ back = /obj/item/weapon/storage/backpack/security
+ l_pocket = /obj/item/weapon/melee/energy/sword/saber
+ r_pocket = /obj/item/weapon/shield/energy
+ suit_store = /obj/item/weapon/tank/internals/emergency_oxygen
+ belt = /obj/item/weapon/gun/projectile/revolver/mateba
+ r_hand = /obj/item/weapon/gun/energy/pulse/loyalpin
+ id = /obj/item/weapon/card/id
+ ears = /obj/item/device/radio/headset/headset_cent/alt
+
+ backpack_contents = list(/obj/item/weapon/storage/box=1,\
+ /obj/item/ammo_box/a357=1,\
+ /obj/item/weapon/storage/firstaid/regular=1,\
+ /obj/item/weapon/storage/box/flashbangs=1,\
+ /obj/item/device/flashlight=1,\
+ /obj/item/weapon/c4=1)
+
+/datum/outfit/death_commando/post_equip(mob/living/carbon/human/H)
+ var/obj/item/device/radio/R = H.ears
+ R.set_frequency(CENTCOM_FREQ)
+ R.freqlock = 1
+
+ var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)//Here you go Deuryn
+ L.imp_in = H
+ L.implanted = 1
+ H.sec_hud_set_implants()
+
+
+ var/obj/item/weapon/card/id/W = H.wear_id
+ W.icon_state = "centcom"
+ W.access = get_all_accesses()//They get full station access.
+ W.access += get_centcom_access("Death Commando")//Let's add their alloted Centcom access.
+ W.assignment = "Death Commando"
+ W.registered_name = H.real_name
+ W.update_label(W.registered_name, W.assignment)
+
+/datum/outfit/death_commando/officer
+ name = "Death Commando Officer"
+ head = /obj/item/clothing/head/helmet/space/beret
+
+
+
+
+
\ No newline at end of file
diff --git a/code/modules/clothing/shoes/bananashoes.dm b/code/modules/clothing/shoes/bananashoes.dm
index 8ecc971b7dd..a51af2db1b4 100644
--- a/code/modules/clothing/shoes/bananashoes.dm
+++ b/code/modules/clothing/shoes/bananashoes.dm
@@ -37,13 +37,17 @@
user << "You cannot retrieve any bananium from the prototype shoes."
/obj/item/clothing/shoes/clown_shoes/banana_shoes/attackby(obj/item/O, mob/user, params)
- if(!bananium.can_insert(O))
+ if(!istype(O,/obj/item/stack/sheet))
+ return
+ if(!bananium.get_item_material_amount(O))
user << "This item has no bananium!"
return
if(!user.unEquip(O))
user << "You can't drop [O]!"
return
- var/sheet_amount = bananium.insert_stack(O)
+
+ var/obj/item/stack/sheet/S = O
+ var/sheet_amount = bananium.insert_stack(O,S.amount)
if(sheet_amount)
user << "You insert [sheet_amount] bananium sheets into the prototype shoes."
else
diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm
index 7759f4bd7e6..c42f252bc26 100644
--- a/code/modules/clothing/shoes/magboots.dm
+++ b/code/modules/clothing/shoes/magboots.dm
@@ -9,6 +9,7 @@
strip_delay = 70
put_on_delay = 70
burn_state = -1 //Won't burn in fires
+ origin_tech = "magnets=2"
/obj/item/clothing/shoes/magboots/verb/toggle()
set name = "Toggle Magboots"
@@ -52,3 +53,4 @@
name = "blood-red magboots"
icon_state = "syndiemag0"
magboot_state = "syndiemag"
+ origin_tech = "magnets=2,syndicate=3"
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index 58101dca40a..097f1c6985d 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -62,6 +62,16 @@
put_on_delay = 50
burn_state = -1 //Won't burn in fires
+/obj/item/clothing/shoes/galoshes/dry
+ name = "absorbent galoshes"
+ desc = "A pair of orange rubber boots, designed to prevent slipping on wet surfaces while also drying them."
+ icon_state = "galoshes_dry"
+
+/obj/item/clothing/shoes/galoshes/dry/step_action()
+ var/turf/simulated/t_loc = get_turf(src)
+ if(istype(t_loc) && t_loc.wet)
+ t_loc.MakeDry(TURF_WET_WATER)
+
/obj/item/clothing/shoes/clown_shoes
desc = "The prankster's standard-issue clowning shoes. Damn, they're huge!"
name = "clown shoes"
@@ -107,7 +117,7 @@
put_on_delay = 40
/obj/item/clothing/shoes/cult
- name = "cultist boots"
+ name = "nar-sian invoker boots"
desc = "A pair of boots worn by the followers of Nar-Sie."
icon_state = "cult"
item_state = "cult"
@@ -117,6 +127,10 @@
heat_protection = FEET
max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT
+/obj/item/clothing/shoes/cult/alt
+ name = "cultist boots"
+ icon_state = "cultalt"
+
/obj/item/clothing/shoes/cyborg
name = "cyborg boots"
desc = "Shoes for a cyborg costume."
diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm
index 9e0b55df4cb..a8048ec3f6d 100644
--- a/code/modules/clothing/spacesuits/chronosuit.dm
+++ b/code/modules/clothing/spacesuits/chronosuit.dm
@@ -14,7 +14,7 @@
/obj/item/clothing/head/helmet/space/chronos/Destroy()
dropped()
- ..()
+ return ..()
/obj/item/clothing/suit/space/chronos
@@ -55,7 +55,7 @@
/obj/item/clothing/suit/space/chronos/Destroy()
dropped()
- ..()
+ return ..()
/obj/item/clothing/suit/space/chronos/emp_act(severity)
var/mob/living/carbon/human/user = src.loc
@@ -216,5 +216,5 @@
holder.remote_control = null
if(holder.client && (holder.client.eye == src))
holder.client.eye = holder
- ..()
+ return ..()
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 06bdfc347d6..008db1709f0 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -10,6 +10,7 @@
var/basestate = "hardsuit"
var/brightness_on = 4 //luminosity when on
var/on = 0
+ var/obj/item/clothing/suit/space/hardsuit/suit
item_color = "engineering" //Determines used sprites: hardsuit[on]-[color] and hardsuit[on]-[color]2 (lying down sprite)
action_button_name = "Toggle Helmet Light"
flags = BLOCKHAIR | STOPSPRESSUREDMAGE | THICKMATERIAL | NODROP
@@ -269,7 +270,7 @@
item_state = "wiz_helm"
item_color = "wiz"
unacidable = 1 //No longer shall our kind be foiled by lone chemists with spray bottles!
- armor = list(melee = 40, bullet = 20, laser = 20, energy = 20, bomb = 35, bio = 100, rad = 50)
+ armor = list(melee = 40, bullet = 40, laser = 40, energy = 20, bomb = 35, bio = 100, rad = 50)
heat_protection = HEAD //Uncomment to enable firesuit protection
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
unacidable = 1
@@ -283,7 +284,7 @@
slowdown = 1
w_class = 3
unacidable = 1
- armor = list(melee = 40, bullet = 20, laser = 20, energy = 20, bomb = 35, bio = 100, rad = 50)
+ armor = list(melee = 40, bullet = 40, laser = 40, energy = 20, bomb = 35, bio = 100, rad = 50)
allowed = list(/obj/item/weapon/teleportation_scroll,/obj/item/weapon/tank/internals)
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS //Uncomment to enable firesuit protection
max_heat_protection_temperature = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index 71f6d7058f7..1386e7d9b0d 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -40,7 +40,7 @@ Contains:
desc = "That's not red paint. That's real blood."
icon_state = "deathsquad"
item_state = "deathsquad"
- armor = list(melee = 50, bullet = 40, laser = 30, energy = 50, bomb = 50, bio = 100, rad = 100)
+ armor = list(melee = 80, bullet = 80, laser = 50, energy = 50, bomb = 100, bio = 100, rad = 100)
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
unacidable = 1
@@ -55,7 +55,7 @@ Contains:
icon_state = "deathsquad"
item_state = "swat_suit"
allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/tank/internals)
- armor = list(melee = 50, bullet = 40, laser = 30,energy = 50, bomb = 50, bio = 100, rad = 100)
+ armor = list(melee = 80, bullet = 80, laser = 50, energy = 50, bomb = 100, bio = 100, rad = 100)
slowdown = 1
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
@@ -68,7 +68,7 @@ Contains:
icon_state = "beret_badge"
flags = STOPSPRESSUREDMAGE
flags_inv = 0
- armor = list(melee = 50, bullet = 40, laser = 30, energy = 50, bomb = 50, bio = 100, rad = 100)
+ armor = list(melee = 80, bullet = 80, laser = 50, energy = 50, bomb = 100, bio = 100, rad = 100)
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
unacidable = 1
@@ -83,7 +83,7 @@ Contains:
flags_inv = 0
w_class = 3
allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/tank/internals)
- armor = list(melee = 50, bullet = 40, laser = 30,energy = 50, bomb = 50, bio = 100, rad = 100)
+ armor = list(melee = 80, bullet = 80, laser = 50, energy = 50, bomb = 100, bio = 100, rad = 100)
slowdown = 1
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index d8dc137f797..59639c9f15b 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -70,6 +70,11 @@
body_parts_covered = CHEST|GROIN
armor = list(melee = 50, bullet = 40, laser = 50, energy = 10, bomb = 25, bio = 0, rad = 0)
+/obj/item/clothing/suit/armor/vest/capcarapace/alt
+ name = "captain's parade jacket"
+ desc = "For when an armoured vest isn't fashionable enough."
+ icon_state = "capformal"
+ item_state = "capspacesuit"
/obj/item/clothing/suit/armor/riot
name = "riot suit"
@@ -105,7 +110,7 @@
/obj/item/clothing/suit/armor/laserproof/IsReflect(def_zone)
if(!(def_zone in list("chest", "groin"))) //If not shot where ablative is covering you, you don't get the reflection bonus!
- hit_reflect_chance = 0
+ return 0
if (prob(hit_reflect_chance))
return 1
@@ -122,7 +127,7 @@
/obj/item/clothing/suit/armor/reactive
name = "reactive teleport armor"
desc = "Someone seperated our Research Director from his own head!"
- var/active = 0.0
+ var/active = 0
icon_state = "reactiveoff"
item_state = "reactiveoff"
blood_overlay_type = "armor"
diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm
index 093b14d0a1f..25a5a906837 100644
--- a/code/modules/clothing/suits/bio.dm
+++ b/code/modules/clothing/suits/bio.dm
@@ -21,7 +21,7 @@
permeability_coefficient = 0.01
flags = THICKMATERIAL
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- slowdown = 1.0
+ slowdown = 1
allowed = list(/obj/item/weapon/tank/internals/emergency_oxygen,/obj/item/weapon/pen,/obj/item/device/flashlight/pen)
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20)
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
@@ -48,9 +48,11 @@
//Security biosuit, grey with red stripe across the chest
/obj/item/clothing/head/bio_hood/security
+ armor = list(melee = 25, bullet = 15, laser = 25, energy = 10, bomb = 25, bio = 100, rad = 20)
icon_state = "bio_security"
/obj/item/clothing/suit/bio_suit/security
+ armor = list(melee = 25, bullet = 15, laser = 25, energy = 10, bomb = 25, bio = 100, rad = 20)
icon_state = "bio_security"
diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm
index 1ae33b0de80..b58216f30c9 100644
--- a/code/modules/clothing/suits/jobs.dm
+++ b/code/modules/clothing/suits/jobs.dm
@@ -20,7 +20,7 @@
item_state = "bio_suit"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
flags_inv = HIDEJUMPSUIT
- allowed = list(/obj/item/weapon/disk, /obj/item/weapon/stamp, /obj/item/weapon/reagent_containers/food/drinks/flask, /obj/item/weapon/melee, /obj/item/weapon/storage/lockbox/medal, /obj/item/device/flash/handheld, /obj/item/weapon/storage/box/matches, /obj/item/weapon/lighter, /obj/item/clothing/mask/cigarette, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/tank/internals/emergency_oxygen)
+ allowed = list(/obj/item/weapon/disk, /obj/item/weapon/stamp, /obj/item/weapon/reagent_containers/food/drinks/flask, /obj/item/weapon/melee, /obj/item/weapon/storage/lockbox/medal, /obj/item/device/assembly/flash/handheld, /obj/item/weapon/storage/box/matches, /obj/item/weapon/lighter, /obj/item/clothing/mask/cigarette, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/tank/internals/emergency_oxygen)
//Chaplain
/obj/item/clothing/suit/hooded/chaplain_hoodie
diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm
index d8d1f409691..6d7a8390ae3 100644
--- a/code/modules/clothing/suits/toggles.dm
+++ b/code/modules/clothing/suits/toggles.dm
@@ -10,7 +10,7 @@
/obj/item/clothing/suit/hooded/Destroy()
qdel(hood)
- ..()
+ return ..()
/obj/item/clothing/suit/hooded/proc/MakeHood()
if(!hood)
@@ -90,7 +90,6 @@
user << "Alt-click on [src] to toggle the [togglename]."
//Hardsuit toggle code
-
/obj/item/clothing/suit/space/hardsuit/New()
MakeHelmet()
if(!jetpack)
@@ -98,15 +97,24 @@
verbs -= /obj/item/clothing/suit/space/hardsuit/verb/Jetpack_Rockets
..()
/obj/item/clothing/suit/space/hardsuit/Destroy()
- qdel(helmet)
+ if(helmet)
+ helmet.suit = null
+ qdel(helmet)
qdel(jetpack)
- ..()
+ return ..()
+
+/obj/item/clothing/head/helmet/space/hardsuit/Destroy()
+ if(suit)
+ suit.helmet = null
+ qdel(suit)
+ return ..()
/obj/item/clothing/suit/space/hardsuit/proc/MakeHelmet()
if(!helmettype)
return
if(!helmet)
var/obj/item/clothing/head/helmet/space/hardsuit/W = new helmettype(src)
+ W.suit = src
helmet = W
/obj/item/clothing/suit/space/hardsuit/ui_action_click()
@@ -121,7 +129,7 @@
..()
/obj/item/clothing/suit/space/hardsuit/proc/RemoveHelmet()
- if(!helmettype)
+ if(!helmet)
return
suittoggled = 0
if(ishuman(helmet.loc))
diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm
index 2236cf7f230..db02b95bb81 100644
--- a/code/modules/clothing/suits/utility.dm
+++ b/code/modules/clothing/suits/utility.dm
@@ -19,7 +19,7 @@
permeability_coefficient = 0.50
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/internals/emergency_oxygen,/obj/item/weapon/extinguisher)
- slowdown = 1.0
+ slowdown = 1
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
flags = STOPSPRESSUREDMAGE | THICKMATERIAL
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
diff --git a/code/modules/clothing/under/ties.dm b/code/modules/clothing/under/ties.dm
index 82f2030cc8d..353da634cd3 100644
--- a/code/modules/clothing/under/ties.dm
+++ b/code/modules/clothing/under/ties.dm
@@ -6,7 +6,7 @@
item_state = "" //no inhands
item_color = "bluetie"
slot_flags = 0
- w_class = 2.0
+ w_class = 2
/obj/item/clothing/tie/blue
name = "blue tie"
@@ -84,6 +84,7 @@
desc = "A bronze medal."
icon_state = "bronze"
item_color = "bronze"
+ materials = list(MAT_METAL=1000)
burn_state = -1 //Won't burn in fires
//Pinning medals on people
@@ -109,7 +110,7 @@
/obj/item/clothing/tie/medal/conduct
name = "distinguished conduct medal"
- desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is most basic award given by Nanotrasen. It is often awarded by a captain to a member of his crew."
+ desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is the most basic award given by Nanotrasen. It is often awarded by a captain to a member of his crew."
/obj/item/clothing/tie/medal/bronze_heart
name = "bronze heart medal"
@@ -125,6 +126,7 @@
desc = "A silver medal."
icon_state = "silver"
item_color = "silver"
+ materials = list(MAT_SILVER=1000)
/obj/item/clothing/tie/medal/silver/valor
name = "medal of valor"
@@ -139,6 +141,7 @@
desc = "A prestigious golden medal."
icon_state = "gold"
item_color = "gold"
+ materials = list(MAT_GOLD=1000)
/obj/item/clothing/tie/medal/gold/captain
name = "medal of captaincy"
diff --git a/code/modules/crafting/guncrafting.dm b/code/modules/crafting/guncrafting.dm
index df9fba019af..0af951395f8 100644
--- a/code/modules/crafting/guncrafting.dm
+++ b/code/modules/crafting/guncrafting.dm
@@ -24,8 +24,8 @@
var/obj/item/weaponcrafting/ishotgunconstruction/I = new /obj/item/weaponcrafting/ishotgunconstruction
user.unEquip(src)
user.put_in_hands(I)
- del(W)
- del(src)
+ qdel(W)
+ qdel(src)
return
// SHOTGUN //
@@ -57,8 +57,8 @@
var/obj/item/weaponcrafting/ishotgunconstruction3/I = new /obj/item/weaponcrafting/ishotgunconstruction3
user.unEquip(src)
user.put_in_hands(I)
- del(W)
- del(src)
+ qdel(W)
+ qdel(src)
return
/obj/item/weaponcrafting/ishotgunconstruction3
diff --git a/code/modules/crafting/table.dm b/code/modules/crafting/table.dm
index 3d0ed8b6d84..1999ed6edb8 100644
--- a/code/modules/crafting/table.dm
+++ b/code/modules/crafting/table.dm
@@ -78,7 +78,7 @@
if(istype(I, /obj/item/weapon/reagent_containers/food/snacks))
var/obj/item/weapon/reagent_containers/food/snacks/S = I
S.create_reagents(S.volume)
- feedback_add_details("food_made","[S.name]")
+ feedback_add_details("food_made","[S.type]")
send_feedback = 0
var/list/parts = del_reqs(R, I)
for(var/A in parts)
@@ -93,7 +93,7 @@
I.reagents.reagent_list.Add(A)
I.CheckParts()
if(send_feedback)
- feedback_add_details("object_crafted","[I.name]")
+ feedback_add_details("object_crafted","[I.type]")
return 1
return 0
diff --git a/code/modules/detectivework/detective_work.dm b/code/modules/detectivework/detective_work.dm
index 9d4981c9e80..fa324c1886c 100644
--- a/code/modules/detectivework/detective_work.dm
+++ b/code/modules/detectivework/detective_work.dm
@@ -52,21 +52,19 @@
if(isnull(M.key)) return
if(ishuman(M))
var/mob/living/carbon/human/H = M
- if(!istype(H.dna, /datum/dna))
- return 0
if(H.gloves)
if(fingerprintslast != H.ckey)
- fingerprintshidden += text("\[[time_stamp()]\] (Wearing gloves). Real name: [], Key: []",H.real_name, H.key)
+ fingerprintshidden += "\[[time_stamp()]\] (Wearing gloves). Real name: [H.real_name], Key: [H.key]"
fingerprintslast = H.ckey
return 0
- if(!( fingerprints ))
+ if(!fingerprints)
if(fingerprintslast != H.ckey)
- fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",H.real_name, H.key)
+ fingerprintshidden += "\[[time_stamp()]\] Real name: [H.real_name], Key: [H.key]"
fingerprintslast = H.ckey
return 1
else
if(fingerprintslast != M.ckey)
- fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",M.real_name, M.key)
+ fingerprintshidden += "\[[time_stamp()]\] Real name: [M.real_name], Key: [M.key]"
fingerprintslast = M.ckey
return
@@ -75,17 +73,15 @@
if(isnull(M)) return
if(isnull(M.key)) return
if(ishuman(M))
+ var/mob/living/carbon/human/H = M
//Add the list if it does not exist.
if(!fingerprintshidden)
fingerprintshidden = list()
//Fibers~
- add_fibers(M)
+ add_fibers(H)
//Now, lets get to the dirty work.
- //First, make sure their DNA makes sense.
- var/mob/living/carbon/human/H = M
- check_dna_integrity(H) //sets up dna and its variables if it was missing somehow
//Check if the gloves (if any) hide fingerprints
if(H.gloves)
diff --git a/code/modules/detectivework/footprints_and_rag.dm b/code/modules/detectivework/footprints_and_rag.dm
index 7d7818fa3e2..f355f13c80a 100644
--- a/code/modules/detectivework/footprints_and_rag.dm
+++ b/code/modules/detectivework/footprints_and_rag.dm
@@ -19,17 +19,28 @@
volume = 5
spillable = 0
+/obj/item/weapon/reagent_containers/glass/rag/suicide_act(mob/user)
+ user.visible_message("[user] ties the [src.name] around their head and groans! It looks like--")
+ user.say("MY BRAIN HURTS!!")
+ return (OXYLOSS)
+
/obj/item/weapon/reagent_containers/glass/rag/afterattack(atom/A as obj|turf|area, mob/user,proximity)
if(!proximity)
return
- if(ismob(A) && A.reagents && reagents.total_volume)
- var/mob/M = A
- if(user.a_intent == "harm")
- reagents.reaction(M, TOUCH)
- reagents.clear_reagents()
+ if(iscarbon(A) && A.reagents && reagents.total_volume)
+ var/mob/living/carbon/C = A
+ if(user.a_intent == "harm" && !C.is_mouth_covered())
+ reagents.reaction(C, INGEST)
+ reagents.trans_to(C, reagents.total_volume)
+ C.visible_message("[user] has smothered \the [C] with \the [src]!", "[user] has smothered you with \the [src]!", "You hear some struggling and muffled cries of surprise.")
+ var/reagentlist = pretty_string_from_reagent_list(A.reagents)
+ log_game("[key_name(user)] smothered [key_name(A)] with a damp rag containing [reagentlist]")
+ log_attack("[key_name(user)] smothered [key_name(A)] with a damp rag containing [reagentlist]")
else
- reagents.trans_to(M, reagents.total_volume)
- M.visible_message("[user] has smothered \the [A] with \the [src]!", "[user] has smothered you with \the [src]!", "You hear some struggling and muffled cries of surprise.")
+ reagents.reaction(C, TOUCH)
+ reagents.clear_reagents()
+ C.visible_message("[user] has touched \the [C] with \the [src].")
+
else if(istype(A) && src in user)
user.visible_message("[user] starts to wipe down [A] with [src]!", "You start to wipe down [A] with [src]...")
if(do_after(user,30, target = A))
diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm
index 66323ca69de..01a41abc9fd 100644
--- a/code/modules/detectivework/scanner.dm
+++ b/code/modules/detectivework/scanner.dm
@@ -6,12 +6,13 @@
name = "forensic scanner"
desc = "Used to remotely scan objects and biomass for DNA and fingerprints. Can print a report of the findings."
icon_state = "forensicnew"
- w_class = 3.0
+ w_class = 3
item_state = "electronic"
flags = CONDUCT | NOBLUDGEON
slot_flags = SLOT_BELT
var/scanning = 0
var/list/log = list()
+ origin_tech = "engineering=3;biotech=2"
/obj/item/device/detective_scanner/attack_self(mob/user)
if(log.len && !scanning)
@@ -82,7 +83,7 @@
if(ishuman(A))
var/mob/living/carbon/human/H = A
- if (istype(H.dna, /datum/dna) && !H.gloves)
+ if(!H.gloves)
fingerprints += md5(H.dna.uni_identity)
else if(!ismob(A))
diff --git a/code/modules/events/abductor.dm b/code/modules/events/abductor.dm
new file mode 100644
index 00000000000..3a4aacbb116
--- /dev/null
+++ b/code/modules/events/abductor.dm
@@ -0,0 +1,61 @@
+/datum/round_event_control/abductor
+ name = "Abductors"
+ typepath = /datum/round_event/abductor
+ weight = 5
+ max_occurrences = 1
+
+ earliest_start = 180000 // 30 min
+
+ gamemode_blacklist = list("nuclear","wizard","revolution","abduction")
+
+/datum/round_event/abductor
+
+/datum/round_event/abductor/start()
+ //spawn abductor team
+ if(!makeAbductorTeam())
+ message_admins("Abductor event failed to find players. Retrying in 30s.")
+ spawn(30)
+ makeAbductorTeam()
+
+/datum/round_event/abductor/proc/makeAbductorTeam()
+ var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for an Abductor Team?", "abductor", null)
+
+ if(candidates.len >= 2)
+ //Oh god why we can't have static functions
+ var/number = ticker.mode.abductor_teams + 1
+
+ var/datum/game_mode/abduction/temp
+ if(ticker.mode.config_tag == "abduction")
+ temp = ticker.mode
+ else
+ temp = new
+
+ var/agent_mind = pick(candidates)
+ candidates -= agent_mind
+ var/scientist_mind = pick(candidates)
+
+ var/mob/living/carbon/human/agent=makeBody(agent_mind)
+ var/mob/living/carbon/human/scientist=makeBody(scientist_mind)
+
+ agent_mind = agent.mind
+ scientist_mind = scientist.mind
+
+ temp.scientists.len = number
+ temp.agents.len = number
+ temp.abductors.len = 2*number
+ temp.team_objectives.len = number
+ temp.team_names.len = number
+ temp.scientists[number] = scientist_mind
+ temp.agents[number] = agent_mind
+ temp.abductors |= list(agent_mind,scientist_mind)
+ temp.make_abductor_team(number,preset_scientist=scientist_mind,preset_agent=agent_mind)
+ temp.post_setup_team(number)
+
+ ticker.mode.abductor_teams++
+
+ if(ticker.mode.config_tag != "abduction")
+ ticker.mode.abductors |= temp.abductors
+
+ return 1
+ else
+ return 0
\ No newline at end of file
diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm
index 4ed1f4c0e8a..d244d7a8626 100644
--- a/code/modules/events/alien_infestation.dm
+++ b/code/modules/events/alien_infestation.dm
@@ -28,8 +28,10 @@
/datum/round_event/alien_infestation/start()
var/list/vents = list()
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in world)
+ if(qdeleted(temp_vent))
+ continue
if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded)
- var/datum/pipeline/temp_vent_parent = temp_vent.parents["p1"]
+ var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1
if(temp_vent_parent.other_atmosmch.len > 20) //Stops Aliens getting stuck in small networks. See: Security, Virology
vents += temp_vent
diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm
index c678bdab8dc..323908775fe 100644
--- a/code/modules/events/blob.dm
+++ b/code/modules/events/blob.dm
@@ -6,6 +6,8 @@
earliest_start = 48000 // 1 hour 20 minutes
+ gamemode_blacklist = list("blob") // Just in case blob survives that long
+
/datum/round_event/blob
announceWhen = 12
endWhen = 120
diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm
index 9a55d77b4ad..f373fad4af6 100644
--- a/code/modules/events/brand_intelligence.dm
+++ b/code/modules/events/brand_intelligence.dm
@@ -7,7 +7,6 @@
/datum/round_event/brand_intelligence
announceWhen = 21
endWhen = 1000 //Ends when all vending machines are subverted anyway.
-
var/list/obj/machinery/vending/vendingMachines = list()
var/list/obj/machinery/vending/infectedMachines = list()
var/obj/machinery/vending/originMachine
@@ -28,11 +27,9 @@
for(var/obj/machinery/vending/V in machines)
if(V.z != 1) continue
vendingMachines.Add(V)
-
if(!vendingMachines.len)
kill()
return
-
originMachine = pick(vendingMachines)
vendingMachines.Remove(originMachine)
originMachine.shut_up = 0
@@ -48,7 +45,7 @@
originMachine.visible_message("[originMachine] beeps and seems lifeless.")
kill()
return
-
+ vendingMachines = removeNullsFromList(vendingMachines)
if(!vendingMachines.len) //if every machine is infected
for(var/obj/machinery/vending/upriser in infectedMachines)
if(prob(70) && !upriser.gc_destroyed)
@@ -62,7 +59,6 @@
kill()
return
-
if(IsMultiple(activeFor, 4))
var/obj/machinery/vending/rebel = pick(vendingMachines)
vendingMachines.Remove(rebel)
diff --git a/code/modules/events/event.dm b/code/modules/events/event.dm
index 07dbff7d269..722f6556868 100644
--- a/code/modules/events/event.dm
+++ b/code/modules/events/event.dm
@@ -20,6 +20,9 @@
var/alertadmins = 1 //should we let the admins know this event is firing
//should be disabled on events that fire a lot
+ var/list/gamemode_blacklist = list() // Event won't happen in these gamemodes
+ var/list/gamemode_whitelist = list() // Event will happen ONLY in these gamemodes if not empty
+
/datum/round_event_control/wizard
wizardevent = 1
diff --git a/code/modules/events/holiday/halloween.dm b/code/modules/events/holiday/halloween.dm
index a08a507a907..107c8f10920 100644
--- a/code/modules/events/holiday/halloween.dm
+++ b/code/modules/events/holiday/halloween.dm
@@ -11,11 +11,10 @@
for(var/mob/living/carbon/human/H in mob_list)
var/obj/item/weapon/storage/backpack/b = locate() in H.contents
new /obj/item/weapon/storage/spooky(b)
- if(H.dna)
- if(prob(50))
- hardset_dna(H, null, null, null, null, /datum/species/skeleton)
- else
- hardset_dna(H, null, null, null, null, /datum/species/zombie)
+ if(prob(50))
+ H.set_species(/datum/species/skeleton)
+ else
+ H.set_species(/datum/species/zombie)
for(var/mob/living/simple_animal/pet/dog/corgi/Ian/Ian in mob_list)
Ian.place_on_head(new /obj/item/weapon/bedsheet(Ian))
diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm
index f86ecdb5c42..c83ea419df4 100644
--- a/code/modules/events/radiation_storm.dm
+++ b/code/modules/events/radiation_storm.dm
@@ -43,10 +43,9 @@
if(prob(25))
if(prob(75))
randmutb(H)
- domutcheck(H, null, 1)
else
randmutg(H)
- domutcheck(H, null, 1)
+ H.domutcheck()
else if(istype(C, /mob/living/carbon/monkey))
var/mob/living/carbon/monkey/M = C
diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm
index c633246b3e4..73c1234680d 100644
--- a/code/modules/events/spacevine.dm
+++ b/code/modules/events/spacevine.dm
@@ -7,11 +7,15 @@
/datum/round_event/spacevine/start()
var/list/turfs = list() //list of all the empty floor turfs in the hallway areas
+ var/obj/effect/spacevine/SV = new()
+
for(var/area/hallway/A in world)
for(var/turf/simulated/F in A)
- if(!F.density && !F.contents.len)
+ if(F.Enter(SV))
turfs += F
+ qdel(SV)
+
if(turfs.len) //Pick a turf to spawn at if we can
var/turf/simulated/T = pick(turfs)
spawn(0) new/obj/effect/spacevine_controller(T) //spawn a controller at turf
@@ -66,7 +70,6 @@
color = "#aa77aa"
icon_state = "vinefloor"
broken_states = list()
- ignoredirt = 1
//All of this shit is useless for vines
@@ -324,7 +327,7 @@
SetOpacity(0)
if(buckled_mob)
unbuckle_mob()
- ..()
+ return ..()
/obj/effect/spacevine/proc/on_chem_effect(datum/reagent/R)
var/override = 0
@@ -363,7 +366,7 @@
qdel(B)
qdel(src)
- else if(is_sharp(W))
+ else if(W.is_sharp())
qdel(src)
else if(istype(W, /obj/item/weapon/weldingtool))
@@ -424,7 +427,7 @@
/obj/effect/spacevine_controller/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/effect/spacevine_controller/proc/spawn_spacevine_piece(turf/location, obj/effect/spacevine/parent, list/muts)
var/obj/effect/spacevine/SV = new(location)
@@ -555,14 +558,14 @@
/obj/effect/spacevine/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
qdel(src)
return
- if(2.0)
+ if(2)
if (prob(90))
qdel(src)
return
- if(3.0)
+ if(3)
if (prob(50))
qdel(src)
return
diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm
index 771ade0995a..32641e5125d 100644
--- a/code/modules/events/spider_infestation.dm
+++ b/code/modules/events/spider_infestation.dm
@@ -22,7 +22,7 @@
var/list/vents = list()
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in world)
if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded)
- var/datum/pipeline/temp_vent_parent = temp_vent.parents["p1"]
+ var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1
if(temp_vent_parent.other_atmosmch.len > 20)
vents += temp_vent
diff --git a/code/modules/events/vent_clog.dm b/code/modules/events/vent_clog.dm
index 46798a3b64d..8d95dd4ed16 100644
--- a/code/modules/events/vent_clog.dm
+++ b/code/modules/events/vent_clog.dm
@@ -18,7 +18,7 @@
endWhen = rand(25, 100)
for(var/obj/machinery/atmospherics/components/unary/vent_scrubber/temp_vent in machines)
if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded)
- var/datum/pipeline/temp_vent_parent = temp_vent.parents["p1"]
+ var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1
if(temp_vent_parent.other_atmosmch.len > 20)
vents += temp_vent
if(!vents.len)
diff --git a/code/modules/events/wizard/greentext.dm b/code/modules/events/wizard/greentext.dm
index 9222cd16304..599b9a6d26e 100644
--- a/code/modules/events/wizard/greentext.dm
+++ b/code/modules/events/wizard/greentext.dm
@@ -22,7 +22,7 @@
/obj/item/weapon/greentext/
name = "greentext"
desc = "No one knows what this massive tome does, but it feels desirable all the same..."
- w_class = 4.0
+ w_class = 4
icon = 'icons/obj/wizard.dmi'
icon_state = "greentext"
var/mob/living/last_holder
@@ -78,4 +78,4 @@
M.color = initial(M.color)
message += "..."
M << message
- ..()
\ No newline at end of file
+ return ..()
\ No newline at end of file
diff --git a/code/modules/events/wizard/imposter.dm b/code/modules/events/wizard/imposter.dm
index cda6dc2d41f..9a155830455 100644
--- a/code/modules/events/wizard/imposter.dm
+++ b/code/modules/events/wizard/imposter.dm
@@ -17,13 +17,11 @@
PoolOrNew(/obj/effect/effect/smoke, W.loc)
var/mob/living/carbon/human/I = new /mob/living/carbon/human(W.loc)
- I.real_name = W.real_name
- I.dna.unique_enzymes = W.dna.unique_enzymes
- I.name = W.real_name
- I.dna.blood_type = W.dna.blood_type
- I.dna.uni_identity = W.dna.uni_identity
- I.dna.struc_enzymes = W.dna.struc_enzymes
- updateappearance(I)
+ W.dna.transfer_identity(I, transfer_SE=1)
+ I.real_name = I.dna.real_name
+ I.name = I.dna.real_name
+ I.updateappearance(mutcolor_update=1)
+ I.domutcheck()
if(W.ears) I.equip_to_slot_or_del(new W.ears.type, slot_ears)
if(W.w_uniform) I.equip_to_slot_or_del(new W.w_uniform.type , slot_w_uniform)
if(W.shoes) I.equip_to_slot_or_del(new W.shoes.type, slot_shoes)
diff --git a/code/modules/events/wizard/race.dm b/code/modules/events/wizard/race.dm
index 54c3cbf6877..7bbee2ba98c 100644
--- a/code/modules/events/wizard/race.dm
+++ b/code/modules/events/wizard/race.dm
@@ -21,10 +21,9 @@
all_the_same = 1
for(var/mob/living/carbon/human/H in mob_list) //yes, even the dead
- if(H.dna)
- hardset_dna(H, null, null, null, null, new_species)
- H.real_name = new_species.random_name(H.gender,1)
- H.regenerate_icons()
- H << "You feel somehow... different?"
+ H.set_species(new_species)
+ H.real_name = new_species.random_name(H.gender,1)
+ H.dna.unique_enzymes = H.dna.generate_unique_enzymes()
+ H << "You feel somehow... different?"
if(!all_the_same)
new_species = pick(all_species)
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 756d7608141..46a6f1e7429 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -107,6 +107,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/hallucination/simple/Destroy()
if(target.client) target.client.images.Remove(current_image)
active = 0
+ return ..()
#define FAKE_FLOOD_EXPAND_TIME 30
#define FAKE_FLOOD_MAX_RADIUS 7
@@ -156,11 +157,11 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/hallucination/fake_flood/Destroy()
SSobj.processing.Remove(src)
- del(flood_turfs)
+ qdel(flood_turfs)
if(target.client) target.client.images.Remove(flood_images)
target = null
- del(flood_images)
- return
+ qdel(flood_images)
+ return ..()
/obj/effect/hallucination/simple/xeno
image_icon = 'icons/mob/alien.dmi'
@@ -188,19 +189,20 @@ Gunshots/explosions/opening doors/less rare audio (done)
if(!U.welded)
pump = U
break
- xeno = new(pump.loc,target)
- sleep(10)
- xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
- xeno.throw_at(target,7,1, spin = 0, diagonals_first = 1)
- sleep(10)
- xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
- xeno.throw_at(pump,7,1, spin = 0, diagonals_first = 1)
- sleep(10)
- var/xeno_name = xeno.name
- target << "[xeno_name] begins climbing into the ventilation system..."
- sleep(10)
- qdel(xeno)
- target << "[xeno_name] scrambles into the ventilation ducts!"
+ if(pump)
+ xeno = new(pump.loc,target)
+ sleep(10)
+ xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
+ xeno.throw_at(target,7,1, spin = 0, diagonals_first = 1)
+ sleep(10)
+ xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
+ xeno.throw_at(pump,7,1, spin = 0, diagonals_first = 1)
+ sleep(10)
+ var/xeno_name = xeno.name
+ target << "[xeno_name] begins climbing into the ventilation system..."
+ sleep(10)
+ qdel(xeno)
+ target << "[xeno_name] scrambles into the ventilation ducts!"
qdel(src)
/obj/effect/hallucination/singularity_scare
diff --git a/code/modules/food&drinks/drinks/drinks.dm b/code/modules/food&drinks/drinks/drinks.dm
index ff06642aa2d..416b5b5777b 100644
--- a/code/modules/food&drinks/drinks/drinks.dm
+++ b/code/modules/food&drinks/drinks/drinks.dm
@@ -88,8 +88,8 @@
/obj/item/weapon/reagent_containers/food/drinks/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/clothing/mask/cigarette)) //ciggies are weird
return
- if(is_hot(I))
- var/added_heat = (is_hot(I) / 100) //ishot returns a temperature
+ if(I.is_hot())
+ var/added_heat = (I.is_hot() / 100) //ishot returns a temperature
if(src.reagents)
src.reagents.chem_temp += added_heat
user << "You heat [src] with [I]."
@@ -107,6 +107,7 @@
force = 14
throwforce = 10
amount_per_transfer_from_this = 20
+ materials = list(MAT_GOLD=1000)
possible_transfer_amounts = null
volume = 150
flags = CONDUCT | OPENCONTAINER
@@ -128,14 +129,6 @@
list_reagents = list("coffee" = 30)
spillable = 1
-/obj/item/weapon/reagent_containers/food/drinks/tea
- name = "Duke Purple Tea"
- desc = "An insult to Duke Purple is an insult to the Space Queen! Any proper gentleman will fight you, if you sully this tea."
- icon_state = "tea"
- item_state = "coffee"
- list_reagents = list("tea" = 30)
- spillable = 1
-
/obj/item/weapon/reagent_containers/food/drinks/ice
name = "Ice Cup"
desc = "Careful, cold ice, do not chew."
@@ -143,14 +136,29 @@
list_reagents = list("ice" = 30)
spillable = 1
-/obj/item/weapon/reagent_containers/food/drinks/h_chocolate
- name = "Dutch Hot Coco"
- desc = "Made in Space South America."
+/obj/item/weapon/reagent_containers/food/drinks/mug/ // parent type is literally just so empty mug sprites are a thing
+ name = "mug"
+ desc = "A drink served in a classy mug."
icon_state = "tea"
item_state = "coffee"
- list_reagents = list("hot_coco" = 30, "sugar" = 5)
spillable = 1
+/obj/item/weapon/reagent_containers/food/drinks/mug/on_reagent_change()
+ if(reagents.total_volume)
+ icon_state = "tea"
+ else
+ icon_state = "tea_empty"
+
+/obj/item/weapon/reagent_containers/food/drinks/mug/tea
+ name = "Duke Purple Tea"
+ desc = "An insult to Duke Purple is an insult to the Space Queen! Any proper gentleman will fight you, if you sully this tea."
+ list_reagents = list("tea" = 30)
+
+/obj/item/weapon/reagent_containers/food/drinks/mug/coco
+ name = "Dutch Hot Coco"
+ desc = "Made in Space South America."
+ list_reagents = list("hot_coco" = 30, "sugar" = 5)
+
/obj/item/weapon/reagent_containers/food/drinks/dry_ramen
name = "Cup Ramen"
desc = "Just add 10ml of water, self heats! A taste that reminds you of your school years."
@@ -202,12 +210,14 @@
name = "captain's flask"
desc = "A silver flask belonging to the captain."
icon_state = "flask"
+ materials = list(MAT_SILVER=500)
volume = 60
/obj/item/weapon/reagent_containers/food/drinks/flask/det
name = "detective's flask"
desc = "The detective's only true friend."
icon_state = "detflask"
+ materials = list(MAT_METAL=250)
list_reagents = list("whiskey" = 30)
/obj/item/weapon/reagent_containers/food/drinks/britcup
diff --git a/code/modules/food&drinks/drinks/drinks/bottle.dm b/code/modules/food&drinks/drinks/drinks/bottle.dm
index 8f003e6fb75..e97d65fdea7 100644
--- a/code/modules/food&drinks/drinks/drinks/bottle.dm
+++ b/code/modules/food&drinks/drinks/drinks/bottle.dm
@@ -136,14 +136,15 @@
desc = "A bottle with a sharp broken bottom."
icon = 'icons/obj/drinks.dmi'
icon_state = "broken_bottle"
- force = 9.0
- throwforce = 5.0
+ force = 9
+ throwforce = 5
throw_speed = 3
throw_range = 5
item_state = "beer"
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("stabbed", "slashed", "attacked")
var/icon/broken_outline = icon('icons/obj/drinks.dmi', "broken")
+ sharpness = IS_SHARP
/obj/item/weapon/reagent_containers/food/drinks/bottle/gin
name = "Griffeater Gin"
@@ -298,13 +299,13 @@
..()
/obj/item/weapon/reagent_containers/food/drinks/bottle/molotov/attackby(obj/item/I, mob/user, params)
- if(is_hot(I) && !active)
+ if(I.is_hot() && !active)
active = 1
var/turf/bombturf = get_turf(src)
var/area/bombarea = get_area(bombturf)
message_admins("[key_name(user)]? has primed a [name] for detonation at [bombarea] (JMP).")
log_game("[key_name(user)] has primed a [name] for detonation at [bombarea] ([bombturf.x],[bombturf.y],[bombturf.z]).")
-
+
user << "You light \the [src] on fire."
overlays += fire_overlay
if(!isGlass)
diff --git a/code/modules/food&drinks/food/snacks.dm b/code/modules/food&drinks/food/snacks.dm
index 51203df2505..e4a790d5404 100644
--- a/code/modules/food&drinks/food/snacks.dm
+++ b/code/modules/food&drinks/food/snacks.dm
@@ -150,9 +150,9 @@
var/obj/item/weapon/reagent_containers/food/snacks/customizable/C = new custom_food_type(get_turf(src))
C.initialize_custom_food(src, S, user)
return 0
- if(is_sharp(W))
- var/sharpness = is_sharp(W)
- if(slice(sharpness, W, user))
+ var/sharp = W.is_sharp()
+ if(sharp)
+ if(slice(sharp, W, user))
return 1
//Called when you finish tablecrafting a snack.
@@ -176,7 +176,7 @@
return 1
var/slices_lost = 0
- if (accuracy > 1)
+ if (accuracy >= IS_SHARP_ACCURATE)
user.visible_message( \
"[user] slices [src].", \
"You slice [src]." \
@@ -223,7 +223,7 @@
if(contents)
for(var/atom/movable/something in contents)
something.loc = get_turf(src)
- ..()
+ return ..()
/obj/item/weapon/reagent_containers/food/snacks/attack_animal(mob/M)
if(isanimal(M))
@@ -278,7 +278,7 @@
/obj/item/weapon/reagent_containers/food/snacks/store/attackby(obj/item/weapon/W, mob/user, params)
..()
if(W.w_class <= 2 & !istype(W, /obj/item/weapon/reagent_containers/food/snacks)) //can't slip snacks inside, they're used for custom foods.
- if(is_sharp(W))
+ if(W.is_sharp())
return 0
if(stored_item)
return 0
diff --git a/code/modules/food&drinks/kitchen machinery/microwave.dm b/code/modules/food&drinks/kitchen machinery/microwave.dm
index 0221c4bdc07..400bbd075a9 100644
--- a/code/modules/food&drinks/kitchen machinery/microwave.dm
+++ b/code/modules/food&drinks/kitchen machinery/microwave.dm
@@ -244,7 +244,7 @@
if(F.cooked_type)
var/obj/item/weapon/reagent_containers/food/snacks/S = new F.cooked_type (get_turf(src))
F.initialize_cooked_food(S, efficiency)
- feedback_add_details("food_made","[F.name]")
+ feedback_add_details("food_made","[F.type]")
else
new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(src)
if(dirty < 100)
diff --git a/code/modules/food&drinks/kitchen machinery/processor.dm b/code/modules/food&drinks/kitchen machinery/processor.dm
index 431dee34309..5db38bbc970 100644
--- a/code/modules/food&drinks/kitchen machinery/processor.dm
+++ b/code/modules/food&drinks/kitchen machinery/processor.dm
@@ -112,8 +112,8 @@
for(var/datum/disease/D in O.viruses)
if(!(D.spread_flags & SPECIAL))
B.data["viruses"] += D.Copy()
- if(check_dna_integrity(O))
- B.data["blood_DNA"] = copytext(O.dna.unique_enzymes,1,0)
+ if(O.has_dna())
+ B.data["blood_DNA"] = O.dna.unique_enzymes
if(O.resistances&&O.resistances.len)
B.data["resistances"] = O.resistances.Copy()
diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm
index f27866be2d2..3723a221dab 100644
--- a/code/modules/hydroponics/grown.dm
+++ b/code/modules/hydroponics/grown.dm
@@ -305,7 +305,7 @@
/obj/item/weapon/reagent_containers/food/snacks/grown/berries/glow/Destroy()
if(istype(loc,/mob))
loc.AddLuminosity(round(-potency / 5,1))
- ..()
+ return ..()
/obj/item/weapon/reagent_containers/food/snacks/grown/berries/glow/pickup(mob/user)
src.SetLuminosity(0)
@@ -487,7 +487,7 @@
/obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
..()
- if(is_sharp(W))
+ if(W.is_sharp())
user.show_message("You carve a face into [src]!", 1)
new /obj/item/clothing/head/hardhat/pumpkinhead (user.loc)
qdel(src)
@@ -1208,7 +1208,7 @@ obj/item/weapon/reagent_containers/food/snacks/grown/shell/eggy/add_juice()
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/glowshroom/Destroy()
if(istype(loc,/mob))
loc.AddLuminosity(round(-potency / 10,1))
- ..()
+ return ..()
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/glowshroom/pickup(mob/user)
SetLuminosity(0)
diff --git a/code/modules/hydroponics/growninedible.dm b/code/modules/hydroponics/growninedible.dm
index 10af706e393..e016b244338 100644
--- a/code/modules/hydroponics/growninedible.dm
+++ b/code/modules/hydroponics/growninedible.dm
@@ -49,7 +49,7 @@
icon_state = "logs"
force = 5
throwforce = 5
- w_class = 3.0
+ w_class = 3
throw_speed = 2
throw_range = 3
plant_type = 2
@@ -110,7 +110,7 @@
force = 0
slot_flags = SLOT_HEAD
throwforce = 0
- w_class = 1.0
+ w_class = 1
throw_speed = 1
throw_range = 3
@@ -128,7 +128,7 @@
force = 0
slot_flags = SLOT_HEAD
throwforce = 0
- w_class = 1.0
+ w_class = 1
throw_speed = 1
throw_range = 3
plant_type = 0
@@ -172,7 +172,7 @@
force = 15
hitsound = 'sound/weapons/bladeslice.ogg'
throwforce = 5
- w_class = 1.0
+ w_class = 1
throw_speed = 1
throw_range = 3
plant_type = 1
@@ -258,7 +258,7 @@
icon = 'icons/obj/items.dmi'
icon_state = "banana_peel"
item_state = "banana_peel"
- w_class = 1.0
+ w_class = 1
throwforce = 0
throw_speed = 3
throw_range = 7
@@ -295,14 +295,14 @@
desc = "A reminder of meals gone by."
icon_state = "corncob"
item_state = "corncob"
- w_class = 1.0
+ w_class = 1
throwforce = 0
throw_speed = 3
throw_range = 7
/obj/item/weapon/grown/corncob/attackby(obj/item/weapon/grown/W, mob/user, params)
..()
- if(is_sharp(W))
+ if(W.is_sharp())
user << "You use [W] to fashion a pipe out of the corn cob!"
new /obj/item/clothing/mask/cigarette/pipe/cobpipe (user.loc)
user.unEquip(src)
@@ -314,7 +314,7 @@
desc = "A cob with snap pops"
icon_state = "snapcorn"
item_state = "corncob"
- w_class = 1.0
+ w_class = 1
throwforce = 0
throw_speed = 3
throw_range = 7
diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm
index 46c56442345..6e5a45843d4 100644
--- a/code/modules/hydroponics/hydroitemdefines.dm
+++ b/code/modules/hydroponics/hydroitemdefines.dm
@@ -24,7 +24,7 @@
flags = OPENCONTAINER
slot_flags = SLOT_BELT
throwforce = 0
- w_class = 2.0
+ w_class = 2
throw_speed = 3
throw_range = 10
@@ -46,7 +46,7 @@
flags = OPENCONTAINER
slot_flags = SLOT_BELT
throwforce = 0
- w_class = 2.0
+ w_class = 2
throw_speed = 3
throw_range = 10
@@ -65,9 +65,9 @@
icon_state = "cultivator"
item_state = "cultivator"
flags = CONDUCT
- force = 5.0
- throwforce = 7.0
- w_class = 2.0
+ force = 5
+ throwforce = 7
+ w_class = 2
materials = list(MAT_METAL=50)
attack_verb = list("slashed", "sliced", "cut", "clawed")
hitsound = 'sound/weapons/bladeslice.ogg'
@@ -78,15 +78,16 @@
icon = 'icons/obj/weapons.dmi'
icon_state = "hatchet"
flags = CONDUCT
- force = 12.0
- w_class = 1.0
- throwforce = 15.0
+ force = 12
+ w_class = 1
+ throwforce = 15
throw_speed = 3
throw_range = 4
materials = list(MAT_METAL=15000)
origin_tech = "materials=2;combat=1"
attack_verb = list("chopped", "torn", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
+ sharpness = IS_SHARP
/obj/item/weapon/hatchet/suicide_act(mob/user)
user.visible_message("[user] is chopping at \himself with the [src.name]! It looks like \he's trying to commit suicide.")
@@ -97,11 +98,11 @@
icon_state = "scythe0"
name = "scythe"
desc = "A sharp and curved blade on a long fibremetal handle, this tool makes it easy to reap what you sow."
- force = 13.0
- throwforce = 5.0
+ force = 13
+ throwforce = 5
throw_speed = 2
throw_range = 3
- w_class = 4.0
+ w_class = 4
flags = CONDUCT | NOSHIELD
slot_flags = SLOT_BACK
origin_tech = "materials=2;combat=2"
@@ -123,14 +124,14 @@
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle16"
volume = 50
- w_class = 1.0
+ w_class = 1
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(1,2,5,10,15,25,50)
/obj/item/weapon/reagent_containers/glass/bottle/nutrient/New()
..()
- src.pixel_x = rand(-5.0, 5)
- src.pixel_y = rand(-5.0, 5)
+ src.pixel_x = rand(-5, 5)
+ src.pixel_y = rand(-5, 5)
/obj/item/weapon/reagent_containers/glass/bottle/nutrient/ez
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index 5d649ae44ed..082ed238267 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -230,9 +230,9 @@
if (mutmod == 2)
if(prob(50)) //50%
mutate()
- else if(prob(75)) //37.5%
+ else if(prob(50)) //25%
hardmutate()
- else if(prob(10)) //1/80
+ else if(prob(50)) //12.5%
mutatespecie()
return
return
@@ -686,7 +686,7 @@
H.applyChemicals(S)
S.clear_reagents()
- del(S)
+ qdel(S)
H.update_icon()
if(reagent_source) // If the source wasn't composted and destroyed
reagent_source.update_icon()
@@ -897,7 +897,7 @@
podman.faction |= factions
if(!features["mcolor"])
features["mcolor"] = "#59CE00"
- hardset_dna(podman,null,null,podman.real_name,blood_type,/datum/species/plant/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman
+ podman.hardset_dna(null,null,podman.real_name,blood_type,/datum/species/plant/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman
podman.set_cloned_appearance()
else //else, one packet of seeds. maybe two
diff --git a/code/modules/hydroponics/seed_extractor.dm b/code/modules/hydroponics/seed_extractor.dm
index b8eec1a9ba8..f3ffdb83c81 100644
--- a/code/modules/hydroponics/seed_extractor.dm
+++ b/code/modules/hydroponics/seed_extractor.dm
@@ -185,7 +185,7 @@
N.amount = max(N.amount - 1, 0)
if (N.amount <= 0)
piles -= N
- del(N)
+ qdel(N)
break
for (var/obj/T in contents)//Now we find the seed we need to vend
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index 7334590239e..06f917a668b 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -1339,21 +1339,29 @@
if(parent)
mutations = parent.mutations
+/obj/item/seeds/kudzuseed/suicide_act(mob/user)
+ user.visible_message("[user] swallows the pack of kudzu seeds! It looks like \he's trying to commit suicide..")
+ plant(user)
+ return (BRUTELOSS)
+
/obj/item/seeds/kudzuseed/harvest()
var/list/prod = ..()
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/kudzupod/K in prod)
K.mutations = mutations
-/obj/item/seeds/kudzuseed/attack_self(mob/user)
+/obj/item/seeds/kudzuseed/proc/plant(mob/user)
if(istype(user.loc,/turf/space))
return
var/turf/T = get_turf(src)
- user << "You plant the kudzu. You monster."
message_admins("Kudzu planted by [key_name_admin(user)](?) (FLW) at ([T.x],[T.y],[T.z] - (JMP))",0,1)
investigate_log("was planted by [key_name(user)] at ([T.x],[T.y],[T.z])","kudzu")
new /obj/effect/spacevine_controller(user.loc, mutations, potency, production)
qdel(src)
+/obj/item/seeds/kudzuseed/attack_self(mob/user)
+ plant(user)
+ user << "You plant the kudzu. You monster."
+
/obj/item/seeds/kudzuseed/get_analyzer_text()
var/list/mut_text = list()
var/text_string = ""
diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm
index 96dc3f1b9a1..3cb02b4f5ed 100644
--- a/code/modules/library/lib_items.dm
+++ b/code/modules/library/lib_items.dm
@@ -284,7 +284,7 @@
icon_state ="scanner"
throw_speed = 3
throw_range = 5
- w_class = 1.0
+ w_class = 1
var/obj/machinery/computer/libraryconsole/bookmanagement/computer //Associated computer - Modes 1 to 3 use this
var/obj/item/weapon/book/book //Currently scanned book
var/mode = 0 //0 - Scan only, 1 - Scan and Set Buffer, 2 - Scan and Attempt to Check In, 3 - Scan and Attempt to Add to Inventory
diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm
index 06c4f46ae2c..12adf16e326 100644
--- a/code/modules/mining/abandoned_crates.dm
+++ b/code/modules/mining/abandoned_crates.dm
@@ -43,7 +43,7 @@
new /obj/item/weapon/ore/diamond(src)
if(21 to 25)
for(var/i = 0, i < 5, i++)
- new /obj/item/weapon/contraband/poster(src)
+ new /obj/item/weapon/poster/contraband(src)
if(26 to 30)
for(var/i = 0, i < 3, i++)
new /obj/item/weapon/reagent_containers/glass/beaker/noreact(src)
diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm
index f0e699253be..99a467ba8f0 100644
--- a/code/modules/mining/equipment_locker.dm
+++ b/code/modules/mining/equipment_locker.dm
@@ -7,7 +7,7 @@
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "ore_redemption"
density = 1
- anchored = 1.0
+ anchored = 1
input_dir = NORTH
output_dir = SOUTH
req_access = list(access_mineral_storeroom)
@@ -257,7 +257,7 @@
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "mining"
density = 1
- anchored = 1.0
+ anchored = 1
var/obj/item/weapon/card/id/inserted_id
var/list/prize_list = list(
new /datum/data/mining_equipment("Stimpack", /obj/item/weapon/reagent_containers/hypospray/medipen/stimpack, 50),
@@ -440,7 +440,7 @@
icon_state = "Jaunter"
item_state = "electronic"
throwforce = 0
- w_class = 2.0
+ w_class = 2
throw_speed = 3
throw_range = 5
origin_tech = "bluespace=2"
@@ -507,6 +507,7 @@
var/fieldsactive = 0
var/burst_time = 50
var/fieldlimit = 3
+ origin_tech = "magnets=2;combat=2"
/obj/item/weapon/resonator/proc/CreateResonance(target, creator)
var/turf/T = get_turf(target)
@@ -573,6 +574,7 @@
/**********************Facehugger toy**********************/
/obj/item/clothing/mask/facehugger/toy
+ item_state = "facehugger_inactive"
desc = "A toy often used to play pranks on other miners by putting it in their beds. It takes a bit to recharge after latching onto something."
throwforce = 0
real = 0
@@ -718,11 +720,12 @@
icon_state = "lazarus_hypo"
item_state = "hypo"
throwforce = 0
- w_class = 2.0
+ w_class = 2
throw_speed = 3
throw_range = 5
var/loaded = 1
var/malfunctioning = 0
+ origin_tech = "biotech=4"
/obj/item/weapon/lazarus_injector/afterattack(atom/target, mob/user, proximity_flag)
if(!loaded)
@@ -773,10 +776,11 @@
name = "mining scanner"
icon_state = "mining1"
item_state = "analyzer"
- w_class = 2.0
+ w_class = 2
flags = CONDUCT
slot_flags = SLOT_BELT
var/cooldown = 0
+ origin_tech = "engineering=1;magnets=1"
/obj/item/device/mining_scanner/attack_self(mob/user)
if(!user.client)
@@ -804,10 +808,11 @@
name = "advanced mining scanner"
icon_state = "mining0"
item_state = "analyzer"
- w_class = 2.0
+ w_class = 2
flags = CONDUCT
slot_flags = SLOT_BELT
var/cooldown = 0
+ origin_tech = "engineering=3;magnets=3"
/obj/item/device/t_scanner/adv_mining_scanner/scan()
if(!cooldown)
diff --git a/code/modules/mining/machine_input_output_plates.dm b/code/modules/mining/machine_input_output_plates.dm
index 2c9d289a9cf..e17cc7107f9 100644
--- a/code/modules/mining/machine_input_output_plates.dm
+++ b/code/modules/mining/machine_input_output_plates.dm
@@ -5,7 +5,7 @@
icon_state = "x2"
name = "Input area"
density = 0
- anchored = 1.0
+ anchored = 1
New()
icon_state = "blank"
@@ -14,7 +14,7 @@
icon_state = "x"
name = "Output area"
density = 0
- anchored = 1.0
+ anchored = 1
New()
icon_state = "blank"
diff --git a/code/modules/mining/machine_stacking.dm b/code/modules/mining/machine_stacking.dm
index aec2fce7f5a..37ce43abc46 100644
--- a/code/modules/mining/machine_stacking.dm
+++ b/code/modules/mining/machine_stacking.dm
@@ -61,7 +61,7 @@
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "stacker"
density = 1
- anchored = 1.0
+ anchored = 1
var/obj/machinery/mineral/stacking_unit_console/CONSOLE
var/stk_types = list()
var/stk_amt = list()
diff --git a/code/modules/mining/machine_unloading.dm b/code/modules/mining/machine_unloading.dm
index 3f60571df9f..4c86526f01d 100644
--- a/code/modules/mining/machine_unloading.dm
+++ b/code/modules/mining/machine_unloading.dm
@@ -6,7 +6,7 @@
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "unloader"
density = 1
- anchored = 1.0
+ anchored = 1
input_dir = WEST
output_dir = EAST
diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm
index 9c4ca620e26..976a019913c 100644
--- a/code/modules/mining/mine_items.dm
+++ b/code/modules/mining/mine_items.dm
@@ -62,10 +62,10 @@
flags = CONDUCT
slot_flags = SLOT_BELT
force = 15
- throwforce = 10.0
+ throwforce = 10
item_state = "pickaxe"
- w_class = 4.0
- materials = list(MAT_METAL=3750) //one sheet, but where can you make them?
+ w_class = 4
+ materials = list(MAT_METAL=2000) //one sheet, but where can you make them?
var/digspeed = 40
var/list/digsound = list('sound/effects/picaxe1.ogg','sound/effects/picaxe2.ogg','sound/effects/picaxe3.ogg')
origin_tech = "materials=1;engineering=1"
@@ -128,23 +128,24 @@
icon_state = "shovel"
flags = CONDUCT
slot_flags = SLOT_BELT
- force = 8.0
+ force = 8
var/digspeed = 20
- throwforce = 4.0
+ throwforce = 4
item_state = "shovel"
- w_class = 3.0
+ w_class = 3
materials = list(MAT_METAL=50)
origin_tech = "materials=1;engineering=1"
attack_verb = list("bashed", "bludgeoned", "thrashed", "whacked")
+ sharpness = IS_SHARP
/obj/item/weapon/shovel/spade
name = "spade"
desc = "A small tool for digging and moving dirt."
icon_state = "spade"
item_state = "spade"
- force = 5.0
- throwforce = 7.0
- w_class = 2.0
+ force = 5
+ throwforce = 7
+ w_class = 2
/**********************Mining car (Crate like thing, not the rail car)**************************/
@@ -154,3 +155,103 @@
name = "Mining car (not for rails)"
icon_crate = "miningcar"
icon_state = "miningcar"
+/*****************************Survival Pod********************************/
+
+
+/area/survivalpod
+ name = "\improper Emergency Shelter"
+ icon_state = "away"
+ requires_power = 0
+ has_gravity = 1
+
+/obj/item/weapon/survivalcapsule
+ name = "bluespace shelter capsule"
+ desc = "An emergency shelter stored within a pocket of bluespace."
+ icon_state = "pill3"
+ icon = 'icons/obj/chemical.dmi'
+ w_class = 1
+ var/used = FALSE
+
+/obj/item/weapon/survivalcapsule/attack_self()
+ if(used == FALSE)
+ src.loc.visible_message("The [src] begins to shake. Stand back!")
+ used = TRUE
+ sleep(50)
+ playsound(get_turf(src), 'sound/effects/phasein.ogg', 100, 1)
+ PoolOrNew(/obj/effect/effect/smoke, src.loc)
+ load()
+ qdel(src)
+
+/obj/item/weapon/survivalcapsule/proc/load()
+ var/turf/start_turf = get_turf(src.loc)
+ var/turf/cur_turf
+ var/x_size = 5
+ var/y_size = 5
+ var/list/walltypes = list(/turf/simulated/wall)
+ var/floor_type = /turf/simulated/floor/wood
+ var/room
+
+ //Center the room/spawn it
+ start_turf = locate(start_turf.x -2, start_turf.y - 2, start_turf.z)
+
+ room = spawn_room(start_turf, x_size, y_size, walltypes, floor_type, "Emergency Shelter")
+
+ start_turf = get_turf(src.loc)
+
+ //Fill it
+ cur_turf = locate(start_turf.x, start_turf.y-2, start_turf.z)
+ new /obj/machinery/door/airlock/glass(cur_turf)
+
+ cur_turf = locate(start_turf.x+1, start_turf.y, start_turf.z)
+ new /obj/structure/table/wood(cur_turf)
+ new /obj/item/weapon/storage/pill_bottle/dice(cur_turf)
+
+ cur_turf = locate(start_turf.x+1, start_turf.y-1, start_turf.z)
+ var/obj/structure/stool/bed/chair/comfy/C = new /obj/structure/stool/bed/chair/comfy(cur_turf)
+ C.dir = 1
+
+ cur_turf = locate(start_turf.x+1, start_turf.y+1, start_turf.z)
+ new /obj/structure/stool/bed/chair/comfy(cur_turf)
+
+ cur_turf = locate(start_turf.x-1, start_turf.y-1, start_turf.z)
+ var/obj/machinery/sleeper/S = new /obj/machinery/sleeper(cur_turf)
+ S.dir = 4
+
+ cur_turf = locate(start_turf.x-1, start_turf.y, start_turf.z)
+ new /obj/structure/table/wood(cur_turf)
+ new /obj/item/weapon/storage/box/donkpockets(cur_turf)
+
+ cur_turf = locate(start_turf.x-1, start_turf.y+1, start_turf.z)
+ new /obj/structure/table/wood(cur_turf)
+ new /obj/machinery/microwave(cur_turf)
+
+ var/area/survivalpod/L = new /area/survivalpod
+
+ var/turf/threshhold = locate(start_turf.x, start_turf.y-2, start_turf.z)
+ threshhold.ChangeTurf(/turf/simulated/floor/wood)
+ threshhold.blocks_air = 1 //So the air doesn't leak out
+ threshhold.oxygen = 21
+ threshhold.temperature = 293.15
+ threshhold.nitrogen = 82
+ threshhold.carbon_dioxide = 0
+ threshhold.toxins = 0
+ L.contents += threshhold
+ threshhold.overlays.Cut()
+
+ var/list/turfs = room["floors"]
+ for(var/turf/simulated/floor/A in turfs)
+ SSair.remove_from_active(A)
+ A.oxygen = 21
+ A.temperature = 293.15
+ A.nitrogen = 82
+ A.carbon_dioxide = 0
+ A.toxins = 0
+ A.air.oxygen = 21
+ A.air.carbon_dioxide = 0
+ A.air.nitrogen = 82
+ A.air.toxins = 0
+ A.air.temperature = 293.15
+ SSair.add_to_active(A)
+ A.overlays.Cut()
+
+ L.contents += A
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index 894d29cbc5c..07752bf7b6f 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -28,13 +28,13 @@ var/global/list/rockTurfEdgeCache
/turf/simulated/mineral/ex_act(severity, target)
..()
switch(severity)
- if(3.0)
+ if(3)
if (prob(75))
src.gets_drilled(null, 1)
- if(2.0)
+ if(2)
if (prob(90))
src.gets_drilled(null, 1)
- if(1.0)
+ if(1)
src.gets_drilled(null, 1)
return
@@ -85,7 +85,7 @@ var/global/list/rockTurfEdgeCache
new src.type(T)
/turf/simulated/mineral/random
- name = "mineral deposit"
+ name = "rock"
icon_state = "rock"
var/mineralSpawnChanceList = list(
"Uranium" = 5, "Diamond" = 1, "Gold" = 10,
@@ -432,10 +432,10 @@ var/global/list/rockTurfEdgeCache
P.playDigSound()
if(do_after(user,P.digspeed, target = src))
- if(istype(src, /turf/simulated/mineral))
+ if(istype(src, /turf/simulated/mineral))
user << "You finish cutting into the rock."
gets_drilled(user)
- feedback_add_details("pick_used_mining","[P.name]")
+ feedback_add_details("pick_used_mining","[P.type]")
else
return attack_hand(user)
return
@@ -509,7 +509,6 @@ var/global/list/rockTurfEdgeCache
icon_state = "asteroid"
icon_plating = "asteroid"
var/dug = 0 //0 = has not yet been dug, 1 = has already been dug
- ignoredirt = 1
/turf/simulated/floor/plating/asteroid/airless
oxygen = 0.01
@@ -534,12 +533,12 @@ var/global/list/rockTurfEdgeCache
/turf/simulated/floor/plating/asteroid/ex_act(severity, target)
contents_explosion(severity, target)
switch(severity)
- if(3.0)
+ if(3)
return
- if(2.0)
+ if(2)
if (prob(20))
src.gets_dug()
- if(1.0)
+ if(1)
src.gets_dug()
return
@@ -565,13 +564,13 @@ var/global/list/rockTurfEdgeCache
user << "You start digging..."
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1) //FUCK YO RUSTLE I GOT'S THE DIGS SOUND HERE
-
+
if(do_after(user, digging_speed, target = src))
- if(istype(src, /turf/simulated/floor/plating/asteroid))
+ if(istype(src, /turf/simulated/floor/plating/asteroid))
user << "You dig a hole."
gets_dug()
- feedback_add_details("pick_used_mining","[W.name]")
-
+ feedback_add_details("pick_used_mining","[W.type]")
+
if(istype(W,/obj/item/weapon/storage/bag/ore))
var/obj/item/weapon/storage/bag/ore/S = W
if(S.collection_mode == 1)
@@ -603,6 +602,12 @@ var/global/list/rockTurfEdgeCache
icon_state = "asteroid_dug"
return
+/turf/simulated/floor/plating/asteroid/singularity_act()
+ return
+
+/turf/simulated/floor/plating/asteroid/singularity_pull(S, current_size)
+ return
+
/turf/proc/updateMineralOverlays()
src.overlays.Cut()
diff --git a/code/modules/mining/mint.dm b/code/modules/mining/mint.dm
index 9285f95aa1d..3caefd09573 100644
--- a/code/modules/mining/mint.dm
+++ b/code/modules/mining/mint.dm
@@ -6,7 +6,7 @@
icon = 'icons/obj/economy.dmi'
icon_state = "coinpress0"
density = 1
- anchored = 1.0
+ anchored = 1
var/amt_silver = 0 //amount of silver
var/amt_gold = 0 //amount of gold
var/amt_diamond = 0
diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm
index ed6056c382a..fd6125dbcda 100644
--- a/code/modules/mining/money_bag.dm
+++ b/code/modules/mining/money_bag.dm
@@ -5,9 +5,9 @@
name = "Money bag"
icon_state = "moneybag"
flags = CONDUCT
- force = 10.0
+ force = 10
throwforce = 0
- w_class = 4.0
+ w_class = 4
burn_state = 0 //Burnable
burntime = 20
diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm
index e1089f54ac3..0f3e08a9e17 100644
--- a/code/modules/mining/ores_coins.dm
+++ b/code/modules/mining/ores_coins.dm
@@ -22,6 +22,7 @@
icon_state = "Uranium ore"
origin_tech = "materials=5"
points = 18
+ materials = list(MAT_URANIUM=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/uranium
/obj/item/weapon/ore/iron
@@ -29,6 +30,7 @@
icon_state = "Iron ore"
origin_tech = "materials=1"
points = 1
+ materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/metal
/obj/item/weapon/ore/glass
@@ -36,6 +38,7 @@
icon_state = "Glass ore"
origin_tech = "materials=1"
points = 1
+ materials = list(MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/glass
/obj/item/weapon/ore/glass/attack_self(mob/living/user)
@@ -60,8 +63,9 @@
/obj/item/weapon/ore/plasma
name = "plasma ore"
icon_state = "Plasma ore"
- origin_tech = "materials=2"
+ origin_tech = "plasmatech=2;materials=2"
points = 36
+ materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/plasma
/obj/item/weapon/ore/plasma/attackby(obj/item/I, mob/user, params)
@@ -78,6 +82,7 @@
icon_state = "Silver ore"
origin_tech = "materials=3"
points = 18
+ materials = list(MAT_SILVER=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/silver
/obj/item/weapon/ore/gold
@@ -85,6 +90,7 @@
icon_state = "Gold ore"
origin_tech = "materials=4"
points = 18
+ materials = list(MAT_GOLD=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/gold
/obj/item/weapon/ore/diamond
@@ -92,6 +98,7 @@
icon_state = "Diamond ore"
origin_tech = "materials=6"
points = 36
+ materials = list(MAT_DIAMOND=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/diamond
/obj/item/weapon/ore/bananium
@@ -99,6 +106,7 @@
icon_state = "Clown ore"
origin_tech = "materials=4"
points = 27
+ materials = list(MAT_BANANIUM=MINERAL_MATERIAL_AMOUNT)
refined_type = /obj/item/stack/sheet/mineral/bananium
/obj/item/weapon/ore/slag
@@ -121,6 +129,11 @@
var/attacher = "UNKNOWN"
var/datum/wires/explosive/gibtonite/wires
+/obj/item/weapon/twohanded/required/gibtonite/Destroy()
+ qdel(wires)
+ wires = null
+ return ..()
+
/obj/item/weapon/twohanded/required/gibtonite/attackby(obj/item/I, mob/user, params)
if(!wires && istype(I, /obj/item/device/assembly/igniter))
user.visible_message("[user] attaches [I] to [src].", "You attach [I] to [src].")
@@ -131,7 +144,7 @@
return
if(wires && !primed)
- if(istype(I, /obj/item/weapon/wirecutters) || istype(I, /obj/item/device/multitool) || istype(I, /obj/item/device/assembly/signaler))
+ if(wires.IsInteractionTool(I))
wires.Interact(user)
return
@@ -213,7 +226,7 @@
flags = CONDUCT
force = 1
throwforce = 2
- w_class = 1.0
+ w_class = 1
var/string_attached
var/list/sideslist = list("heads","tails")
var/cmineral = null
@@ -232,36 +245,43 @@
cmineral = "gold"
icon_state = "coin_gold_heads"
value = 160
+ materials = list(MAT_GOLD = 400)
/obj/item/weapon/coin/silver
cmineral = "silver"
icon_state = "coin_silver_heads"
value = 40
+ materials = list(MAT_SILVER = 400)
/obj/item/weapon/coin/diamond
cmineral = "diamond"
icon_state = "coin_diamond_heads"
value = 120
+ materials = list(MAT_DIAMOND = 400)
/obj/item/weapon/coin/iron
cmineral = "iron"
icon_state = "coin_iron_heads"
value = 20
+ materials = list(MAT_METAL = 400)
/obj/item/weapon/coin/plasma
cmineral = "plasma"
icon_state = "coin_plasma_heads"
value = 80
+ materials = list(MAT_PLASMA = 400)
/obj/item/weapon/coin/uranium
cmineral = "uranium"
icon_state = "coin_uranium_heads"
value = 160
+ materials = list(MAT_URANIUM = 400)
/obj/item/weapon/coin/clown
cmineral = "bananium"
icon_state = "coin_bananium_heads"
value = 600 //makes the clown cri
+ materials = list(MAT_BANANIUM = 400)
/obj/item/weapon/coin/adamantine
cmineral = "adamantine"
@@ -326,7 +346,9 @@
flick("coin_[cmineral]_flip", src)
icon_state = "coin_[cmineral]_[coinflip]"
playsound(user.loc, 'sound/items/coinflip.ogg', 50, 1)
- if(do_after(user, 15, target = src))
+ var/oldloc = loc
+ sleep(15)
+ if(loc == oldloc && user && !user.incapacitated())
user.visible_message("[user] has flipped [src]. It lands on [coinflip].", \
"You flip [src]. It lands on [coinflip].", \
"You hear the clattering of loose change.")
\ No newline at end of file
diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm
index 69f6cb9b558..eb3f4a6c8d0 100644
--- a/code/modules/mob/camera/camera.dm
+++ b/code/modules/mob/camera/camera.dm
@@ -14,10 +14,6 @@
/mob/camera/experience_pressure_difference()
return
-/mob/camera/Destroy()
- ..()
- del(src)
-
/mob/camera/Login()
..()
update_interface()
\ No newline at end of file
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 13ca44627a0..b6649aada21 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -69,7 +69,7 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi
qdel(ghostimage)
ghostimage = null
updateallghostimages()
- ..()
+ return ..()
/mob/dead/CanPass(atom/movable/mover, turf/target, height=0)
return 1
@@ -106,6 +106,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/Move(NewLoc, direct)
+ if (orbiting)
+ stop_orbit()
if(NewLoc)
loc = NewLoc
for(var/obj/effect/step_trigger/S in NewLoc)
@@ -158,12 +160,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(mind.current.key && copytext(mind.current.key,1,2)!="@") //makes sure we don't accidentally kick any clients
usr << "Another consciousness is in your body...It is resisting you."
return
- if(mind.current.ajourn && mind.current.stat != DEAD) //check if the corpse is astral-journeying (it's client ghosted using a cultist rune).
- var/obj/effect/rune/R = locate() in mind.current.loc //whilst corpse is alive, we can only reenter the body if it's on the rune
- if(!(R && R.word1 == wordhell && R.word2 == wordtravel && R.word3 == wordself)) //astral journeying rune
- usr << "The astral cord that ties your body and your spirit has been severed. You are likely to wander the realm beyond until your body is finally dead and thus reunited with you."
- return
- mind.current.ajourn=0
mind.current.key = key
return 1
@@ -200,8 +196,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/verb/follow()
set category = "Ghost"
- set name = "Follow" // "Haunt"
- set desc = "Follow and haunt a mob."
+ set name = "Orbit" // "Haunt"
+ set desc = "Follow and orbit a mob."
var/list/mobs = getmobs()
var/input = input("Please, select a mob!", "Haunt", null, null) as null|anything in mobs
@@ -211,22 +207,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
// This is the ghost's follow verb with an argument
/mob/dead/observer/proc/ManualFollow(atom/movable/target)
if(target && target != src)
- if(following && following == target)
+ if(orbiting && orbiting == target)
return
- following = target
- src << "Now following [target]."
- spawn(0)
- var/turf/pos = get_turf(src)
- while(loc == pos && target && following == target && client)
- var/turf/T = get_turf(target)
- if(!T)
- break
- // To stop the ghost flickering.
- if(loc != T)
- loc = T
- pos = loc
- sleep(15)
- if (target == following) following = null
+ src << "Now orbiting [target]."
+ orbit(target,24,0)
/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak
@@ -377,4 +361,4 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(istype(target) && (target != src))
ManualFollow(target)
if(href_list["reenter"])
- reenter_corpse()
\ No newline at end of file
+ reenter_corpse()
diff --git a/code/modules/mob/interactive.dm b/code/modules/mob/interactive.dm
index 12d822561f4..3c24e017066 100644
--- a/code/modules/mob/interactive.dm
+++ b/code/modules/mob/interactive.dm
@@ -86,22 +86,14 @@
/mob/living/carbon/human/interactive/proc/random()
//this is here because this has no client/prefs/brain whatever.
- underwear = random_underwear(gender)
- skin_tone = random_skin_tone()
- hair_style = random_hair_style(gender)
- facial_hair_style = random_facial_hair_style(gender)
- hair_color = random_short_color()
- facial_hair_color = hair_color
- eye_color = "blue"
age = rand(AGE_MIN,AGE_MAX)
- ready_dna(src,random_blood_type())
//job handling
var/list/jobs = SSjob.occupations
for(var/datum/job/J in jobs)
if(J.title == "Cyborg" || J.title == "AI" || J.title == "Chaplain" || J.title == "Mime")
jobs -= J
myjob = pick(jobs)
- src.job = myjob.title
+ job = myjob.title
if(!graytide)
myjob.equip(src)
myjob.apply_fingerprints(src)
@@ -120,25 +112,18 @@
/mob/living/carbon/human/interactive/New()
..()
- gender = pick(MALE,FEMALE)
- if(gender == MALE)
- name = "[pick(first_names_male)] [pick(last_names)]"
- real_name = name
- else
- name = "[pick(first_names_female)] [pick(last_names)]"
- real_name = name
random()
MYID = new(src)
MYID.name = "[src.real_name]'s ID Card ([myjob.title])"
MYID.assignment = "[myjob.title]"
MYID.registered_name = src.real_name
MYID.access = myjob.access
- src.equip_to_slot_or_del(MYID, slot_wear_id)
+ equip_to_slot_or_del(MYID, slot_wear_id)
MYPDA = new(src)
- MYPDA.owner = src.real_name
+ MYPDA.owner = real_name
MYPDA.ownjob = "Crew"
- MYPDA.name = "PDA-[src.real_name] ([myjob.title])"
- src.equip_to_slot_or_del(MYPDA, slot_belt)
+ MYPDA.name = "PDA-[real_name] ([myjob.title])"
+ equip_to_slot_or_del(MYPDA, slot_belt)
zone_sel = new /obj/screen/zone_sel()
zone_sel.selecting = "chest"
if(prob(10)) //my x is augmented
@@ -186,7 +171,7 @@
if(TRAITS & TRAIT_SMART)
smartness = 25
else if(TRAITS & TRAIT_DUMB)
- mutations |= CLUMSY
+ disabilities |= CLUMSY
smartness = 75
if(TRAITS & TRAIT_MEAN)
@@ -293,7 +278,9 @@
/mob/living/carbon/human/interactive/Life()
..()
- if(isnotfunc()) return
+ if(isnotfunc())
+ walk(src,0)
+ return
if(a_intent != "disarm")
a_intent = "disarm"
//---------------------------
@@ -369,9 +356,7 @@
if(!l_hand || !r_hand)
var/obj/item/clothing/C = TARGET
take_to_slot(C)
- if(equip_to_appropriate_slot(C))
- C.update_icon()
- else
+ if(!equip_to_appropriate_slot(C))
var/obj/item/I = get_item_by_slot(C)
unEquip(I)
equip_to_appropriate_slot(C)
@@ -382,7 +367,6 @@
equip_to_appropriate_slot(MYPDA)
if(MYID in src.loc)
equip_to_appropriate_slot(MYID)
- update_icons()
//THIEVING SKILLS END
//-------------TOUCH ME
if(istype(TARGET,/obj/structure))
diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm
index 3283c0ebb4f..38c89f9a3c9 100644
--- a/code/modules/mob/living/bloodcrawl.dm
+++ b/code/modules/mob/living/bloodcrawl.dm
@@ -1,91 +1,6 @@
-//Travel through pools of blood. Slaughter Demon powers for everyone!
-
#define BLOODCRAWL 1
#define BLOODCRAWL_EAT 2
-/mob/living/proc/phaseout(obj/effect/decal/cleanable/B)
- var/mob/living/kidnapped = null
- var/turf/mobloc = get_turf(src.loc)
- var/turf/bloodloc = get_turf(B.loc)
- if(Adjacent(bloodloc))
- src.notransform = TRUE
- spawn(0)
- src.visible_message("[src] sinks into the pool of blood.")
- playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1)
- var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,mobloc)
- src.ExtinguishMob()
- if(src.buckled)
- src.buckled.unbuckle_mob()
- if(src.pulling && src.bloodcrawl == BLOODCRAWL_EAT)
- if(istype(src.pulling, /mob/living))
- var/mob/living/victim = src.pulling
- if(victim.stat == CONSCIOUS)
- src.visible_message("[victim] kicks free of the [src] at the last second!")
- else
- victim.loc = holder
- src.visible_message("The [src] drags [victim] into the pool of blood!")
- kidnapped = victim
- src.loc = holder
- src.holder = holder
- if(kidnapped)
- src << "You begin to feast on [kidnapped]. You can not move while you are doing this."
- playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
- sleep(30)
- playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
- sleep(30)
- playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
- sleep(30)
- src << "You devour [kidnapped]. Your health is fully restored."
- src.adjustBruteLoss(-1000)
- src.adjustFireLoss(-1000)
- src.adjustOxyLoss(-1000)
- src.adjustToxLoss(-1000)
- kidnapped.ghostize()
- qdel(kidnapped)
- src.notransform = 0
-
-/mob/living/proc/phasein(obj/effect/decal/cleanable/B)
- if(src.notransform)
- src << "Finish eating first!"
- else
- src.loc = B.loc
- src.client.eye = src
- src.visible_message("The [src] rises out of the pool of blood!")
- playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
- qdel(src.holder)
- src.holder = null
-
-/obj/effect/decal/cleanable/blood/CtrlClick(mob/living/user)
- ..()
- if(user.bloodcrawl)
- if(user.holder)
- user.phasein(src)
- else
- user.phaseout(src)
-
-
-/obj/effect/decal/cleanable/trail_holder/CtrlClick(mob/living/user)
- ..()
- if(user.bloodcrawl)
- if(user.holder)
- user.phasein(src)
- else
- user.phaseout(src)
-
-
-
-/turf/CtrlClick(var/mob/living/user)
- ..()
- if(user.bloodcrawl)
- for(var/obj/effect/decal/cleanable/B in src.contents)
- if(istype(B, /obj/effect/decal/cleanable/blood) || istype(B, /obj/effect/decal/cleanable/trail_holder))
- if(user.holder)
- user.phasein(B)
- break
- else
- user.phaseout(B)
- break
-
/obj/effect/dummy/slaughter //Can't use the wizard one, blocked by jaunt/slow
name = "water"
icon = 'icons/effects/effects.dmi'
@@ -113,3 +28,100 @@ obj/effect/dummy/slaughter/relaymove(mob/user, direction)
/obj/effect/dummy/slaughter/Destroy()
return QDEL_HINT_PUTINPOOL
+
+
+/mob/living/proc/phaseout(obj/effect/decal/cleanable/B)
+ if(iscarbon(src))
+ var/mob/living/carbon/C = src
+ if(C.l_hand || C.r_hand)
+ C << "You may not hold items while blood crawling!"
+ return 0
+ var/obj/item/weapon/bloodcrawl/B1 = new(C)
+ var/obj/item/weapon/bloodcrawl/B2 = new(C)
+ B1.icon_state = "bloodhand_left"
+ B2.icon_state = "bloodhand_right"
+ C.put_in_hands(B1)
+ C.put_in_hands(B2)
+ C.regenerate_icons()
+ var/mob/living/kidnapped = null
+ var/turf/mobloc = get_turf(src.loc)
+ src.notransform = TRUE
+ spawn(0)
+ src.visible_message("[src] sinks into the pool of blood!")
+ playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1)
+ var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,mobloc)
+ src.ExtinguishMob()
+ if(src.buckled)
+ src.buckled.unbuckle_mob()
+ if(src.pulling && src.bloodcrawl == BLOODCRAWL_EAT)
+ if(istype(src.pulling, /mob/living))
+ var/mob/living/victim = src.pulling
+ if(victim.stat == CONSCIOUS)
+ src.visible_message("[victim] kicks free of the blood pool just before entering it!")
+ else
+ victim.loc = holder
+ victim.emote("scream")
+ src.visible_message("[src] drags [victim] into the pool of blood!")
+ kidnapped = victim
+ src.loc = holder
+ src.holder = holder
+ if(kidnapped)
+ src << "You begin to feast on [kidnapped]. You can not move while you are doing this."
+ for(var/i = 3; i > 0; i--)
+ playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
+ sleep(30)
+ if(kidnapped)
+ src << "You devour [kidnapped]. Your health is fully restored."
+ src.adjustBruteLoss(-1000)
+ src.adjustFireLoss(-1000)
+ src.adjustOxyLoss(-1000)
+ src.adjustToxLoss(-1000)
+ if(istype(src, /mob/living/simple_animal/slaughter))
+ var/mob/living/simple_animal/slaughter/S = src
+ kidnapped << "You feel teeth sink into your flesh, and the--"
+ kidnapped.adjustBruteLoss(1000)
+ kidnapped.loc = src
+ S.consumed_mobs.Add(kidnapped)
+ else
+ kidnapped.ghostize()
+ qdel(kidnapped)
+ else
+ src << "You happily devour... nothing? Your meal vanished at some point!"
+ src.notransform = 0
+ return 1
+
+/obj/item/weapon/bloodcrawl
+ name = "blood crawl"
+ desc = "You are unable to hold anything while in this form."
+ icon = 'icons/effects/blood.dmi'
+ flags = NODROP
+
+/mob/living/proc/phasein(obj/effect/decal/cleanable/B)
+ if(src.notransform)
+ src << "Finish eating first!"
+ return 0
+ B.visible_message("[B] starts to bubble...")
+ if(!do_after(src, 20, target = B))
+ return
+ if(!B)
+ return
+ src.loc = B.loc
+ src.client.eye = src
+ src.visible_message("[src] rises out of the pool of blood!")
+ playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
+ if(iscarbon(src))
+ var/mob/living/carbon/C = src
+ for(var/obj/item/weapon/bloodcrawl/BC in C)
+ C.flags = null
+ C.unEquip(BC)
+ qdel(BC)
+ var/oldcolor = src.color
+ if(istype(B, /obj/effect/decal/cleanable/xenoblood)) //Makes the mob have the color of the blood pool it came out of for a few seconds
+ src.color = rgb(43, 186, 0)
+ else
+ src.color = rgb(149, 10, 10)
+ qdel(src.holder)
+ src.holder = null
+ spawn(30)
+ src.color = oldcolor
+ return 1
diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm
index e2adcf9323b..15d859a83fd 100644
--- a/code/modules/mob/living/carbon/alien/alien.dm
+++ b/code/modules/mob/living/carbon/alien/alien.dm
@@ -93,16 +93,16 @@
..()
switch (severity)
- if (1.0)
+ if (1)
gib()
return
- if (2.0)
+ if (2)
adjustBruteLoss(60)
adjustFireLoss(60)
adjustEarDamage(30,120)
- if(3.0)
+ if(3)
adjustBruteLoss(30)
if (prob(50))
Paralyse(1)
@@ -149,9 +149,10 @@ Des: Gives the client of the alien an image on each infected mob.
if (client)
for (var/mob/living/C in mob_list)
if(C.status_flags & XENO_HOST)
- var/obj/item/organ/internal/body_egg/alien_embryo/A = getorgan(/obj/item/organ/internal/body_egg/alien_embryo)
- var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[A.stage]")
- client.images += I
+ var/obj/item/organ/internal/body_egg/alien_embryo/A = C.getorgan(/obj/item/organ/internal/body_egg/alien_embryo)
+ if(A)
+ var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[A.stage]")
+ client.images += I
return
diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm
index fd3fff64a4b..20577531b27 100644
--- a/code/modules/mob/living/carbon/alien/alien_defense.dm
+++ b/code/modules/mob/living/carbon/alien/alien_defense.dm
@@ -73,7 +73,19 @@ In all, this is a lot like the monkey code. /N
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
- adjustBruteLoss(damage)
+ switch(M.melee_damage_type)
+ if(BRUTE)
+ adjustBruteLoss(damage)
+ if(BURN)
+ adjustFireLoss(damage)
+ if(TOX)
+ adjustToxLoss(damage)
+ if(OXY)
+ adjustOxyLoss(damage)
+ if(CLONE)
+ adjustCloneLoss(damage)
+ if(STAMINA)
+ adjustStaminaLoss(damage)
updatehealth()
/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M)
diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
index f4e62fdaf7c..a49d8cd2dcf 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
@@ -1,8 +1,8 @@
/mob/living/carbon/alien/humanoid/hunter
name = "alien hunter"
caste = "h"
- maxHealth = 150
- health = 150
+ maxHealth = 125
+ health = 125
icon_state = "alienh_s"
/mob/living/carbon/alien/humanoid/hunter/New()
@@ -88,10 +88,16 @@
if(A)
if(istype(A, /mob/living))
var/mob/living/L = A
- L.visible_message("[src] pounces on [L]!", "[src] pounces on you!")
- L.Weaken(5)
- sleep(2)//Runtime prevention (infinite bump() calls on hulks)
- step_towards(src,L)
+ var/blocked = 0
+ if(ishuman(A))
+ var/mob/living/carbon/human/H = A
+ if(H.check_shields(90, "the [name]", src, 1))
+ blocked = 1
+ if(!blocked)
+ L.visible_message("[src] pounces on [L]!", "[src] pounces on you!")
+ L.Weaken(5)
+ sleep(2)//Runtime prevention (infinite bump() calls on hulks)
+ step_towards(src,L)
toggle_leap(0)
pounce_cooldown = !pounce_cooldown
diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm
index 9194dafe2b6..aa86fe90a52 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm
@@ -1,8 +1,8 @@
/mob/living/carbon/alien/humanoid/sentinel
name = "alien sentinel"
caste = "s"
- maxHealth = 125
- health = 125
+ maxHealth = 150
+ health = 150
icon_state = "aliens_s"
@@ -35,4 +35,3 @@
/mob/living/carbon/alien/humanoid/sentinel/movement_delay()
. = ..()
- . += 1
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/alien/humanoid/emote.dm b/code/modules/mob/living/carbon/alien/humanoid/emote.dm
index 5270fdabb6d..6129dd7ef77 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/emote.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/emote.dm
@@ -1,4 +1,4 @@
-/mob/living/carbon/alien/humanoid/emote(act)
+/mob/living/carbon/alien/humanoid/emote(act,m_type=1,message = null)
var/param = null
if (findtext(act, "-", 1, null))
@@ -7,8 +7,6 @@
act = copytext(act, 1, t1)
var/muzzled = is_muzzled()
- var/m_type = 1
- var/message
switch(act) //Alphabetical please
if ("deathgasp","deathgasps")
@@ -25,6 +23,10 @@
message = "[src] hisses."
m_type = 2
+ if ("me")
+ ..()
+ return
+
if ("moan","moans")
message = "[src] moans!"
m_type = 2
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
index a3e1ff31665..b5bbee5eb4c 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
@@ -2,6 +2,7 @@
name = "alien"
icon_state = "alien_s"
pass_flags = PASSTABLE
+ butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
var/obj/item/r_store = null
var/obj/item/l_store = null
var/caste = ""
@@ -14,7 +15,6 @@
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/humanoid/New()
- create_reagents(1000)
AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null))
..()
diff --git a/code/modules/mob/living/carbon/alien/humanoid/queen.dm b/code/modules/mob/living/carbon/alien/humanoid/queen.dm
index 03745eb7306..540fc3874fd 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/queen.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/queen.dm
@@ -10,8 +10,6 @@
/mob/living/carbon/alien/humanoid/queen/New()
- create_reagents(100)
-
//there should only be one queen
for(var/mob/living/carbon/alien/humanoid/queen/Q in living_mob_list)
if(Q == src) continue
@@ -77,17 +75,3 @@
icon_state = "queen_s"
pixel_x = -16
mob_size = MOB_SIZE_LARGE
-
-/mob/living/carbon/alien/humanoid/queen/large/update_icons()
- update_hud() //TODO: remove the need for this to be here
- overlays.Cut()
- if(stat == DEAD)
- icon_state = "queen_dead"
- else if((stat == UNCONSCIOUS && !sleeping) || weakened)
- icon_state = "queen_l"
- else if(sleeping || lying || resting)
- icon_state = "queen_sleep"
- else
- icon_state = "queen_s"
- for(var/image/I in overlays_standing)
- overlays += I
diff --git a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm
index 1495d4f99d3..de272e0c0d7 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm
@@ -50,4 +50,29 @@
if(lying > 0)
lying = 90 //Anything else looks retarded
..()
- update_icons()
\ No newline at end of file
+ update_icons()
+
+
+/mob/living/carbon/alien/humanoid/queen/large/update_icons()
+ update_hud() //TODO: remove the need for this to be here
+ overlays.Cut()
+ if(stat == DEAD)
+ icon_state = "queen_dead"
+ else if((stat == UNCONSCIOUS && !sleeping) || weakened)
+ icon_state = "queen_l"
+ else if(sleeping || lying || resting)
+ icon_state = "queen_sleep"
+ else
+ icon_state = "queen_s"
+ for(var/image/I in overlays_standing)
+ overlays += I
+
+/mob/living/carbon/alien/humanoid/queen/large/update_inv_l_hand()
+ remove_overlay(L_HAND_LAYER)
+ if(handcuffed)
+ drop_l_hand()
+
+/mob/living/carbon/alien/humanoid/queen/large/update_inv_r_hand()
+ remove_overlay(R_HAND_LAYER)
+ if(handcuffed)
+ drop_r_hand()
diff --git a/code/modules/mob/living/carbon/alien/larva/powers.dm b/code/modules/mob/living/carbon/alien/larva/powers.dm
index 3bc9e44a910..3f9cb657498 100644
--- a/code/modules/mob/living/carbon/alien/larva/powers.dm
+++ b/code/modules/mob/living/carbon/alien/larva/powers.dm
@@ -40,9 +40,9 @@
if(L.amount_grown >= L.max_grown) //TODO ~Carn
L << "You are growing into a beautiful alien! It is time to choose a caste."
L << "There are three to choose from:"
- L << "Huntersare strong and agile, able to hunt away from the hive and rapidly move through ventilation shafts. Hunters generate plasma slowly and have low reserves."
- L << "Sentinelsare tasked with protecting the hive and are deadly up close and at a range. They are not as physically imposing nor fast as the hunters."
- L << "Dronesare the working class, offering the largest plasma storage and generation. They are the only caste which may evolve again, turning into the dreaded alien queen."
+ L << "Huntersare the most agile caste tasked with hunting for hosts. They are faster than a human and can even pounce, but are not much tougher than a drone."
+ L << "Sentinelsare tasked with protecting the hive. With their ranged spit, invisibility, and high health, they make formidable guardians and acceptable secondhand hunters."
+ L << "Dronesare the weakest and slowest of the castes, but can grow into the queen if there is none, and are vital to maintaining a hive with their resin secretion abilities."
var/alien_caste = alert(L, "Please choose which alien caste you shall belong to.",,"Hunter","Sentinel","Drone")
var/mob/living/carbon/alien/humanoid/new_xeno
diff --git a/code/modules/mob/living/carbon/alien/larva/update_icons.dm b/code/modules/mob/living/carbon/alien/larva/update_icons.dm
index dba2774866a..b12a2b766b6 100644
--- a/code/modules/mob/living/carbon/alien/larva/update_icons.dm
+++ b/code/modules/mob/living/carbon/alien/larva/update_icons.dm
@@ -24,5 +24,5 @@
/mob/living/carbon/alien/larva/update_transform() //All this is handled in update_icons()
return update_icons()
-/mob/living/carbon/larva/update_inv_handcuffed()
+/mob/living/carbon/alien/larva/update_inv_handcuffed()
return
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm
index b7db238a99a..8e64f7820cc 100644
--- a/code/modules/mob/living/carbon/alien/organs.dm
+++ b/code/modules/mob/living/carbon/alien/organs.dm
@@ -1,6 +1,5 @@
/obj/item/organ/internal/alien
origin_tech = "biotech=5"
- icon = 'icons/effects/blood.dmi'
icon_state = "xgibmid2"
var/list/alien_powers = list()
@@ -30,6 +29,7 @@
/obj/item/organ/internal/alien/plasmavessel
name = "plasma vessel"
+ icon_state = "plasma"
origin_tech = "biotech=5;plasma=2"
w_class = 3
zone = "chest"
@@ -48,6 +48,7 @@
/obj/item/organ/internal/alien/plasmavessel/large
name = "large plasma vessel"
+ icon_state = "plasma_large"
w_class = 4
storedPlasma = 200
max_plasma = 500
@@ -59,6 +60,7 @@
/obj/item/organ/internal/alien/plasmavessel/small
name = "small plasma vessel"
+ icon_state = "plasma_small"
w_class = 2
storedPlasma = 100
max_plasma = 150
@@ -66,6 +68,7 @@
/obj/item/organ/internal/alien/plasmavessel/small/tiny
name = "tiny plasma vessel"
+ icon_state = "plasma_tiny"
w_class = 1
max_plasma = 100
alien_powers = list(/obj/effect/proc_holder/alien/transfer)
@@ -73,15 +76,17 @@
/obj/item/organ/internal/alien/plasmavessel/on_life()
//If there are alien weeds on the ground then heal if needed or give some plasma
if(locate(/obj/structure/alien/weeds) in owner.loc)
- if(owner.health >= owner.maxHealth - owner.getCloneLoss())
+ if(owner.health >= owner.maxHealth)
owner.adjustPlasma(plasma_rate)
else
- var/mod = 1
+ var/heal_amt = heal_rate
if(!isalien(owner))
- mod = 0.2
- owner.adjustBruteLoss(-heal_rate*mod)
- owner.adjustFireLoss(-heal_rate*mod)
- owner.adjustOxyLoss(-heal_rate*mod)
+ heal_amt *= 0.2
+ owner.adjustPlasma(plasma_rate*0.5)
+ owner.adjustBruteLoss(-heal_amt)
+ owner.adjustFireLoss(-heal_amt)
+ owner.adjustOxyLoss(-heal_amt)
+ owner.adjustCloneLoss(-heal_amt)
/obj/item/organ/internal/alien/plasmavessel/Insert(mob/living/carbon/M, special = 0)
..()
@@ -98,6 +103,7 @@
/obj/item/organ/internal/alien/hivenode
name = "hive node"
+ icon_state = "hivenode"
zone = "head"
slot = "hivenode"
origin_tech = "biotech=5;magnets=4;bluespace=3"
@@ -115,6 +121,7 @@
/obj/item/organ/internal/alien/resinspinner
name = "resin spinner"
+ icon_state = "stomach-x"
zone = "mouth"
slot = "resinspinner"
origin_tech = "biotech=5;materials=4"
@@ -123,6 +130,7 @@
/obj/item/organ/internal/alien/acid
name = "acid gland"
+ icon_state = "acid"
zone = "mouth"
slot = "acidgland"
origin_tech = "biotech=5;materials=2;combat=2"
@@ -131,6 +139,7 @@
/obj/item/organ/internal/alien/neurotoxin
name = "neurotoxin gland"
+ icon_state = "neurotox"
zone = "mouth"
slot = "neurotoxingland"
origin_tech = "biotech=5;combat=5"
@@ -139,6 +148,7 @@
/obj/item/organ/internal/alien/eggsac
name = "egg sac"
+ icon_state = "eggsac"
zone = "groin"
slot = "eggsac"
w_class = 4
diff --git a/code/modules/mob/living/carbon/alien/say.dm b/code/modules/mob/living/carbon/alien/say.dm
index a674add3ff1..387c67ec242 100644
--- a/code/modules/mob/living/carbon/alien/say.dm
+++ b/code/modules/mob/living/carbon/alien/say.dm
@@ -3,16 +3,20 @@
if(.)
playsound(loc, "hiss", 25, 1, 1) //erp just isn't the same without sound feedback
-/mob/living/proc/alien_talk(message)
+/mob/living/proc/alien_talk(message, shown_name = name)
log_say("[key_name(src)] : [message]")
message = trim(message)
if(!message) return
- var/message_a = say_quote(message)
- var/rendered = "Hivemind, [name][message_a]"
+ var/message_a = say_quote(message, get_spans())
+ var/rendered = "Hivemind, [shown_name][message_a]"
for(var/mob/S in player_list)
if((!S.stat && S.hivecheck()) || (S in dead_mob_list))
S << rendered
+/mob/living/carbon/alien/humanoid/queen/alien_talk(message, shown_name = name)
+ shown_name = "[shown_name]"
+ ..(message, shown_name)
+
/mob/living/carbon/hivecheck()
return getorgan(/obj/item/organ/internal/alien/hivenode)
diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
index 6995c025b0e..bb7abd6f7f9 100644
--- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
+++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
@@ -57,6 +57,10 @@ var/const/ALIEN_AFK_BRACKET = 450 // 45 seconds
RefreshInfectionImage()
if(stage == 5 && prob(50))
+ for(var/datum/surgery/S in owner.surgeries)
+ if(S.location == "chest" && istype(S.get_surgery_step(), /datum/surgery_step/manipulate_organs))
+ AttemptGrow(0)
+ return
AttemptGrow()
@@ -79,10 +83,8 @@ var/const/ALIEN_AFK_BRACKET = 450 // 45 seconds
stage = 4 // Let's try again later.
return
- if(owner.lying)
- owner.overlays += image('icons/mob/alien.dmi', loc = owner, icon_state = "burst_lie")
- else
- owner.overlays += image('icons/mob/alien.dmi', loc = owner, icon_state = "burst_stand")
+ var/overlay = image('icons/mob/alien.dmi', loc = owner, icon_state = "burst_lie")
+ owner.overlays += overlay
spawn(6)
var/atom/xeno_loc = owner
if(!gib_on_success)
@@ -94,6 +96,9 @@ var/const/ALIEN_AFK_BRACKET = 450 // 45 seconds
if(gib_on_success)
owner.stomach_contents += new_xeno
owner.gib()
+ else
+ owner.adjustBruteLoss(40)
+ owner.overlays -= overlay
qdel(src)
diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm
index 4c2aee91be8..8253084dc46 100644
--- a/code/modules/mob/living/carbon/alien/special/facehugger.dm
+++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm
@@ -19,6 +19,7 @@ var/const/MAX_ACTIVE_TIME = 400
throw_range = 5
tint = 3
flags_cover = MASKCOVERSEYES | MASKCOVERSMOUTH
+ layer = MOB_LAYER
var/stat = CONSCIOUS //UNCONSCIOUS is the idle state in this case
@@ -177,7 +178,7 @@ var/const/MAX_ACTIVE_TIME = 400
Die()
icon_state = "[initial(icon_state)]_impregnated"
- if(!target.getlimb(/obj/item/organ/limb/robot/chest) && !(target.status_flags & XENO_HOST))
+ if(!target.getlimb(/obj/item/organ/limb/robot/chest) && !target.getorgan(/obj/item/organ/internal/body_egg/alien_embryo))
new /obj/item/organ/internal/body_egg/alien_embryo(target)
if(iscorgi(target))
@@ -187,7 +188,6 @@ var/const/MAX_ACTIVE_TIME = 400
else
target.visible_message("[src] violates [target]'s face!", \
"[src] violates [target]'s face!")
- return
/obj/item/clothing/mask/facehugger/proc/GoActive()
if(stat == DEAD || stat == CONSCIOUS)
@@ -196,20 +196,10 @@ var/const/MAX_ACTIVE_TIME = 400
stat = CONSCIOUS
icon_state = "[initial(icon_state)]"
-/* for(var/mob/living/carbon/alien/alien in world)
- var/image/activeIndicator = image('icons/mob/alien.dmi', loc = src, icon_state = "facehugger_active")
- activeIndicator.override = 1
- if(alien && alien.client)
- alien.client.images += activeIndicator */
-
- return
-
/obj/item/clothing/mask/facehugger/proc/GoIdle()
if(stat == DEAD || stat == UNCONSCIOUS)
return
-/* RemoveActiveIndicators() */
-
stat = UNCONSCIOUS
icon_state = "[initial(icon_state)]_inactive"
@@ -221,15 +211,12 @@ var/const/MAX_ACTIVE_TIME = 400
if(stat == DEAD)
return
-/* RemoveActiveIndicators() */
-
icon_state = "[initial(icon_state)]_dead"
+ item_state = "facehugger_inactive"
stat = DEAD
visible_message("[src] curls up into a ball!")
- return
-
/proc/CanHug(mob/living/M)
if(!istype(M))
return 0
diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm
index a7360f8ef65..c762338f038 100644
--- a/code/modules/mob/living/carbon/brain/MMI.dm
+++ b/code/modules/mob/living/carbon/brain/MMI.dm
@@ -85,15 +85,19 @@
update_icon()
name = "Man-Machine Interface"
-/obj/item/device/mmi/proc/transfer_identity(mob/living/carbon/human/H) //Same deal as the regular brain proc. Used for human-->robot people.
+/obj/item/device/mmi/proc/transfer_identity(mob/living/L) //Same deal as the regular brain proc. Used for human-->robot people.
brainmob = new(src)
- brainmob.name = H.real_name
- brainmob.real_name = H.real_name
- if(check_dna_integrity(H))
- brainmob.dna = H.dna
+ brainmob.name = L.real_name
+ brainmob.real_name = L.real_name
+ if(L.has_dna())
+ var/mob/living/carbon/C = L
+ if(!brainmob.dna)
+ brainmob.dna = new /datum/dna(brainmob)
+ C.dna.copy_dna(brainmob.dna)
brainmob.container = src
- if(istype(H))
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
var/obj/item/organ/internal/brain/newbrain = H.getorgan(/obj/item/organ/internal/brain)
newbrain.loc = src
brain = newbrain
@@ -147,7 +151,7 @@
if(brainmob)
qdel(brainmob)
brainmob = null
- ..()
+ return ..()
/obj/item/device/mmi/examine(mob/user)
..()
diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/carbon/brain/brain.dm
index 3eec0aa657d..48b71893397 100644
--- a/code/modules/mob/living/carbon/brain/brain.dm
+++ b/code/modules/mob/living/carbon/brain/brain.dm
@@ -8,16 +8,12 @@
var/alert = null
has_limbs = 0
-/mob/living/carbon/brain/New()
- create_reagents(1000)
- ..()
-
/mob/living/carbon/brain/Destroy()
if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting.
if(stat!=DEAD) //If not dead.
death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA
ghostize() //Ghostize checks for key so nothing else is necessary.
- ..()
+ return ..()
/mob/living/carbon/brain/update_canmove()
if(in_contents_of(/obj/mecha)) canmove = 1
diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm
index 21e701b4940..031989bd3f0 100644
--- a/code/modules/mob/living/carbon/brain/brain_item.dm
+++ b/code/modules/mob/living/carbon/brain/brain_item.dm
@@ -26,10 +26,10 @@
qdel(brainmob)
- //Update the body's icon so it doesnt appear debrained anymore
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- H.update_hair(0)
+ //Update the body's icon so it doesnt appear debrained anymore
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ H.update_hair(0)
/obj/item/organ/internal/brain/Remove(mob/living/carbon/M, special = 0)
..()
@@ -56,9 +56,11 @@
brainmob.name = L.real_name
brainmob.real_name = L.real_name
brainmob.timeofhostdeath = L.timeofdeath
- if(iscarbon(L))
+ if(L.has_dna())
var/mob/living/carbon/C = L
- brainmob.dna = C.dna
+ if(!brainmob.dna)
+ brainmob.dna = new /datum/dna(brainmob)
+ C.dna.copy_dna(brainmob.dna)
if(L.mind)
L.mind.transfer_to(brainmob)
brainmob << "You feel slightly disoriented. That's normal when you're just a brain."
@@ -112,10 +114,10 @@
if(brainmob)
qdel(brainmob)
brainmob = null
- ..()
+ return ..()
/obj/item/organ/internal/brain/alien
name = "alien brain"
desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?"
- icon_state = "brain-alien"
+ icon_state = "brain-x"
origin_tech = "biotech=7"
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/brain/life.dm b/code/modules/mob/living/carbon/brain/life.dm
index eb8dc6e9c65..cb16be5dc03 100644
--- a/code/modules/mob/living/carbon/brain/life.dm
+++ b/code/modules/mob/living/carbon/brain/life.dm
@@ -45,12 +45,12 @@
if(status_flags & GODMODE) return
if(exposed_temperature > bodytemperature)
- var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0)
- adjustFireLoss(20.0*discomfort)
+ var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1)
+ adjustFireLoss(20*discomfort)
else
- var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0)
- adjustFireLoss(5.0*discomfort)
+ var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1)
+ adjustFireLoss(5*discomfort)
/mob/living/carbon/brain/handle_regular_status_updates() //TODO: comment out the unused bits >_>
diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm
index 7f8445b95fc..5796e870ac8 100644
--- a/code/modules/mob/living/carbon/brain/posibrain.dm
+++ b/code/modules/mob/living/carbon/brain/posibrain.dm
@@ -55,17 +55,21 @@ var/global/posibrain_notif_cooldown = 0
return
transfer_personality(user)
-/obj/item/device/mmi/posibrain/transfer_identity(mob/living/carbon/H)
- name = "positronic brain ([H])"
- brainmob.name = H.real_name
- brainmob.real_name = H.real_name
- brainmob.dna = H.dna
- brainmob.timeofhostdeath = H.timeofdeath
+/obj/item/device/mmi/posibrain/transfer_identity(mob/living/carbon/C)
+ name = "positronic brain ([C])"
+ brainmob.name = C.real_name
+ brainmob.real_name = C.real_name
+ brainmob.dna = C.dna
+ if(C.has_dna())
+ if(!brainmob.dna)
+ brainmob.dna = new /datum/dna(brainmob)
+ C.dna.copy_dna(brainmob.dna)
+ brainmob.timeofhostdeath = C.timeofdeath
brainmob.stat = 0
if(brainmob.mind)
brainmob.mind.assigned_role = "Positronic Brain"
- if(H.mind)
- H.mind.transfer_to(brainmob)
+ if(C.mind)
+ C.mind.transfer_to(brainmob)
brainmob.mind.remove_all_antag()
brainmob.mind.wipe_memory()
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 9dbf026e3c2..ff959f6c940 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -1,3 +1,7 @@
+/mob/living/carbon/New()
+ create_reagents(1000)
+ ..()
+
/mob/living/carbon/prepare_huds()
..()
prepare_data_huds()
@@ -18,6 +22,8 @@
for(var/atom/movable/food in stomach_contents)
qdel(food)
remove_from_all_data_huds()
+ if(dna)
+ qdel(dna)
return ..()
/mob/living/carbon/Move(NewLoc, direct)
@@ -74,9 +80,9 @@
. = ..()
-/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0)
+/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, override = 0)
shock_damage *= siemens_coeff
- if (shock_damage<1)
+ if(shock_damage<1 && !override)
return 0
take_overall_damage(0,shock_damage)
//src.burn_skin(shock_damage)
@@ -95,7 +101,10 @@
jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less
Stun(3)
Weaken(3)
- return shock_damage
+ if(override)
+ return override
+ else
+ return shock_damage
/mob/living/carbon/swap_hand()
@@ -335,11 +344,10 @@
return "trails_2"
var/const/NO_SLIP_WHEN_WALKING = 1
-var/const/STEP = 2
-var/const/SLIDE = 4
-var/const/GALOSHES_DONT_HELP = 8
+var/const/SLIDE = 2
+var/const/GALOSHES_DONT_HELP = 4
/mob/living/carbon/slip(s_amount, w_amount, obj/O, lube)
- loc.handle_slip(src, s_amount, w_amount, O, lube)
+ return loc.handle_slip(src, s_amount, w_amount, O, lube)
/mob/living/carbon/fall(forced)
loc.handle_fall(src, forced)//it's loc so it doesn't call the mob's handle_fall which does nothing
@@ -505,7 +513,7 @@ var/const/GALOSHES_DONT_HELP = 8
return 1
/mob/living/carbon/proc/accident(obj/item/I)
- if(!I || (I.flags & NODROP))
+ if(!I || (I.flags & (NODROP|ABSTRACT)))
return
unEquip(I)
@@ -573,4 +581,7 @@ var/const/GALOSHES_DONT_HELP = 8
var/obj/item/organ/internal/alien/plasmavessel/vessel = getorgan(/obj/item/organ/internal/alien/plasmavessel)
if(vessel)
stat(null, "Plasma Stored: [vessel.storedPlasma]/[vessel.max_plasma]")
+ if(locate(/obj/item/device/assembly/health) in src)
+ stat(null, "Health: [health]")
+
add_abilities_to_panel()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 80224f72e38..f4d46e02fc3 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -1,4 +1,4 @@
-/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = 1)
+/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0)
if(!skipcatch) //ugly, but easy
if(in_throw_mode && !get_active_hand()) //empty active hand and we're in throw mode
if(canmove && !restrained())
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index 580b0b5919d..89af6c2f4ca 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -9,9 +9,6 @@
var/obj/item/handcuffed = null //Whether or not the mob is handcuffed
var/obj/item/legcuffed = null //Same as handcuffs but for legs. Bear traps use this.
- var/list/features = list("mcolor" = "FFF", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None")
-
-
//inventory slots
var/obj/item/back = null
var/obj/item/clothing/mask/wear_mask = null
diff --git a/code/modules/mob/living/carbon/emote.dm b/code/modules/mob/living/carbon/emote.dm
index 2009c2bc5fe..1f1717517df 100644
--- a/code/modules/mob/living/carbon/emote.dm
+++ b/code/modules/mob/living/carbon/emote.dm
@@ -111,6 +111,11 @@
else
message = "[src] makes a noise."
+ if ("me")
+ if(!silent)
+ ..()
+ return
+
if ("nod","nods")
message = "[src] nods."
m_type = 1
diff --git a/code/modules/mob/living/carbon/monkey/examine.dm b/code/modules/mob/living/carbon/examine.dm
similarity index 60%
rename from code/modules/mob/living/carbon/monkey/examine.dm
rename to code/modules/mob/living/carbon/examine.dm
index 48963b00eed..1da6b212e10 100644
--- a/code/modules/mob/living/carbon/monkey/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -1,45 +1,61 @@
-/mob/living/carbon/monkey/examine(mob/user)
- var/msg = "*---------*\nThis is \icon[src] \a [src]!\n"
-
- if (src.handcuffed)
- msg += "It is \icon[src.handcuffed] handcuffed!\n"
- if (src.head)
- msg += "It has \icon[src.head] \a [src.head] on its head. \n"
- if (src.wear_mask)
- msg += "It has \icon[src.wear_mask] \a [src.wear_mask] on its face.\n"
- if (src.l_hand)
- msg += "It has \icon[src.l_hand] \a [src.l_hand] in its left hand.\n"
- if (src.r_hand)
- msg += "It has \icon[src.r_hand] \a [src.r_hand] in its right hand.\n"
- if (src.back)
- msg += "It has \icon[src.back] \a [src.back] on its back.\n"
- if (src.stat == DEAD)
- msg += "It is limp and unresponsive, with no signs of life.\n"
- else
- msg += ""
- if (src.getBruteLoss())
- if (src.getBruteLoss() < 30)
- msg += "It has minor bruising.\n"
- else
- msg += "It has severe bruising!\n"
- if (src.getFireLoss())
- if (src.getFireLoss() < 30)
- msg += "It has minor burns.\n"
- else
- msg += "It has severe burns!\n"
-
- if (src.fire_stacks > 0)
- msg += "It's covered in something flammable.\n"
- if (src.fire_stacks < 0)
- msg += "It's soaked in water.\n"
-
- if (src.stat == UNCONSCIOUS)
- msg += "It isn't responding to anything around it; it seems to be asleep.\n"
- msg += ""
-
- if (src.digitalcamo)
- msg += "It is moving its body in an unnatural and blatantly unsimian manner.\n"
-
- msg += "*---------*"
-
+/mob/living/carbon/examine(mob/user)
+ var/msg = "*---------*\nThis is \icon[src] \a [src]!\n"
+
+ if (handcuffed)
+ msg += "It is \icon[src.handcuffed] handcuffed!\n"
+ if (head)
+ msg += "It has \icon[src.head] \a [src.head] on its head. \n"
+ if (wear_mask)
+ msg += "It has \icon[src.wear_mask] \a [src.wear_mask] on its face.\n"
+ if (l_hand)
+ msg += "It has \icon[src.l_hand] \a [src.l_hand] in its left hand.\n"
+ if (r_hand)
+ msg += "It has \icon[src.r_hand] \a [src.r_hand] in its right hand.\n"
+ if (back)
+ msg += "It has \icon[src.back] \a [src.back] on its back.\n"
+ if (stat == DEAD)
+ msg += "It is limp and unresponsive, with no signs of life.\n"
+ else
+ msg += ""
+ var/temp = getBruteLoss()
+ if(temp)
+ if (temp < 30)
+ msg += "It has minor bruising.\n"
+ else
+ msg += "It has severe bruising!\n"
+
+ temp = getFireLoss()
+ if(temp)
+ if (temp < 30)
+ msg += "It has minor burns.\n"
+ else
+ msg += "It has severe burns!\n"
+
+ temp = getCloneLoss()
+ if(temp)
+ if(getCloneLoss() < 30)
+ msg += "It is slightly deformed.\n"
+ else
+ msg += "It is severely deformed.\n"
+
+ if(getBrainLoss() > 60)
+ msg += "It seems to be clumsy and unable to think.\n"
+
+ if(fire_stacks > 0)
+ msg += "It's covered in something flammable.\n"
+ if(fire_stacks < 0)
+ msg += "It's soaked in water.\n"
+
+ if(stat == UNCONSCIOUS)
+ msg += "It isn't responding to anything around it; it seems to be asleep.\n"
+ msg += ""
+
+ if(digitalcamo)
+ msg += "It is moving its body in an unnatural and blatantly unsimian manner.\n"
+
+ if(!getorgan(/obj/item/organ/internal/brain))
+ msg += "It appears that it's brain is missing...\n"
+
+ msg += "*---------*"
+
user << msg
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/blood.dm b/code/modules/mob/living/carbon/human/blood.dm
index d03805d7d22..86ab99bf505 100644
--- a/code/modules/mob/living/carbon/human/blood.dm
+++ b/code/modules/mob/living/carbon/human/blood.dm
@@ -272,17 +272,16 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
source = M.get_blood(M.vessel)
else if(istype(source,/mob/living/carbon/monkey))
var/mob/living/carbon/monkey/donor = source
- if(donor.dna)
- source = new()
- source.data["blood_DNA"] = donor.dna.unique_enzymes
- source.data["blood_type"] = donor.dna.blood_type
+ source = new()
+ source.data["blood_DNA"] = donor.dna.unique_enzymes
+ source.data["blood_type"] = donor.dna.blood_type
// Are we dripping or splattering?
var/list/drips = list()
// Only a certain number of drips (or one large splatter) can be on a given turf.
for(var/obj/effect/decal/cleanable/blood/drip/drop in T)
drips |= drop.drips
- del(drop)
+ qdel(drop)
if(!large && drips.len < 3)
decal_type = /obj/effect/decal/cleanable/blood/drip
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index 0e91f3f1d66..a24e880ed7a 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -8,10 +8,7 @@
..()
/mob/living/carbon/human/spawn_gibs()
- if(dna)
- hgibs(loc, viruses, dna)
- else
- hgibs(loc, viruses, null)
+ hgibs(loc, viruses, dna)
/mob/living/carbon/human/spawn_dust()
new /obj/effect/decal/remains/human(loc)
@@ -35,8 +32,7 @@
update_canmove()
if(client) blind.layer = 0
- if(dna)
- dna.species.spec_death(gibbed,src)
+ dna.species.spec_death(gibbed,src)
tod = worldtime2text() //weasellos time of death patch
if(mind) mind.store_memory("Time of death: [tod]", 0)
@@ -47,9 +43,8 @@
return ..(gibbed)
/mob/living/carbon/human/proc/makeSkeleton()
- if(!check_dna_integrity(src)) return
status_flags |= DISFIGURED
- hardset_dna(src, null, null, null, null, /datum/species/skeleton)
+ set_species(/datum/species/skeleton)
return 1
/mob/living/carbon/proc/ChangeToHusk()
@@ -66,5 +61,5 @@
/mob/living/carbon/proc/Drain()
ChangeToHusk()
- mutations |= NOCLONE
+ disabilities |= NOCLONE
return 1
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index 6523c085039..2ab52c617ef 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -18,7 +18,7 @@
if(mind)
miming=mind.miming
- if(src.stat == 2.0 && (act != "deathgasp"))
+ if(src.stat == 2 && (act != "deathgasp"))
return
switch(act) //Please keep this alphabetically ordered when adding or changing emotes.
if ("aflap") //Any emote on human that uses miming must be left in, oh well.
@@ -45,6 +45,7 @@
if ("collapse","collapses")
Paralyse(2)
+ adjustStaminaLoss(100) // Hampers abuse against simple mobs, but still leaves it a viable option.
message = "[src] collapses!"
m_type = 2
@@ -307,7 +308,7 @@
m_type = 2
if("wag","wags")
- if(dna && dna.species && (("tail_lizard" in dna.species.mutant_bodyparts) || (features["tail_human"] != "None")))
+ if(dna && dna.species && (("tail_lizard" in dna.species.mutant_bodyparts) || (dna.features["tail_human"] != "None")))
message = "[src] wags \his tail."
startTailWag()
else
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index f2a6715af8e..b59be0b793c 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -280,7 +280,8 @@
if(istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/medical))
var/implant_detect
for(var/obj/item/organ/internal/cyberimp/CI in internal_organs)
- implant_detect += "[name] is modified with a [CI.name]. "
+ if(CI.status == ORGAN_ROBOTIC)
+ implant_detect += "[name] is modified with a [CI.name]. "
if(implant_detect)
msg += "Detected cybernetic modifications: "
msg += implant_detect
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 795c7e68da7..2b585fa1f89 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -14,9 +14,14 @@
/mob/living/carbon/human/New()
- create_reagents(1000)
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
+
+ //initialize dna. for spawned humans; overwritten by other code
+ create_dna(src)
+ randomize_human(src)
+ dna.initialize_dna()
+
//initialise organs
organs = newlist(/obj/item/organ/limb/chest, /obj/item/organ/limb/head, /obj/item/organ/limb/l_arm,
/obj/item/organ/limb/r_arm, /obj/item/organ/limb/r_leg, /obj/item/organ/limb/l_leg)
@@ -29,10 +34,6 @@
for(var/obj/item/organ/internal/I in internal_organs)
I.Insert(src)
- // for spawned humans; overwritten by other code
- ready_dna(src)
- randomize_human(src)
-
make_blood()
..()
@@ -90,9 +91,8 @@
stat("Energy Charge:", "[round(SN.cell.charge/100)]%")
stat("Smoke Bombs:", "\Roman [SN.s_bombs]")
//Ninja status
- if(dna)
- stat("Fingerprints:", "[md5(dna.uni_identity)]")
- stat("Unique Identity:", "[dna.unique_enzymes]")
+ stat("Fingerprints:", "[md5(dna.uni_identity)]")
+ stat("Unique Identity:", "[dna.unique_enzymes]")
stat("Overall Status:", "[stat > 1 ? "dead" : "[health]% healthy"]")
stat("Nutrition Status:", "[nutrition]")
stat("Oxygen Loss:", "[getOxyLoss()]")
@@ -113,7 +113,7 @@
var/b_loss = null
var/f_loss = null
switch (severity)
- if (1.0)
+ if (1)
b_loss += 500
if (prob(getarmor(null, "bomb")))
shred_clothing(1,150)
@@ -123,7 +123,7 @@
gib()
return
- if (2.0)
+ if (2)
b_loss += 60
f_loss += 60
@@ -139,7 +139,7 @@
if (prob(70))
Paralyse(10)
- if(3.0)
+ if(3)
b_loss += 30
if (prob(getarmor(null, "bomb")))
b_loss = b_loss/2
@@ -270,7 +270,7 @@
spreadFire(AM)
//Added a safety check in case you want to shock a human mob directly through electrocute_act.
-/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, safety = 0)
+/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0)
if(!safety)
if(gloves)
var/obj/item/clothing/gloves/G = gloves
@@ -280,7 +280,11 @@
heart_attack = 0
if(stat == CONSCIOUS)
src << "You feel your heart beating again!"
- return ..(shock_damage,source,siemens_coeff)
+ . = ..(shock_damage,source,siemens_coeff,safety,override)
+ if(.)
+ electrocution_animation(40)
+
+
/mob/living/carbon/human/Topic(href, href_list)
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
@@ -659,7 +663,8 @@
facial_hair_style = "Shaved"
hair_style = pick("Bedhead", "Bedhead 2", "Bedhead 3")
underwear = "Nude"
- regenerate_icons()
+ update_body()
+ update_hair()
/mob/living/carbon/human/singularity_act()
var/gain = 20
@@ -801,4 +806,30 @@
H.bloody_hands = 0
H.bloody_hands_mob = null
H.update_inv_gloves()
- update_icons() //apply the now updated overlays to the mob
\ No newline at end of file
+ update_icons() //apply the now updated overlays to the mob
+
+
+
+//Turns a mob black, flashes a skeleton overlay
+//Just like a cartoon!
+/mob/living/carbon/human/proc/electrocution_animation(anim_duration)
+ //Handle mutant parts if possible
+ if(dna && dna.species)
+ dna.species.handle_mutant_bodyparts(src,"black")
+ dna.species.handle_hair(src,"black")
+ dna.species.update_color(src,"black")
+ overlays += "electrocuted_base"
+ spawn(anim_duration)
+ if(src)
+ if(dna && dna.species)
+ dna.species.handle_mutant_bodyparts(src)
+ dna.species.handle_hair(src)
+ dna.species.update_color(src)
+ overlays -= "electrocuted_base"
+
+ else //or just do a generic animation
+ var/list/viewing = list()
+ for(var/mob/M in viewers(src))
+ if(M.client)
+ viewing += M.client
+ flick_overlay(image(icon,src,"electrocuted_generic",MOB_LAYER+1), viewing, anim_duration)
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/human_attackalien.dm b/code/modules/mob/living/carbon/human/human_attackalien.dm
index 30e03e615cb..50616ff5af8 100644
--- a/code/modules/mob/living/carbon/human/human_attackalien.dm
+++ b/code/modules/mob/living/carbon/human/human_attackalien.dm
@@ -7,7 +7,7 @@
if(M.a_intent == "harm")
if (w_uniform)
w_uniform.add_fingerprint(M)
- var/damage = rand(15, 30)
+ var/damage = prob(90) ? 20 : 0
if(!damage)
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
visible_message("[M] has lunged at [src]!", \
@@ -21,7 +21,7 @@
"[M] has slashed at [src]!")
apply_damage(damage, BRUTE, affecting, armor_block)
- if (damage >= 25)
+ if (prob(30))
visible_message("[M] has wounded [src]!", \
"[M] has wounded [src]!")
apply_effect(4, WEAKEN, armor_block)
diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm
index 39ba01934e5..b1502b73eef 100644
--- a/code/modules/mob/living/carbon/human/human_attackhand.dm
+++ b/code/modules/mob/living/carbon/human/human_attackhand.dm
@@ -7,11 +7,7 @@
/mob/living/carbon/human/attack_hand(mob/living/carbon/human/M)
if(..()) //to allow surgery to return properly.
return
-
- if(dna)
- dna.species.spec_attack_hand(M, src)
-
- return
+ dna.species.spec_attack_hand(M, src)
/mob/living/carbon/human/proc/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, inrange, params)
return
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index 70d3d476103..37f501760a5 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -146,7 +146,7 @@
/mob/living/carbon/human/proc/restore_blood()
if(!(NOBLOOD in dna.species.specflags))
var/blood_volume = vessel.get_reagent_amount("blood")
- vessel.add_reagent("blood",560.0-blood_volume)
+ vessel.add_reagent("blood",560-blood_volume)
////////////////////////////////////////////
@@ -160,38 +160,5 @@
/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = 0)
- if(dna) // if you have a species, it will run the apply_damage code there instead
- dna.species.apply_damage(damage, damagetype, def_zone, blocked, src)
- else
- if((damagetype != BRUTE) && (damagetype != BURN))
- ..(damage, damagetype, def_zone, blocked)
- return 1
-
- else
- blocked = (100-blocked)/100
- if(blocked <= 0) return 0
-
- var/obj/item/organ/limb/organ = null
- if(islimb(def_zone))
- organ = def_zone
- else
- if(!def_zone) def_zone = ran_zone(def_zone)
- organ = get_organ(check_zone(def_zone))
- if(!organ) return 0
-
- damage = (damage * blocked)
-
- switch(damagetype)
- if(BRUTE)
- damageoverlaytemp = 20
- if(organ.take_damage(damage, 0))
- update_damage_overlays(0)
- if(BURN)
- damageoverlaytemp = 20
- if(organ.take_damage(0, damage))
- update_damage_overlays(0)
-
- // Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life().
-
- updatehealth()
- return 1
+ // depending on the species, it will run the corresponding apply_damage code there
+ return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 86c3b23fd50..d11d0e389e2 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -37,9 +37,7 @@ emp_act
return protection
/mob/living/carbon/human/on_hit(proj_type)
- if(dna)
- dna.species.on_hit(proj_type, src)
- return
+ dna.species.on_hit(proj_type, src)
/mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone)
if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
@@ -68,42 +66,38 @@ emp_act
return (..(P , def_zone))
/mob/living/carbon/human/proc/check_reflect(def_zone) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object
- if(wear_suit && istype(wear_suit, /obj/item/))
- var/obj/item/I = wear_suit
- if(I.IsReflect(def_zone) == 1)
+ if(wear_suit)
+ if(wear_suit.IsReflect(def_zone) == 1)
return 1
- if(l_hand && istype(l_hand, /obj/item/))
- var/obj/item/I = l_hand
- if(I.IsReflect(def_zone) == 1)
+ if(l_hand)
+ if(l_hand.IsReflect(def_zone) == 1)
return 1
- if(r_hand && istype(r_hand, /obj/item/))
- var/obj/item/I = r_hand
- if(I.IsReflect(def_zone) == 1)
+ if(r_hand)
+ if(r_hand.IsReflect(def_zone) == 1)
return 1
return 0
//End Here
-/mob/living/carbon/human/proc/check_shields(damage = 0, attack_text = "the attack", obj/item/O)
- if(O)
- if(O.flags & NOSHIELD) //weapon ignores shields altogether
+/mob/living/carbon/human/proc/check_shields(damage = 0, attack_text = "the attack", atom/movable/AM, thrown_proj = 0)
+ var/block_chance = 50 + 30*thrown_proj - round(damage / 3) //thrown things are easier to block
+ if(AM)
+ if(AM.flags & NOSHIELD) //weapon ignores shields altogether
return 0
- if(l_hand && istype(l_hand, /obj/item/weapon))//Current base is the prob(50-d/3)
- var/obj/item/weapon/I = l_hand
- if(I.IsShield() && (prob(50 - round(damage / 3))))
- visible_message("[src] blocks [attack_text] with [l_hand]!", \
- "[src] blocks [attack_text] with [l_hand]!")
- return 1
- if(r_hand && istype(r_hand, /obj/item/weapon))
- var/obj/item/weapon/I = r_hand
- if(I.IsShield() && (prob(50 - round(damage / 3))))
- visible_message("[src] blocks [attack_text] with [r_hand]!", \
- "[src] blocks [attack_text] with [r_hand]!")
- return 1
- if(wear_suit && istype(wear_suit, /obj/item/))
- var/obj/item/I = wear_suit
- if(I.IsShield() && (prob(50)))
+ var/blocker
+ if(l_hand)
+ if(l_hand.IsShield() && prob(block_chance))
+ blocker = l_hand
+ if(r_hand)
+ if(r_hand.IsShield() && prob(block_chance))
+ blocker = r_hand
+ if(blocker)
+ visible_message("[src] blocks [attack_text] with [blocker]!", \
+ "[src] blocks [attack_text] with [blocker]!")
+ return 1
+ if(wear_suit)
+ if(wear_suit.IsShield() && (prob(50)))
visible_message("The reactive teleport system flings [src] clear of [attack_text]!", \
"The reactive teleport system flings [src] clear of [attack_text]!")
var/list/turfs = new/list()
@@ -129,94 +123,11 @@ emp_act
var/obj/item/organ/limb/affecting = get_organ(ran_zone(user.zone_sel.selecting))
var/hit_area = parse_zone(affecting.name)
var/target_area = parse_zone(target_limb.name)
- feedback_add_details("item_used_for_combat","[I.name]|[I.force]")
- feedback_add_details("zone_targeted","[def_zone]")
+ feedback_add_details("item_used_for_combat","[I.type]|[I.force]")
+ feedback_add_details("zone_targeted","[target_area]")
- if(dna) // allows your species to affect the attacked_by code
- return dna.species.spec_attacked_by(I,user,def_zone,affecting,hit_area,src.a_intent,target_limb,target_area,src)
-
- else
- if(user != src)
- user.do_attack_animation(src)
- if(check_shields(I.force, "the [I.name]", I))
- return 0
-
- if(I.attack_verb && I.attack_verb.len)
- visible_message("[user] has [pick(I.attack_verb)] [src] in the [hit_area] with [I]!", \
- "[user] has [pick(I.attack_verb)] [src] in the [hit_area] with [I]!")
- else if(I.force)
- visible_message("[user] has attacked [src] in the [hit_area] with [I]!", \
- "[user] has attacked [src] in the [hit_area] with [I]!")
- else
- return 0
-
- var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened a hit to your [hit_area].", I.armour_penetration)
- armor = min(90,armor) //cap damage reduction at 90%
-
- var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords)
-
- apply_damage(I.force, I.damtype, affecting, armor , I)
- var/bloody = 0
- if(((I.damtype == BRUTE) && I.force && prob(25 + (I.force * 2))))
- if(affecting.status == ORGAN_ORGANIC)
- I.add_blood(src) //Make the weapon bloody, not the person.
- if(prob(I.force * 2)) //blood spatter!
- bloody = 1
- var/turf/location = loc
- if(istype(location, /turf/simulated))
- location.add_blood(src)
- if(ishuman(user))
- var/mob/living/carbon/human/H = user
- if(get_dist(H, src) <= 1) //people with TK won't get smeared with blood
- if(H.wear_suit)
- H.wear_suit.add_blood(src)
- H.update_inv_wear_suit() //updates mob overlays to show the new blood (no refresh)
- else if(H.w_uniform)
- H.w_uniform.add_blood(src)
- H.update_inv_w_uniform() //updates mob overlays to show the new blood (no refresh)
- if (H.gloves)
- var/obj/item/clothing/gloves/G = H.gloves
- G.add_blood(H)
- else
- H.add_blood(H)
- H.update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves
-
- switch(hit_area)
- if("head") //Harder to score a stun but if you do it lasts a bit longer
- if(stat == CONSCIOUS)
- if(prob(I.force))
- visible_message("[src] has been knocked unconscious!", \
- "[src] has been knocked unconscious!")
- apply_effect(20, PARALYZE, armor)
- if(prob(I.force + min(100,100 - src.health)) && src != user && I.damtype == BRUTE)
- ticker.mode.remove_revolutionary(mind)
- if(bloody) //Apply blood
- if(wear_mask)
- wear_mask.add_blood(src)
- update_inv_wear_mask()
- if(head)
- head.add_blood(src)
- update_inv_head()
- if(glasses && prob(33))
- glasses.add_blood(src)
- update_inv_glasses()
-
- if("chest") //Easier to score a stun but lasts less time
- if(stat == CONSCIOUS && I.force && prob(I.force + 10))
- visible_message("[src] has been knocked down!", \
- "[src] has been knocked down!")
- apply_effect(5, WEAKEN, armor)
-
- if(bloody)
- if(wear_suit)
- wear_suit.add_blood(src)
- update_inv_wear_suit()
- if(w_uniform)
- w_uniform.add_blood(src)
- update_inv_w_uniform()
-
- if(Iforce > 10 || Iforce >= 5 && prob(33))
- forcesay(hit_appends) //forcesay checks stat already
+ // the attacked_by code varies among species
+ return dna.species.spec_attacked_by(I,user,def_zone,affecting,hit_area,src.a_intent,target_limb,target_area,src)
/mob/living/carbon/human/emp_act(severity)
var/informed = 0
@@ -389,7 +300,7 @@ emp_act
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/obj/item/organ/limb/affecting = get_organ(ran_zone(dam_zone))
var/armor = run_armor_check(affecting, "melee")
- apply_damage(damage, BRUTE, affecting, armor)
+ apply_damage(damage, M.melee_damage_type, affecting, armor)
updatehealth()
@@ -454,12 +365,18 @@ emp_act
else
..()
-/mob/living/carbon/human/hitby(atom/movable/AM)
- var/hitpush = 1
- var/skipcatch = 0
- if(AM.throw_speed >= EMBED_THROWSPEED_THRESHOLD)
- if(istype(AM, /obj/item))
- var/obj/item/I = AM
+/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
+ var/obj/item/I
+ var/throwpower = 30
+ if(istype(AM, /obj/item))
+ I = AM
+ throwpower = I.throwforce
+ if(check_shields(throwpower, "\the [AM.name]", AM, 1))
+ hitpush = 0
+ skipcatch = 1
+ blocked = 1
+ else if(I)
+ if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD)
if(can_embed(I))
if(prob(I.embed_chance) && !(dna && (PIERCEIMMUNE in dna.species.specflags)))
throw_alert("embeddedobject")
@@ -471,4 +388,5 @@ emp_act
visible_message("\the [I.name] embeds itself in [src]'s [L.getDisplayName()]!","\the [I.name] embeds itself in your [L.getDisplayName()]!")
hitpush = 0
skipcatch = 1 //can't catch the now embedded item
- return ..(AM, skipcatch, hitpush)
+
+ return ..()
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 6a61b043f42..5f64d3bcea6 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -18,7 +18,6 @@
var/lip_color = "white"
var/age = 30 //Player's age (pure fluff)
- var/blood_type = "A+" //Player's bloodtype
var/underwear = "Nude" //Which underwear the player wants
var/undershirt = "Nude" //Which undershirt the player wants
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index 6950ff303f8..ed0add4de62 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -56,7 +56,7 @@
if( head && (head.flags_inv&HIDEFACE) )
return if_no_face //Likewise for hats
var/obj/item/organ/limb/O = get_organ("head")
- if( (status_flags&DISFIGURED) || (O.brutestate+O.burnstate)>2 || cloneloss>50 || !real_name ) //disfigured. use id-name if possible
+ if( !O || (status_flags&DISFIGURED) || (O.brutestate+O.burnstate)>2 || cloneloss>50 || !real_name ) //disfigured. use id-name if possible
return if_no_face
return real_name
@@ -128,11 +128,9 @@
return (health <= config.health_threshold_crit && stat == UNCONSCIOUS)
/mob/living/carbon/human/reagent_check(datum/reagent/R)
- if(dna)
- var/bypass = dna.species.handle_chemicals(R,src)
- return bypass // if it returns 0, it will run the usual on_mob_life for that reagent. otherwise, it will stop after running handle_chemicals for the species.
- else
- return 0
+ return dna.species.handle_chemicals(R,src)
+ // if it returns 0, it will run the usual on_mob_life for that reagent. otherwise, it will stop after running handle_chemicals for the species.
+
/mob/living/carbon/human/can_track(mob/living/user)
if(wear_id && istype(wear_id.GetID(), /obj/item/weapon/card/id/syndicate))
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 664933c175b..ea16885f05f 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -1,6 +1,6 @@
/mob/living/carbon/human/movement_delay()
- if(dna)
- . += dna.species.movement_delay(src)
+
+ . += dna.species.movement_delay(src)
. += ..()
. += config.human_delay
@@ -45,15 +45,32 @@
return shoes && shoes.negates_gravity()
/mob/living/carbon/human/Move(NewLoc, direct)
- . = ..()
- if(dna)
- for(var/datum/mutation/human/HM in dna.mutations)
- HM.on_move(src, NewLoc)
+ . = ..()
+ for(var/datum/mutation/human/HM in dna.mutations)
+ HM.on_move(src, NewLoc)
if(shoes)
- if(!lying)
+ if(!lying && !buckled)
if(loc == NewLoc)
if(!has_gravity(loc))
return
var/obj/item/clothing/shoes/S = shoes
+
+ //Bloody footprints
+ var/turf/T = get_turf(src)
+ if(S.bloody_shoes && S.bloody_shoes[S.blood_state])
+ var/obj/effect/decal/cleanable/blood/footprints/oldFP = locate(/obj/effect/decal/cleanable/blood/footprints) in T
+ if(oldFP && oldFP.blood_state == S.blood_state)
+ return
+ else
+ //No oldFP or it's a different kind of blood
+ S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state]-BLOOD_LOSS_PER_STEP)
+ var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T)
+ FP.blood_state = S.blood_state
+ FP.entered_dirs |= dir
+ FP.bloodiness = S.bloody_shoes[S.blood_state]
+ FP.update_icon()
+ update_inv_shoes()
+ //End bloody footprints
+
S.step_action()
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 30f90b8c51a..5968b88647e 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -1,158 +1,5 @@
/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = 0)
- if(dna)
- return dna.species.can_equip(I, slot, disable_warning, src)
- else
- switch(slot)
- if(slot_l_hand)
- if(l_hand)
- return 0
- return 1
- if(slot_r_hand)
- if(r_hand)
- return 0
- return 1
- if(slot_wear_mask)
- if(wear_mask)
- return 0
- if( !(I.slot_flags & SLOT_MASK) )
- return 0
- return 1
- if(slot_back)
- if(back)
- return 0
- if( !(I.slot_flags & SLOT_BACK) )
- return 0
- return 1
- if(slot_wear_suit)
- if(wear_suit)
- return 0
- if( !(I.slot_flags & SLOT_OCLOTHING) )
- return 0
- return 1
- if(slot_gloves)
- if(gloves)
- return 0
- if( !(I.slot_flags & SLOT_GLOVES) )
- return 0
- return 1
- if(slot_shoes)
- if(shoes)
- return 0
- if( !(I.slot_flags & SLOT_FEET) )
- return 0
- return 1
- if(slot_belt)
- if(belt)
- return 0
- if(!w_uniform)
- if(!disable_warning)
- src << "You need a jumpsuit before you can attach this [I.name]!"
- return 0
- if( !(I.slot_flags & SLOT_BELT) )
- return
- return 1
- if(slot_glasses)
- if(glasses)
- return 0
- if( !(I.slot_flags & SLOT_EYES) )
- return 0
- return 1
- if(slot_head)
- if(head)
- return 0
- if( !(I.slot_flags & SLOT_HEAD) )
- return 0
- return 1
- if(slot_ears)
- if(ears)
- return 0
- if( !(I.slot_flags & SLOT_EARS) )
- return 0
- return 1
- if(slot_w_uniform)
- if(w_uniform)
- return 0
- if( !(I.slot_flags & SLOT_ICLOTHING) )
- return 0
- return 1
- if(slot_wear_id)
- if(wear_id)
- return 0
- if(!w_uniform)
- if(!disable_warning)
- src << "You need a jumpsuit before you can attach this [I.name]!"
- return 0
- if( !(I.slot_flags & SLOT_ID) )
- return 0
- return 1
- if(slot_l_store)
- if(I.flags & NODROP) //Pockets aren't visible, so you can't move NODROP items into them.
- return 0
- if(l_store)
- return 0
- if(!w_uniform)
- if(!disable_warning)
- src << "You need a jumpsuit before you can attach this [I.name]!"
- return 0
- if(I.slot_flags & SLOT_DENYPOCKET)
- return
- if( I.w_class <= 2 || (I.slot_flags & SLOT_POCKET) )
- return 1
- if(slot_r_store)
- if(I.flags & NODROP)
- return 0
- if(r_store)
- return 0
- if(!w_uniform)
- if(!disable_warning)
- src << "You need a jumpsuit before you can attach this [I.name]!"
- return 0
- if(I.slot_flags & SLOT_DENYPOCKET)
- return 0
- if( I.w_class <= 2 || (I.slot_flags & SLOT_POCKET) )
- return 1
- return 0
- if(slot_s_store)
- if(I.flags & NODROP) //Suit storage NODROP items drop if you take a suit off, this is to prevent people exploiting this.
- return 0
- if(s_store)
- return 0
- if(!wear_suit)
- if(!disable_warning)
- src << "You need a suit before you can attach this [I.name]!"
- return 0
- if(!wear_suit.allowed)
- if(!disable_warning)
- usr << "You somehow have a suit with no defined allowed items for suit storage, stop that!" //should be src?
- return 0
- if(I.w_class > 4)
- if(!disable_warning)
- usr << "The [I.name] is too big to attach!" //should be src?
- return 0
- if( istype(I, /obj/item/device/pda) || istype(I, /obj/item/weapon/pen) || is_type_in_list(I, wear_suit.allowed) ) //ugly and un-polymorphic.
- return 1
- return 0
- if(slot_handcuffed)
- if(handcuffed)
- return 0
- if(!istype(I, /obj/item/weapon/restraints/handcuffs))
- return 0
- return 1
- if(slot_legcuffed)
- if(legcuffed)
- return 0
- if(!istype(I, /obj/item/weapon/restraints/legcuffs))
- return 0
- return 1
- if(slot_in_backpack)
- if (back && istype(back, /obj/item/weapon/storage/backpack))
- var/obj/item/weapon/storage/backpack/B = back
- if(B.contents.len < B.storage_slots && I.w_class <= B.max_w_class)
- return 1
- return 0
- return 0 //Unsupported slot
-
-
+ return dna.species.can_equip(I, slot, disable_warning, src)
/mob/living/carbon/human/verb/quick_equip()
set name = "quick-equip"
@@ -360,6 +207,8 @@
head = I
if(head.flags & BLOCKHAIR)
update_hair(redraw_mob) //rebuild hair
+ if(head.flags_inv & HIDEEARS)
+ update_body(redraw_mob)
update_inv_head(redraw_mob)
if(slot_shoes)
shoes = I
@@ -471,4 +320,18 @@
else
burn()
- return shredded
\ No newline at end of file
+ return shredded
+
+/mob/living/carbon/human/proc/equipOutfit(outfit)
+ var/datum/outfit/O = null
+
+ if(ispath(outfit))
+ O = new outfit
+ else
+ O = outfit
+ if(!istype(O))
+ return 0
+ if(!O)
+ return 0
+
+ return O.equip(src)
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index be552c4aedb..b4f66fe3ccc 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -8,7 +8,7 @@
#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point
#define HEAT_DAMAGE_LEVEL_2 3 //Amount of damage applied when your body temperature passes the 400K point
-#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 460K point and you are on fire
+#define HEAT_DAMAGE_LEVEL_3 10 //Amount of damage applied when your body temperature passes the 460K point and you are on fire
#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point
#define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point
@@ -38,9 +38,8 @@
tinttotal = tintcheck() //here as both hud updates and status updates call it
if(..())
- if(dna)
- for(var/datum/mutation/human/HM in dna.mutations)
- HM.on_life(src)
+ for(var/datum/mutation/human/HM in dna.mutations)
+ HM.on_life(src)
//heart attack stuff
handle_heart()
@@ -50,8 +49,7 @@
//Update our name based on whether our face is obscured/disfigured
name = get_visible_name()
- if(dna)
- dna.species.spec_life(src) // for mutantraces
+ dna.species.spec_life(src) // for mutantraces
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
@@ -93,17 +91,20 @@
if(!dna || !dna.species.handle_mutations_and_radiation(src))
..()
+/mob/living/carbon/human/handle_chemicals_in_body()
+ if(reagents)
+ reagents.metabolize(src, can_overdose=1)
+
/mob/living/carbon/human/breathe()
- if(!dna || !dna.species.breathe(src))
+ if(!dna.species.breathe(src))
..()
/mob/living/carbon/human/check_breath(datum/gas_mixture/breath)
- if(!dna || !dna.species.check_breath(breath, src))
+ if(!dna.species.check_breath(breath, src))
..()
/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment)
- if(dna)
- dna.species.handle_environment(environment, src)
+ dna.species.handle_environment(environment, src)
///FIRE CODE
/mob/living/carbon/human/handle_fire()
@@ -123,7 +124,7 @@
if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT)
bodytemperature += 11
else
- bodytemperature += BODYTEMP_HEATING_MAX
+ bodytemperature += (BODYTEMP_HEATING_MAX + (fire_stacks * 12))
/mob/living/carbon/human/IgniteMob()
@@ -164,7 +165,7 @@
/mob/living/carbon/human/proc/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to.
var/thermal_protection_flags = get_heat_protection_flags(temperature)
- var/thermal_protection = 0.0
+ var/thermal_protection = 0
if(thermal_protection_flags)
if(thermal_protection_flags & HEAD)
thermal_protection += THERMAL_PROTECTION_HEAD
@@ -229,7 +230,7 @@
temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K.
var/thermal_protection_flags = get_cold_protection_flags(temperature)
- var/thermal_protection = 0.0
+ var/thermal_protection = 0
if(thermal_protection_flags)
if(thermal_protection_flags & HEAD)
thermal_protection += THERMAL_PROTECTION_HEAD
@@ -259,10 +260,7 @@
/mob/living/carbon/human/handle_chemicals_in_body()
..()
- if(dna)
- dna.species.handle_chemicals_in_body(src)
-
- return //TODO: DEFERRED
+ dna.species.handle_chemicals_in_body(src)
/mob/living/carbon/human/handle_vision()
client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask)
@@ -271,12 +269,10 @@
else
if(!client.adminobs) reset_view(null)
- if(dna)
- dna.species.handle_vision(src)
+ dna.species.handle_vision(src)
/mob/living/carbon/human/handle_hud_icons()
- if(dna)
- dna.species.handle_hud_icons(src)
+ dna.species.handle_hud_icons(src)
/mob/living/carbon/human/handle_random_events()
// Puke if toxloss is too high
diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm
index 8b0fdbe16d5..4720ac6a5cf 100644
--- a/code/modules/mob/living/carbon/human/say.dm
+++ b/code/modules/mob/living/carbon/human/say.dm
@@ -9,8 +9,7 @@
return ..()
/mob/living/carbon/human/treat_message(message)
- if(dna)
- message = dna.species.handle_speech(message,src)
+ message = dna.species.handle_speech(message,src)
if(viruses.len)
for(var/datum/disease/pierrot_throat/D in viruses)
var/list/temp_message = text2list(message, " ") //List each word in the message
@@ -25,8 +24,7 @@
pick_list -= H //Make sure that you dont HONK the same word twice
message = list2text(temp_message, " ")
message = ..(message)
- if(dna)
- message = dna.mutations_say_mods(message)
+ message = dna.mutations_say_mods(message)
return message
/mob/living/carbon/human/get_spans()
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index db366b79fb0..f9973ea991d 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -118,24 +118,35 @@
else
return "[id]"
-/datum/species/proc/update_color(mob/living/carbon/human/H)
+/datum/species/proc/update_color(mob/living/carbon/human/H, forced_colour)
H.remove_overlay(SPECIES_LAYER)
var/image/standing
var/g = (H.gender == FEMALE) ? "f" : "m"
- if(MUTCOLORS in specflags)
+ if((MUTCOLORS in specflags) || use_skintones)
var/image/spec_base
var/icon_state_string = "[id]_"
- if(sexes)
- icon_state_string += "[g]_s"
+
+ if(use_skintones)
+ if(sexes)
+ icon_state_string = "[H.skin_tone]_[g]_s"
+ else
+ icon_state_string = "[H.skin_tone]_s"
else
- icon_state_string += "_s"
+ if(sexes)
+ icon_state_string += "[g]_s"
+ else
+ icon_state_string += "_s"
spec_base = image("icon" = 'icons/mob/human.dmi', "icon_state" = icon_state_string, "layer" = -SPECIES_LAYER)
- spec_base.color = "#[H.dna.features["mcolor"]]"
+ if(!forced_colour && !use_skintones)
+ spec_base.color = "#[H.dna.features["mcolor"]]"
+ else
+ spec_base.color = forced_colour
+
standing = spec_base
if(standing)
@@ -143,7 +154,7 @@
H.apply_overlay(SPECIES_LAYER)
-/datum/species/proc/handle_hair(mob/living/carbon/human/H)
+/datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour)
H.remove_overlay(HAIR_LAYER)
var/datum/sprite_accessory/S
@@ -156,13 +167,17 @@
img_facial_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER)
- if(hair_color)
- if(hair_color == "mutcolor")
- img_facial_s.color = "#" + H.dna.features["mcolor"]
+ if(!forced_colour)
+ if(hair_color)
+ if(hair_color == "mutcolor")
+ img_facial_s.color = "#" + H.dna.features["mcolor"]
+ else
+ img_facial_s.color = "#" + hair_color
else
- img_facial_s.color = "#" + hair_color
+ img_facial_s.color = "#" + H.facial_hair_color
else
- img_facial_s.color = "#" + H.facial_hair_color
+ img_facial_s.color = forced_colour
+
img_facial_s.alpha = hair_alpha
standing += img_facial_s
@@ -184,13 +199,16 @@
img_hair_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER)
- if(hair_color)
- if(hair_color == "mutcolor")
- img_hair_s.color = "#" + H.dna.features["mcolor"]
+ if(!forced_colour)
+ if(hair_color)
+ if(hair_color == "mutcolor")
+ img_hair_s.color = "#" + H.dna.features["mcolor"]
+ else
+ img_hair_s.color = "#" + hair_color
else
- img_hair_s.color = "#" + hair_color
+ img_hair_s.color = "#" + H.hair_color
else
- img_hair_s.color = "#" + H.hair_color
+ img_hair_s.color = forced_colour
img_hair_s.alpha = hair_alpha
standing += img_hair_s
@@ -229,7 +247,7 @@
if(H.undershirt)
var/datum/sprite_accessory/undershirt/U2 = undershirt_list[H.undershirt]
if(U2)
- if(H.dna && H.dna.species.sexes && H.gender == FEMALE)
+ if(H.dna.species.sexes && H.gender == FEMALE)
standing += H.wear_female_version(U2.icon_state, U2.icon, BODY_LAYER)
else
standing += image("icon"=U2.icon, "icon_state"="[U2.icon_state]_s", "layer"=-BODY_LAYER)
@@ -246,7 +264,7 @@
return
-/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H)
+/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
var/list/bodyparts_to_add = mutant_bodyparts.Copy()
var/list/relevent_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
var/list/standing = list()
@@ -359,18 +377,21 @@
I = image("icon" = 'icons/mob/mutant_bodyparts.dmi', "icon_state" = icon_string, "layer" =- layer)
if(!(H.disabilities & HUSK))
- switch(S.color_src)
- if(MUTCOLORS)
- I.color = "#[H.dna.features["mcolor"]]"
- if(HAIR)
- if(hair_color == "mutcolor")
+ if(!forced_colour)
+ switch(S.color_src)
+ if(MUTCOLORS)
I.color = "#[H.dna.features["mcolor"]]"
- else
- I.color = "#[H.hair_color]"
- if(FACEHAIR)
- I.color = "#[H.facial_hair_color]"
- if(EYECOLOR)
- I.color = "#[H.eye_color]"
+ if(HAIR)
+ if(hair_color == "mutcolor")
+ I.color = "#[H.dna.features["mcolor"]]"
+ else
+ I.color = "#[H.hair_color]"
+ if(FACEHAIR)
+ I.color = "#[H.facial_hair_color]"
+ if(EYECOLOR)
+ I.color = "#[H.eye_color]"
+ else
+ I.color = forced_colour
standing += I
if(S.hasinner)
@@ -657,7 +678,7 @@
var/obj/item/clothing/glasses/G = H.glasses
H.sight |= G.vision_flags
H.see_in_dark = G.darkness_view
- H.see_invisible = G.invis_view
+ H.see_invisible = min(G.invis_view, H.see_invisible)
if(H.druggy) //Override for druggy
H.see_invisible = see_temp
@@ -783,8 +804,8 @@
if(prob(1))
H << "You mutate!"
randmutb(H)
- domutcheck(H,null)
H.emote("gasp")
+ H.domutcheck()
return 0
return 1
@@ -886,22 +907,14 @@
else
M.do_attack_animation(H)
- var/atk_verb = "punch"
+ var/atk_verb = M.dna.species.attack_verb
if(H.lying)
atk_verb = "kick"
- else if(M.dna)
- atk_verb = M.dna.species.attack_verb
- var/damage = rand(0, 9)
- if(M.dna)
- damage += M.dna.species.punchmod
+ var/damage = rand(0, 9) + M.dna.species.punchmod
if(!damage)
- if(M.dna)
- playsound(H.loc, M.dna.species.miss_sound, 25, 1, -1)
- else
- playsound(H.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
-
+ playsound(H.loc, M.dna.species.miss_sound, 25, 1, -1)
H.visible_message("[M] has attempted to [atk_verb] [H]!")
return 0
@@ -909,11 +922,7 @@
var/obj/item/organ/limb/affecting = H.get_organ(ran_zone(M.zone_sel.selecting))
var/armor_block = H.run_armor_check(affecting, "melee")
- if(M.dna)
- playsound(H.loc, M.dna.species.attack_sound, 25, 1, -1)
- else
- playsound(H.loc, 'sound/weapons/punch1.ogg', 25, 1, -1)
-
+ playsound(H.loc, M.dna.species.attack_sound, 25, 1, -1)
H.visible_message("[M] has [atk_verb]ed [H]!", \
"[M] has [atk_verb]ed [H]!")
@@ -987,9 +996,9 @@
/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, def_zone, obj/item/organ/limb/affecting, hit_area, intent, obj/item/organ/limb/target_limb, target_area, mob/living/carbon/human/H)
// Allows you to put in item-specific reactions based on species
- if(user != src)
+ if(user != H)
user.do_attack_animation(H)
- if((user != H) && H.check_shields(I.force, "the [I.name]", I))
+ if(H.check_shields(I.force, "the [I.name]", I))
return 0
if(I.attack_verb && I.attack_verb.len)
@@ -1001,11 +1010,11 @@
else
return 0
- var/armor = H.run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened a hit to your [hit_area].",I.armour_penetration)
- armor = min(90,armor) //cap damage reduction at 90%
+ var/armor_block = H.run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened a hit to your [hit_area].",I.armour_penetration)
+ armor_block = min(90,armor_block) //cap damage reduction at 90%
var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords)
- apply_damage(I.force, I.damtype, affecting, armor, H)
+ apply_damage(I.force, I.damtype, affecting, armor_block, H)
var/bloody = 0
if(((I.damtype == BRUTE) && I.force && prob(25 + (I.force * 2))))
@@ -1016,28 +1025,30 @@
var/turf/location = H.loc
if(istype(location, /turf/simulated))
location.add_blood(H)
- if(get_dist(H, H) <= 1) //people with TK won't get smeared with blood
- if(H.wear_suit)
- H.wear_suit.add_blood(H)
- H.update_inv_wear_suit() //updates mob overlays to show the new blood (no refresh)
- else if(H.w_uniform)
- H.w_uniform.add_blood(H)
- H.update_inv_w_uniform() //updates mob overlays to show the new blood (no refresh)
- if (H.gloves)
- var/obj/item/clothing/gloves/G = H.gloves
- G.add_blood(H)
- else
- H.add_blood(H)
- H.update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves
+ if(ishuman(user))
+ var/mob/living/carbon/human/M = user
+ if(get_dist(M, H) <= 1) //people with TK won't get smeared with blood
+ if(M.wear_suit)
+ M.wear_suit.add_blood(H)
+ M.update_inv_wear_suit() //updates mob overlays to show the new blood (no refresh)
+ else if(M.w_uniform)
+ M.w_uniform.add_blood(H)
+ M.update_inv_w_uniform() //updates mob overlays to show the new blood (no refresh)
+ if (M.gloves)
+ var/obj/item/clothing/gloves/G = M.gloves
+ G.add_blood(H)
+ else
+ M.add_blood(H)
+ M.update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves
switch(hit_area)
if("head") //Harder to score a stun but if you do it lasts a bit longer
- if(H.stat == CONSCIOUS && armor < 50)
+ if(H.stat == CONSCIOUS && armor_block < 50)
if(prob(I.force))
H.visible_message("[H] has been knocked unconscious!", \
"[H] has been knocked unconscious!")
- H.apply_effect(20, PARALYZE, armor)
+ H.apply_effect(20, PARALYZE, armor_block)
if(prob(I.force + ((100 - H.health)/2)) && H != user && I.damtype == BRUTE)
ticker.mode.remove_revolutionary(H.mind)
@@ -1056,7 +1067,7 @@
if(H.stat == CONSCIOUS && I.force && prob(I.force + 10))
H.visible_message("[H] has been knocked down!", \
"[H] has been knocked down!")
- H.apply_effect(5, WEAKEN, armor)
+ H.apply_effect(5, WEAKEN, armor_block)
if(bloody)
if(H.wear_suit)
@@ -1070,34 +1081,9 @@
H.forcesay(hit_appends) //forcesay checks stat already.
return
-/datum/species/proc/attacked_by(obj/item/I, mob/living/user, def_zone, mob/living/carbon/human/H)
- H.apply_damage(I.force, I.damtype)
- if(I.damtype == "brute")
- if(prob(33) && I.force && !(NOBLOOD in specflags))
- var/turf/location = H.loc
- if(istype(location, /turf/simulated))
- location.add_blood_floor(H)
-
- var/message_verb = ""
- if(I.attack_verb && I.attack_verb.len)
- message_verb = "[pick(I.attack_verb)]"
- else if(I.force)
- message_verb = "attacked"
-
- var/attack_message = "[H] has been [message_verb] with [I]."
- if(user)
- user.do_attack_animation(src)
- if(user in viewers(src, null))
- attack_message = "[user] has [message_verb] [H] with [I]!"
- if(message_verb)
- H.visible_message("[attack_message]",
- "[attack_message]")
-
- return
-
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H)
blocked = (100-(blocked+armor))/100
- if(blocked <= 0) return 0
+ if(!damage || blocked <= 0) return 0
var/obj/item/organ/limb/organ = null
if(islimb(def_zone))
@@ -1126,6 +1112,7 @@
H.adjustCloneLoss(damage * blocked)
if(STAMINA)
H.adjustStaminaLoss(damage * blocked)
+ return 1
/datum/species/proc/on_hit(obj/item/projectile/proj_type, mob/living/carbon/human/H)
// called when hit by a projectile
diff --git a/code/modules/mob/living/carbon/human/species_types.dm b/code/modules/mob/living/carbon/human/species_types.dm
index 2549b1635bf..cd5c473014b 100644
--- a/code/modules/mob/living/carbon/human/species_types.dm
+++ b/code/modules/mob/living/carbon/human/species_types.dm
@@ -38,8 +38,7 @@
/datum/species/human/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == "mutationtoxin")
H << "Your flesh rapidly mutates!"
- hardset_dna(H, null, null, null, null, /datum/species/slime)
- H.regenerate_icons()
+ H.set_species(/datum/species/slime)
H.reagents.del_reagent(chem.type)
H.faction |= "slime"
return 1
@@ -128,10 +127,9 @@ datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
H.visible_message("[H] writhes in pain as \his vacuoles boil.", "You writhe in pain as your vacuoles boil!", "You hear the crunching of leaves.")
if(prob(80))
randmutb(H)
- domutcheck(H,null)
else
randmutg(H)
- domutcheck(H,null)
+ H.domutcheck()
else
H.adjustFireLoss(rand(5,15))
H.show_message("The radiation beam singes you!")
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 8f8f5829970..1b3da71d25d 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -53,33 +53,10 @@ Please contact me on #coderbus IRC. ~Carnie x
*/
/mob/living/carbon/human/proc/update_base_icon_state()
- //var/race = dna ? dna.mutantrace : null
- if(dna)
- base_icon_state = dna.species.update_base_icon_state(src)
- else
- if(disabilities & HUSK)
- base_icon_state = "husk"
- else
- base_icon_state = "[skin_tone]_[(gender == FEMALE) ? "f" : "m"]"
-
+ base_icon_state = dna.species.update_base_icon_state(src)
icon_state = "[base_icon_state]_s"
-//UPDATES OVERLAYS FROM OVERLAYS_STANDING
-//TODO: Remove all instances where this proc is called. It used to be the fastest way to swap between standing/lying.
-/mob/living/carbon/human/update_icons()
-
- update_hud() //TODO: remove the need for this
-
- if(overlays.len != overlays_standing.len)
- overlays.Cut()
-
- for(var/thing in overlays_standing)
- if(thing) overlays += thing
-
- update_transform()
-
-
//DAMAGE OVERLAYS
//constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists
/mob/living/carbon/human/update_damage_overlays()
@@ -108,30 +85,21 @@ Please contact me on #coderbus IRC. ~Carnie x
if((wear_suit) && (wear_suit.hooded) && (wear_suit.suittoggled == 1))
return
- if(dna)
- dna.species.handle_hair(src)
+ dna.species.handle_hair(src)
/mob/living/carbon/human/proc/update_mutcolor()
- if(dna && !(disabilities & HUSK))
+ if(!(disabilities & HUSK))
dna.species.update_color(src)
+//used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body.
/mob/living/carbon/human/proc/update_mutant_bodyparts()
- if(dna)
- dna.species.handle_mutant_bodyparts(src)
+ dna.species.handle_mutant_bodyparts(src)
/mob/living/carbon/human/proc/update_body()
remove_overlay(BODY_LAYER)
-
- if(dna)
- base_icon_state = dna.species.update_base_icon_state(src)
- else
- update_base_icon_state()
-
- icon_state = "[base_icon_state]_s"
-
- if(dna) // didn't want to have a duplicate if(dna) here, but due to the ordering of the code this was the only way
- dna.species.handle_body(src)
+ update_base_icon_state()
+ dna.species.handle_body(src)
/mob/living/carbon/human/update_fire()
..("Standing")
@@ -189,6 +157,8 @@ Please contact me on #coderbus IRC. ~Carnie x
update_hud()
// Mutantrace colors
update_mutcolor()
+ //mutations
+ update_mutations_overlay()
/* --------------------------------------- */
//vvvvvv UPDATE_INV PROCS vvvvvv
@@ -370,7 +340,15 @@ Please contact me on #coderbus IRC. ~Carnie x
standing = image("icon"='icons/mob/feet.dmi', "icon_state"="[shoes.icon_state]", "layer"=-layer2use)
overlays_standing[SHOES_LAYER] = standing
+ //Bloody shoes
+ var/obj/item/clothing/shoes/S = shoes
+ var/bloody = 0
if(shoes.blood_DNA)
+ bloody = 1
+ else
+ bloody = S.bloody_shoes[BLOOD_STATE_HUMAN]
+
+ if(bloody)
standing.overlays += image("icon"='icons/effects/blood.dmi', "icon_state"="shoeblood")
apply_overlay(SHOES_LAYER)
@@ -399,6 +377,8 @@ Please contact me on #coderbus IRC. ~Carnie x
if(hud_used.inventory_shown) //if the inventory is open ...
H.screen_loc = ui_head //TODO //...draw the item in the inventory screen
client.screen += H //Either way, add the item to the HUD
+
+ update_mutant_bodyparts()
apply_overlay(HEAD_LAYER)
diff --git a/code/modules/mob/living/carbon/monkey/emote.dm b/code/modules/mob/living/carbon/monkey/emote.dm
index 42adb99ec59..b2b739109b2 100644
--- a/code/modules/mob/living/carbon/monkey/emote.dm
+++ b/code/modules/mob/living/carbon/monkey/emote.dm
@@ -1,4 +1,4 @@
-/mob/living/carbon/monkey/emote(act)
+/mob/living/carbon/monkey/emote(act,m_type=1,message = null)
var/param = null
if (findtext(act, "-", 1, null))
@@ -6,10 +6,7 @@
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
-
var/muzzled = is_muzzled()
- var/m_type = 1
- var/message
switch(act) //Ooh ooh ah ah keep this alphabetical ooh ooh ah ah!
if ("deathgasp","deathgasps")
@@ -21,15 +18,19 @@
message = "[src] gnarls and shows its teeth.."
m_type = 2
- if ("paw")
- if (!src.restrained())
- message = "[src] flails its paw."
- m_type = 1
+ if ("me")
+ ..()
+ return
if ("moan","moans")
message = "[src] moans!"
m_type = 2
+ if ("paw")
+ if (!src.restrained())
+ message = "[src] flails its paw."
+ m_type = 1
+
if ("roar","roars")
if (!muzzled)
message = "[src] roars."
@@ -67,7 +68,7 @@
src << "Help for monkey emotes. You can use these emotes with say \"*emote\":\n\naflap, airguitar, blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, dance, deathgasp, drool, flap, frown, gasp, gnarl, giggle, glare-(none)/mob, grin, jump, laugh, look, me, moan, nod, paw, point-(atom), roar, roll, scream, scratch, screech, shake, shiver, sigh, sign-#, sit, smile, sneeze, sniff, snore, stare-(none)/mob, sulk, sway, tail, tremble, twitch, twitch_s, wave whimper, wink, yawn"
else
- ..(act)
+ ..()
if ((message && src.stat == 0))
if(src.client)
diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm
index 06f663a56f2..909d769ac74 100644
--- a/code/modules/mob/living/carbon/monkey/life.dm
+++ b/code/modules/mob/living/carbon/monkey/life.dm
@@ -38,10 +38,14 @@
if(prob(1))
src << "You mutate!"
randmutb(src)
- domutcheck(src,null)
emote("gasp")
+ domutcheck()
..()
+/mob/living/carbon/monkey/handle_chemicals_in_body()
+ if(reagents)
+ reagents.metabolize(src, can_overdose=1)
+
/mob/living/carbon/monkey/handle_breath_temperature(datum/gas_mixture/breath)
if(abs(310.15 - breath.temperature) > 50)
switch(breath.temperature)
diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm
index 5f721ecb512..844ebd793ae 100644
--- a/code/modules/mob/living/carbon/monkey/monkey.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey.dm
@@ -8,25 +8,33 @@
pass_flags = PASSTABLE
languages = MONKEY
ventcrawler = 1
+ butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey
gib_type = /obj/effect/decal/cleanable/blood/gibs
unique_name = 1
/mob/living/carbon/monkey/New()
- create_reagents(1000)
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
+ gender = pick(MALE, FEMALE)
+ real_name = name
+ if(good_mutations.len) //genetic mutations have been set up.
+ initialize()
+
internal_organs += new /obj/item/organ/internal/appendix
internal_organs += new /obj/item/organ/internal/heart
internal_organs += new /obj/item/organ/internal/brain
for(var/obj/item/organ/internal/I in internal_organs)
I.Insert(src)
- gender = pick(MALE, FEMALE)
..()
+/mob/living/carbon/monkey/initialize()
+ create_dna(src)
+ dna.initialize_dna(random_blood_type())
+
/mob/living/carbon/monkey/prepare_data_huds()
//Prepare our med HUD...
..()
@@ -103,7 +111,7 @@
if (prob(25))
Paralyse(2)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
- add_logs(M, src, "pushed", admin=0)
+ add_logs(M, src, "pushed")
visible_message("[M] has pushed down [src]!", \
"[M] has pushed down [src]!")
else
@@ -155,7 +163,19 @@
/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
- adjustBruteLoss(damage)
+ switch(M.melee_damage_type)
+ if(BRUTE)
+ adjustBruteLoss(damage)
+ if(BURN)
+ adjustFireLoss(damage)
+ if(TOX)
+ adjustToxLoss(damage)
+ if(OXY)
+ adjustOxyLoss(damage)
+ if(CLONE)
+ adjustCloneLoss(damage)
+ if(STAMINA)
+ adjustStaminaLoss(damage)
updatehealth()
@@ -188,14 +208,14 @@
/mob/living/carbon/monkey/ex_act(severity, target)
..()
switch(severity)
- if(1.0)
+ if(1)
gib()
return
- if(2.0)
+ if(2)
adjustBruteLoss(60)
adjustFireLoss(60)
adjustEarDamage(30,120)
- if(3.0)
+ if(3)
adjustBruteLoss(30)
if (prob(50))
Paralyse(10)
diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm
index b8129dd15c9..59d26cb7135 100644
--- a/code/modules/mob/living/carbon/update_icons.dm
+++ b/code/modules/mob/living/carbon/update_icons.dm
@@ -52,7 +52,10 @@
var/t_state = r_hand.item_state
if(!t_state)
t_state = r_hand.icon_state
- overlays_standing[R_HAND_LAYER] = image("icon" = r_hand.righthand_file, "icon_state"="[t_state]", "layer"=-R_HAND_LAYER)
+
+ var/image/I = image("icon" = r_hand.righthand_file, "icon_state"="[t_state]", "layer"=-R_HAND_LAYER)
+ I = center_image(I, r_hand.inhand_x_dimension, r_hand.inhand_y_dimension)
+ overlays_standing[R_HAND_LAYER] = I
apply_overlay(R_HAND_LAYER)
@@ -68,7 +71,10 @@
var/t_state = l_hand.item_state
if(!t_state)
t_state = l_hand.icon_state
- overlays_standing[L_HAND_LAYER] = image("icon" = l_hand.lefthand_file, "icon_state"="[t_state]", "layer"=-L_HAND_LAYER)
+
+ var/image/I = image("icon" = l_hand.lefthand_file, "icon_state"="[t_state]", "layer"=-L_HAND_LAYER)
+ I = center_image(I, l_hand.inhand_x_dimension, l_hand.inhand_y_dimension)
+ overlays_standing[L_HAND_LAYER] = I
apply_overlay(L_HAND_LAYER)
@@ -179,3 +185,7 @@
L.overlays = null
+
+
+
+
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 5fbd65c7037..0d5b4cd0444 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -2,6 +2,9 @@
set invisibility = 0
set background = BACKGROUND_ENABLED
+ if(digitalinvis)
+ handle_diginvis() //AI becomes unable to see mob
+
if (notransform)
return
if(!loc)
@@ -66,6 +69,14 @@
/mob/living/proc/handle_chemicals_in_body()
return
+/mob/living/proc/handle_diginvis()
+ if(!digitaldisguise)
+ src.digitaldisguise = image(loc = src)
+ src.digitaldisguise.override = 1
+ for(var/mob/living/silicon/ai/AI in player_list)
+ AI.client.images |= src.digitaldisguise
+
+
/mob/living/proc/handle_blood()
return
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index dfb9bcfbc7a..a2ef1cb8689 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -186,7 +186,7 @@ Sorry Giacom. Please don't be mad :(
death()
/mob/living/proc/InCritical()
- return (src.health < 0 && src.health > -95.0 && stat == UNCONSCIOUS)
+ return (src.health < 0 && src.health > -95 && stat == UNCONSCIOUS)
/mob/living/ex_act(severity, target)
..()
@@ -385,7 +385,7 @@ Sorry Giacom. Please don't be mad :(
return 0
-/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, safety = 0)
+/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0)
return 0 //only carbon liveforms have this proc
/mob/living/emp_act(severity)
@@ -605,8 +605,8 @@ Sorry Giacom. Please don't be mad :(
if((!(newdir in H.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && H.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled)
H.existing_dirs += newdir
H.overlays.Add(image('icons/effects/blood.dmi',trail_type,dir = newdir))
- if(check_dna_integrity(M)) //blood DNA
- var/mob/living/carbon/DNA_helper = pulling
+ if(M.has_dna()) //blood DNA
+ var/mob/living/carbon/DNA_helper = M
H.blood_DNA[DNA_helper.dna.unique_enzymes] = DNA_helper.dna.blood_type
/mob/living/proc/getTrail() //silicon and simple_animals don't get blood trails
@@ -839,12 +839,12 @@ Sorry Giacom. Please don't be mad :(
else if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
var/obj/machinery/atmospherics/components/unary/cryo_cell/C = loc
- var/datum/gas_mixture/C_air_contents = C.airs[1]
+ var/datum/gas_mixture/G = C.AIR1
- if(C_air_contents.total_moles() < 10)
+ if(G.total_moles() < 10)
loc_temp = environment.temperature
else
- loc_temp = C_air_contents.temperature
+ loc_temp = G.temperature
else
loc_temp = environment.temperature
@@ -883,7 +883,7 @@ Sorry Giacom. Please don't be mad :(
return 0
if(invisibility || alpha == 0)//cloaked
return 0
- if(digitalcamo)
+ if(digitalcamo || digitalinvis)
return 0
// Now, are they viewable by a camera? (This is last because it's the most intensive check)
@@ -895,3 +895,14 @@ Sorry Giacom. Please don't be mad :(
//used in datum/reagents/reaction() proc
/mob/living/proc/get_permeability_protection()
return 0
+
+/mob/living/proc/harvest(mob/living/user)
+ if(qdeleted(src))
+ return
+ if(butcher_results)
+ for(var/path in butcher_results)
+ for(var/i = 1; i <= butcher_results[path];i++)
+ new path(src.loc)
+ butcher_results.Remove(path) //In case you want to have things like simple_animals drop their butcher results on gib, so it won't double up below.
+ visible_message("[user] butchers [src].")
+ gib()
\ No newline at end of file
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 9a332445538..c30c3527d60 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -44,7 +44,7 @@
else
return 0
-/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = 1)
+/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0)
if(istype(AM, /obj/item))
var/obj/item/I = AM
var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest
@@ -66,13 +66,13 @@
playsound(loc, 'sound/weapons/genhit.ogg', volume, 1, -1)//...play genhit.ogg
if(!I.throwforce)// Otherwise, if the item's throwforce is 0...
playsound(loc, 'sound/weapons/throwtap.ogg', 1, volume, -1)//...play throwtap.ogg.
-
- visible_message("[src] has been hit by [I].", \
- "[src] has been hit by [I].")
- var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
- apply_damage(I.throwforce, dtype, zone, armor, I)
- if(I.thrownby)
- add_logs(I.thrownby, src, "hit", I)
+ if(!blocked)
+ visible_message("[src] has been hit by [I].", \
+ "[src] has been hit by [I].")
+ var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
+ apply_damage(I.throwforce, dtype, zone, armor, I)
+ if(I.thrownby)
+ add_logs(I.thrownby, src, "hit", I)
else
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
..()
@@ -133,7 +133,7 @@
if(!on_fire)
return 1
if(fire_stacks > 0)
- adjust_fire_stacks(-0.2) //the fire is slowly consumed
+ adjust_fire_stacks(-0.1) //the fire is slowly consumed
else
ExtinguishMob()
return
@@ -145,7 +145,7 @@
location.hotspot_expose(700, 50, 1)
/mob/living/fire_act()
- adjust_fire_stacks(0.5)
+ adjust_fire_stacks(3)
IgniteMob()
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index b9f1cefa0f2..0c4d370dca7 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -53,3 +53,5 @@
var/last_bumped = 0
var/unique_name = 0 //if a mob's name should be appended with an id when created e.g. Mob (666)
+
+ var/list/butcher_results = null
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 3f601c0810f..e39e59063dc 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -37,6 +37,7 @@ var/list/ai_list = list()
var/obj/item/device/multitool/aiMulti = null
var/obj/machinery/bot/Bot
var/tracking = 0 //this is 1 if the AI is currently tracking somebody, but the track has not yet been completed.
+ var/datum/effect/effect/system/spark_spread/spark_system//So they can initialize sparks whenever/N
//MALFUNCTION
var/datum/module_picker/malf_picker
@@ -82,6 +83,10 @@ var/list/ai_list = list()
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1"))
+ spark_system = new /datum/effect/effect/system/spark_spread()
+ spark_system.set_up(5, 0, src)
+ spark_system.attach(src)
+
if(L)
if (istype(L, /datum/ai_laws))
laws = L
@@ -147,7 +152,7 @@ var/list/ai_list = list()
shuttle_caller_list -= src
SSshuttle.autoEvac()
qdel(eyeobj) // No AI, no Eye
- ..()
+ return ..()
/mob/living/silicon/ai/verb/pick_icon()
@@ -300,16 +305,15 @@ var/list/ai_list = list()
onclose(src, "airoster")
/mob/living/silicon/ai/proc/ai_call_shuttle()
- if(src.stat == DEAD)
- src << "You can't call the shuttle because you are dead!"
- return
+ if(stat == 2)
+ return //won't work if dead
if(istype(usr,/mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = src
if(AI.control_disabled)
usr << "Wireless control is disabled!"
return
- var/reason = input(src, "What is the nature of your emergency? ([CALL_SHUTTLE_REASON_LENGTH] characters required.)", "Confirm Shuttle Call") as text
+ var/reason = input(src, "What is the nature of your emergency? ([CALL_SHUTTLE_REASON_LENGTH] characters required.)", "Confirm Shuttle Call") as null|text
if(trim(reason))
SSshuttle.requestEvac(src, reason)
@@ -330,6 +334,8 @@ var/list/ai_list = list()
set name = "Toggle Floor Bolts"
if(!isturf(loc)) // if their location isn't a turf
return // stop
+ if(stat == 2)
+ return //won't work if dead
anchored = !anchored // Toggles the anchor
src << "[anchored ? "You are now anchored." : "You are now unanchored."]"
@@ -340,9 +346,8 @@ var/list/ai_list = list()
/mob/living/silicon/ai/proc/ai_cancel_call()
set category = "Malfunction"
- if(src.stat == 2)
- src << "You can't send the shuttle back because you are dead!"
- return
+ if(stat == 2)
+ return //won't work if dead
if(istype(usr,/mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = src
if(AI.control_disabled)
@@ -380,13 +385,13 @@ var/list/ai_list = list()
..()
switch(severity)
- if(1.0)
+ if(1)
gib()
- if(2.0)
+ if(2)
if (stat != 2)
adjustBruteLoss(60)
adjustFireLoss(60)
- if(3.0)
+ if(3)
if (stat != 2)
adjustBruteLoss(30)
@@ -507,8 +512,7 @@ var/list/ai_list = list()
set name = "Access Robot Control"
set desc = "Wirelessly control various automatic robots."
if(stat == 2)
- src << "Critical error. System offline."
- return
+ return //won't work if dead
if(control_disabled)
src << "Wireless communication is disabled."
@@ -623,9 +627,8 @@ var/list/ai_list = list()
cameraFollow = null
var/cameralist[0]
- if(usr.stat == 2)
- usr << "You can't change your camera network because you are dead!"
- return
+ if(stat == 2)
+ return //won't work if dead
var/mob/living/silicon/ai/U = usr
@@ -668,9 +671,8 @@ var/list/ai_list = list()
set category = "AI Commands"
set name = "AI Status"
- if(usr.stat == 2)
- usr <<"You cannot change your emotional status because you are dead!"
- return
+ if(stat == 2)
+ return //won't work if dead
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer", "Dorfy", "Blue Glow", "Red Glow")
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
for (var/obj/machinery/M in machines) //change status
@@ -693,6 +695,8 @@ var/list/ai_list = list()
set desc = "Change the default hologram available to AI to something else."
set category = "AI Commands"
+ if(stat == 2)
+ return //won't work if dead
var/input
if(alert("Would you like to select a hologram based on a crew member or switch to unique avatar?",,"Crew Member","Unique")=="Crew Member")
@@ -705,7 +709,7 @@ var/list/ai_list = list()
input = input("Select a crew member:") as null|anything in personnel_list
var/icon/character_icon = personnel_list[input]
if(character_icon)
- del(holo_icon)//Clear old icon so we're not storing it in memory.
+ qdel(holo_icon)//Clear old icon so we're not storing it in memory.
holo_icon = getHologramIcon(icon(character_icon))
else
alert("No suitable records found. Aborting.")
@@ -719,7 +723,7 @@ var/list/ai_list = list()
)
input = input("Please select a hologram:") as null|anything in icon_list
if(input)
- del(holo_icon)
+ qdel(holo_icon)
switch(input)
if("default")
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1"))
@@ -788,6 +792,8 @@ var/list/ai_list = list()
set desc = "Allows you to change settings of your radio."
set category = "AI Commands"
+ if(stat == 2)
+ return //won't work if dead
src << "Accessing Subspace Transceiver control..."
if (radio)
radio.interact(src)
@@ -801,6 +807,8 @@ var/list/ai_list = list()
set desc = "Modify the default radio setting for your automatic announcements."
set category = "AI Commands"
+ if(stat == 2)
+ return //won't work if dead
set_autosay()
/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user)
@@ -825,4 +833,9 @@ var/list/ai_list = list()
user << "Transfer successful: [name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."
/mob/living/silicon/ai/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
- return // no eyes, no flashing
\ No newline at end of file
+ return // no eyes, no flashing
+
+/mob/living/silicon/ai/attackby(obj/item/weapon/W, mob/user, params)
+ if(W.force && W.damtype != STAMINA && src.stat != DEAD) //only sparks if real damage is dealt.
+ spark_system.start()
+ return ..()
diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm
index 25b8bd2b310..c4f06f0be4d 100644
--- a/code/modules/mob/living/silicon/ai/death.dm
+++ b/code/modules/mob/living/silicon/ai/death.dm
@@ -1,5 +1,8 @@
/mob/living/silicon/ai/death(gibbed)
- if(stat == DEAD) return
+ if(stat == DEAD)
+ return
+ if(!gibbed)
+ emote("me", 1, "sparks and its screen flickers, its systems slowly coming to a halt.")
stat = DEAD
@@ -8,6 +11,7 @@
else
icon_state = "ai_dead"
+ anchored = 0 //unbolt floorbolts
update_canmove()
if(src.eyeobj)
src.eyeobj.setLoc(get_turf(src))
diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm
index 30918bbcec3..f3569d4c503 100644
--- a/code/modules/mob/living/silicon/ai/freelook/eye.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm
@@ -38,7 +38,7 @@
/mob/camera/aiEye/Destroy()
ai = null
- ..()
+ return ..()
/atom/proc/move_camera_by_click()
if(istype(usr, /mob/living/silicon/ai))
@@ -100,5 +100,7 @@
set category = "AI Commands"
set name = "Toggle Camera Acceleration"
+ if(usr.stat == 2)
+ return //won't work if dead
acceleration = !acceleration
usr << "Camera acceleration has been toggled [acceleration ? "on" : "off"]."
diff --git a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm
deleted file mode 100644
index 2b69c20cd65..00000000000
--- a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm
+++ /dev/null
@@ -1,99 +0,0 @@
-#define BORG_CAMERA_BUFFER 30
-
-//UPDATE TRIGGERS, when the chunk (and the surrounding chunks) should update.
-
-// TURFS
-
-/turf
- var/image/obscured
-
-/turf/proc/visibilityChanged()
- if(ticker)
- cameranet.updateVisibility(src)
-
-/turf/simulated/Del()
- visibilityChanged()
- ..()
-
-/turf/simulated/New()
- ..()
- visibilityChanged()
-
-
-
-// STRUCTURES
-
-/obj/structure/Destroy()
- if(ticker)
- cameranet.updateVisibility(src)
- ..()
-
-/obj/structure/New()
- ..()
- if(ticker)
- cameranet.updateVisibility(src)
-
-// EFFECTS
-
-/obj/effect/Destroy()
- if(ticker)
- cameranet.updateVisibility(src)
- ..()
-
-/obj/effect/New()
- ..()
- if(ticker)
- cameranet.updateVisibility(src)
-
-
-// DOORS
-
-// Simply updates the visibility of the area when it opens/closes/destroyed.
-/obj/machinery/door/proc/update_freelook_sight()
- // Glass door glass = 1
- // don't check then?
- if(!glass && cameranet)
- cameranet.updateVisibility(src, 0)
-
-
-// ROBOT MOVEMENT
-
-// Update the portable camera everytime the Robot moves.
-// This might be laggy, comment it out if there are problems.
-/mob/living/silicon/robot/var/updating = 0
-
-/mob/living/silicon/robot/Move()
- var/oldLoc = src.loc
- . = ..()
- if(.)
- if(src.camera)
- if(!updating)
- updating = 1
- spawn(BORG_CAMERA_BUFFER)
- if(oldLoc != src.loc)
- cameranet.updatePortableCamera(src.camera)
- updating = 0
-
-// CAMERA
-
-// An addition to deactivate which removes/adds the camera from the chunk list based on if it works or not.
-
-/obj/machinery/camera/deactivate(mob/user, choice = 1)
- ..(user, choice)
- if(src.can_use())
- cameranet.addCamera(src)
- else
- src.SetLuminosity(0)
- cameranet.removeCamera(src)
-
-/obj/machinery/camera/New()
- ..()
- cameranet.cameras += src
- cameranet.addCamera(src)
-
-/obj/machinery/camera/Destroy()
- cameranet.cameras -= src
- cameranet.removeCamera(src)
- ..()
-
-#undef BORG_CAMERA_BUFFER
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/ai/laws.dm b/code/modules/mob/living/silicon/ai/laws.dm
index 8371f6e3021..50c188ca629 100644
--- a/code/modules/mob/living/silicon/ai/laws.dm
+++ b/code/modules/mob/living/silicon/ai/laws.dm
@@ -2,6 +2,8 @@
/mob/living/silicon/ai/proc/show_laws_verb()
set category = "AI Commands"
set name = "Show Laws"
+ if(usr.stat == 2)
+ return //won't work if dead
src.show_laws()
/mob/living/silicon/ai/show_laws(everyone = 0)
diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm
index 86158b3c4f0..014dd45b84c 100644
--- a/code/modules/mob/living/silicon/ai/say.dm
+++ b/code/modules/mob/living/silicon/ai/say.dm
@@ -69,6 +69,8 @@ var/const/VOX_DELAY = 600
set desc = "Display a list of vocal words to announce to the crew."
set category = "AI Commands"
+ if(usr.stat == 2)
+ return //won't work if dead
var/dat = "Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you. \
You can also click on the word to preview it.
\
diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm
index 201efb3297f..2c0cbfbc247 100644
--- a/code/modules/mob/living/silicon/login.dm
+++ b/code/modules/mob/living/silicon/login.dm
@@ -3,4 +3,6 @@
ticker.mode.remove_cultist(mind, 0)
ticker.mode.remove_revolutionary(mind, 0)
ticker.mode.remove_gangster(mind, remove_bosses=1)
+ ticker.mode.remove_thrall(mind,0)
+ ticker.mode.remove_shadowling(mind)
..()
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index ecb7eca0247..c1ea89972d6 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -138,15 +138,15 @@
..()
switch(severity)
- if(1.0)
+ if(1)
if (src.stat != 2)
adjustBruteLoss(100)
adjustFireLoss(100)
- if(2.0)
+ if(2)
if (src.stat != 2)
adjustBruteLoss(60)
adjustFireLoss(60)
- if(3.0)
+ if(3)
if (src.stat != 2)
adjustBruteLoss(30)
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
index 5655b34bc97..ccabb8a7ece 100644
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -372,10 +372,10 @@
/mob/living/silicon/pai/proc/CheckDNA(mob/living/carbon/M, mob/living/silicon/pai/P)
var/answer = input(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", "No") in list("Yes", "No")
if(answer == "Yes")
- var/turf/T = get_turf(P.loc)
- for (var/mob/v in viewers(T))
- v.show_message("[M] presses \his thumb against [P].", 3, "[P] makes a sharp clicking sound as it extracts DNA material from [M].", 2)
- if(!check_dna_integrity(M))
+ M.visible_message("[M] presses \his thumb against [P].",\
+ "You press your thumb against [P].",\
+ "[P] makes a sharp clicking sound as it extracts DNA material from [M].")
+ if(!M.has_dna())
P << "No DNA detected"
return
P << "
[M]'s UE string : [M.dna.unique_enzymes]
"
diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm
index 0f40c5d5817..96439b2d1a5 100644
--- a/code/modules/mob/living/silicon/robot/death.dm
+++ b/code/modules/mob/living/silicon/robot/death.dm
@@ -23,6 +23,7 @@
return
if(!gibbed)
emote("deathgasp")
+ locked = 0 //unlock cover
stat = DEAD
update_canmove()
if(camera)
diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm
index 337ca2118f0..da45ee8e9ad 100644
--- a/code/modules/mob/living/silicon/robot/laws.dm
+++ b/code/modules/mob/living/silicon/robot/laws.dm
@@ -1,6 +1,9 @@
/mob/living/silicon/robot/verb/cmd_show_laws()
set category = "Robot Commands"
set name = "Show Laws"
+
+ if(usr.stat == DEAD)
+ return //won't work if dead
show_laws()
/mob/living/silicon/robot/show_laws(everyone = 0)
diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm
index af742597953..bfa2a039960 100644
--- a/code/modules/mob/living/silicon/robot/login.dm
+++ b/code/modules/mob/living/silicon/robot/login.dm
@@ -6,6 +6,7 @@
if(mind) ticker.mode.remove_revolutionary(mind)
if(mind) ticker.mode.remove_gangster(mind,1,remove_bosses=1)
if(mind) ticker.mode.remove_thrall(mind,0)
+ if(mind) ticker.mode.remove_shadowling(mind)
/mob/living/silicon/robot/update_hotkey_mode()
winset(src, null, "mainwindow.macro=borghotkeymode hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#F0F0F0")
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index f22de8919e0..d4cf25c2e3f 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -9,6 +9,7 @@
var/custom_name = ""
designation = "Default" //used for displaying the prefix & getting the current module of cyborg
has_limbs = 1
+ var/magpulse = 0
//Hud stuff
@@ -36,6 +37,7 @@
var/opened = 0
var/emagged = 0
+ var/emag_cooldown = 0
var/wiresexposed = 0
var/locked = 1
var/list/req_access = list(access_robotics)
@@ -65,6 +67,8 @@
var/lamp_intensity = 0 //Luminosity of the headlamp. 0 is off. Higher settings than the minimum require power.
var/lamp_recharging = 0 //Flag for if the lamp is on cooldown after being forcibly disabled.
+ var/updating = 0 //portable camera camerachunk update
+
/mob/living/silicon/robot/New(loc)
spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
@@ -138,7 +142,13 @@
mmi = null
if(connected_ai)
connected_ai.connected_robots -= src
- ..()
+ qdel(wires)
+ qdel(module)
+ wires = null
+ module = null
+ camera = null
+ cell = null
+ return ..()
/mob/living/silicon/robot/proc/pick_module()
@@ -213,6 +223,7 @@
animation_length = 45
modtype = "Eng"
feedback_inc("cyborg_engineering",1)
+ magpulse = 1
if("Janitor")
module = new /obj/item/weapon/robot_module/janitor(src)
@@ -255,6 +266,8 @@
/mob/living/silicon/robot/verb/cmd_robot_alerts()
set category = "Robot Commands"
set name = "Show Alerts"
+ if(usr.stat == DEAD)
+ return //won't work if dead
robot_alerts()
//for borg hotkeys, here module refers to borg inv slot, not core module
@@ -336,14 +349,14 @@
/mob/living/silicon/robot/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
gib()
return
- if(2.0)
+ if(2)
if (stat != 2)
adjustBruteLoss(60)
adjustFireLoss(60)
- if(3.0)
+ if(3)
if (stat != 2)
adjustBruteLoss(30)
return
@@ -462,7 +475,7 @@
user << "You insert the power cell."
update_icons()
- else if (istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/multitool) || istype(W, /obj/item/device/assembly/signaler))
+ else if (wires.IsInteractionTool(W))
if (wiresexposed)
wires.Interact(user)
else
@@ -556,7 +569,7 @@
user << "You fill the toner level of [src] to its max capacity."
else
- if(W.force && W.damtype != STAMINA) //only sparks if real damage is dealt.
+ if(W.force && W.damtype != STAMINA && src.stat != DEAD) //only sparks if real damage is dealt.
spark_system.start()
return ..()
@@ -570,11 +583,26 @@
user << "The cover is already unlocked!"
return
if(opened)//Cover is open
- if(emagged) return//Prevents the X has hit Y with Z message also you cant emag them twice
+ if((world.time - 100) < emag_cooldown)
+ return
+
+ var/ai_is_antag = 0
+ if(connected_ai && connected_ai.mind)
+ if(connected_ai.mind.special_role)
+ ai_is_antag = (connected_ai.mind.special_role == "malfunction") || (connected_ai.mind.special_role == "traitor")
+ if(ai_is_antag)
+ user << "You emag [src]'s interface."
+ src << "ALERT: Foreign software execution prevented."
+ connected_ai << "ALERT: Cyborg unit \[[src]] successfuly defended against subversion."
+ log_game("[key_name(user)] attempted to emag cyborg [key_name(src)] slaved to traitor AI [connected_ai].")
+ emag_cooldown = world.time
+ return
+
if(wiresexposed)
user << "You must close the cover first!"
return
else
+ emag_cooldown = world.time
sleep(6)
SetEmagged(1)
SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown
@@ -613,6 +641,8 @@
set category = "Robot Commands"
set name = "Unlock Cover"
set desc = "Unlocks your own cover if it is locked. You can not lock it again. A human will have to lock it for you."
+ if(stat == DEAD)
+ return //won't work if dead
if(locked)
switch(alert("You can not lock your cover again, are you sure?\n (You can still ask for a human to lock it)", "Unlock Own Cover", "Yes", "No"))
if("Yes")
@@ -625,7 +655,7 @@
if(!(lying))
M.do_attack_animation(src)
if (prob(85))
- Stun(7)
+ Stun(2)
step(src,get_dir(M,src))
spawn(5)
step(src,get_dir(M,src))
@@ -854,17 +884,23 @@
/mob/living/silicon/robot/proc/radio_menu()
radio.interact(src)//Just use the radio's Topic() instead of bullshit special-snowflake code
-
+#define BORG_CAMERA_BUFFER 30
/mob/living/silicon/robot/Move(a, b, flag)
+ var/oldLoc = src.loc
. = ..()
+ if(.)
+ if(src.camera)
+ if(!updating)
+ updating = 1
+ spawn(BORG_CAMERA_BUFFER)
+ if(oldLoc != src.loc)
+ cameranet.updatePortableCamera(src.camera)
+ updating = 0
if(module)
if(module.type == /obj/item/weapon/robot_module/janitor)
var/turf/tile = loc
if(isturf(tile))
tile.clean_blood()
- if (istype(tile, /turf/simulated/floor))
- var/turf/simulated/floor/F = tile
- F.dirt = 0
for(var/A in tile)
if(istype(A, /obj/effect))
if(is_cleanable(A))
@@ -899,6 +935,7 @@
loc.attackby(module_state_2,src)
else if(istype(module_state_3,/obj/item/weapon/storage/bag/ore))
loc.attackby(module_state_3,src)
+#undef BORG_CAMERA_BUFFER
/mob/living/silicon/robot/proc/self_destruct()
if(emagged)
@@ -981,12 +1018,17 @@
set category = "Robot Commands"
set name = "State Laws"
+ if(usr.stat == DEAD)
+ return //won't work if dead
checklaws()
/mob/living/silicon/robot/verb/set_automatic_say_channel() //Borg version of setting the radio for autosay messages.
set name = "Set Auto Announce Mode"
set desc = "Modify the default radio setting for stating your laws."
set category = "Robot Commands"
+
+ if(usr.stat == DEAD)
+ return //won't work if dead
set_autosay()
/mob/living/silicon/robot/proc/control_headlamp()
@@ -1028,7 +1070,7 @@
robot_suit.r_leg = null
new /obj/item/stack/cable_coil(T, robot_suit.chest.wires)
robot_suit.chest.loc = T
- robot_suit.chest.wires = 0.0
+ robot_suit.chest.wires = 0
robot_suit.chest = null
robot_suit.l_arm.loc = T
robot_suit.l_arm = null
@@ -1054,7 +1096,7 @@
new /obj/item/robot_parts/head(T)
var/b
for(b=0, b!=2, b++)
- var/obj/item/device/flash/handheld/F = new /obj/item/device/flash/handheld(T)
+ var/obj/item/device/assembly/flash/handheld/F = new /obj/item/device/assembly/flash/handheld(T)
F.burn_out()
if (cell) //Sanity check.
cell.loc = T
@@ -1067,8 +1109,12 @@
scrambledcodes = 1
modtype = "Synd"
faction = list("syndicate")
- designation = "Syndicate"
+ designation = "Syndicate Assault"
req_access = list(access_syndicate)
+ var/playstyle_string = "You are a Syndicate assault cyborg! \
+ You are armed with powerful offensive tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
+ Your cyborg LMG will slowly produce ammunition from your power supply, and your operative pinpointer will find and locate fellow nuclear operatives. \
+ Help the operatives secure the disk at all costs!"
/mob/living/silicon/robot/syndicate/New(loc)
..()
@@ -1078,6 +1124,23 @@
module = new /obj/item/weapon/robot_module/syndicate(src)
laws = new /datum/ai_laws/syndicate_override()
+/mob/living/silicon/robot/syndicate/medical
+ icon_state = "syndi-medi"
+ designation = "Syndicate Medical"
+ playstyle_string = "You are a Syndicate medical cyborg! \
+ You are armed with powerful medical tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
+ Your hypospray will produce Restorative Nanites, a wonder-drug that will heal most types of bodily damages, including clone and brain damage. It also produces morphine for offense. \
+ Your defibrillator paddles can revive operatives through their hardsuits, or can be used on harm intent to shock enemies! \
+ Your energy saw functions as a circular saw, but can be activated to deal more damage, and your operative pinpointer will find and locate fellow nuclear operatives. \
+ Help the operatives secure the disk at all costs!"
+
+/mob/living/silicon/robot/syndicate/New(loc)
+ ..()
+ module = new /obj/item/weapon/robot_module/syndicate_medical(src)
+ spawn(5)
+ if(playstyle_string)
+ src << playstyle_string
+
/mob/living/silicon/robot/proc/notify_ai(notifytype, oldname, newname)
if(!connected_ai)
return
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index c594fbfdfbb..4073292af07 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -2,7 +2,7 @@
name = "robot module"
icon = 'icons/obj/module.dmi'
icon_state = "std_module"
- w_class = 100.0
+ w_class = 100
item_state = "electronic"
flags = CONDUCT
@@ -10,6 +10,12 @@
var/obj/item/emag = null
var/list/storages = list()
+/obj/item/weapon/robot_module/Destroy()
+ modules.Cut()
+ emag = null
+ storages.Cut()
+ return ..()
+
/obj/item/weapon/robot_module/emp_act(severity)
if(modules)
for(var/obj/O in modules)
@@ -34,7 +40,7 @@
/obj/item/weapon/robot_module/New()
- modules += new /obj/item/device/flash/cyborg(src)
+ modules += new /obj/item/device/assembly/flash/cyborg(src)
emag = new /obj/item/toy/sword(src)
emag.name = "Placeholder Emag Item"
return
@@ -242,7 +248,7 @@
/obj/item/weapon/robot_module/syndicate
- name = "syndicate robot module"
+ name = "syndicate assault robot module"
/obj/item/weapon/robot_module/syndicate/New()
..()
@@ -256,6 +262,37 @@
emag = null
fix_modules()
+/obj/item/weapon/robot_module/syndicate_medical
+ name = "syndicate medical robot module"
+
+/obj/item/weapon/robot_module/syndicate_medical/New()
+ ..()
+ modules += new /obj/item/weapon/reagent_containers/borghypo/syndicate(src)
+ modules += new /obj/item/weapon/twohanded/shockpaddles/syndicate(src)
+ modules += new /obj/item/device/healthanalyzer(src)
+ modules += new /obj/item/weapon/reagent_containers/syringe(src)
+ modules += new /obj/item/weapon/surgical_drapes(src)
+ modules += new /obj/item/weapon/retractor(src)
+ modules += new /obj/item/weapon/hemostat(src)
+ modules += new /obj/item/weapon/cautery(src)
+ modules += new /obj/item/weapon/scalpel(src)
+ modules += new /obj/item/weapon/melee/energy/sword/cyborg/saw(src) //Energy saw -- primary weapon
+ modules += new /obj/item/roller/robo(src)
+ modules += new /obj/item/weapon/tank/jetpack/carbondioxide(src)
+ modules += new /obj/item/weapon/crowbar(src)
+ modules += new /obj/item/weapon/pinpointer/operative(src)
+ emag = null
+
+ var/datum/robot_energy_storage/gauze/gauzestore = new /datum/robot_energy_storage/gauze(src)
+
+ var/obj/item/stack/medical/gauze/cyborg/G = new /obj/item/stack/medical/gauze/cyborg(src)
+ G.source = gauzestore
+ modules += G
+
+ storages += gauzestore
+
+ fix_modules()
+
/datum/robot_energy_storage
var/name = "Generic energy storage"
var/max_energy = 30000
diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm
index d459886311c..bb643c16811 100644
--- a/code/modules/mob/living/silicon/robot/robot_movement.dm
+++ b/code/modules/mob/living/silicon/robot/robot_movement.dm
@@ -13,3 +13,13 @@
tally = speed
return tally+config.robot_delay
+
+/mob/living/silicon/robot/mob_negates_gravity()
+ return magpulse
+
+/mob/living/silicon/robot/mob_has_gravity()
+ return ..() || mob_negates_gravity()
+
+/mob/living/silicon/robot/experience_pressure_difference(pressure_difference, direction)
+ if(!magpulse)
+ return ..()
diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm
index e022b8991a4..fa112f3186e 100644
--- a/code/modules/mob/living/silicon/say.dm
+++ b/code/modules/mob/living/silicon/say.dm
@@ -10,7 +10,7 @@
if(istype(src, /mob/living/silicon))
var/mob/living/silicon/S = src
desig = trim_left(S.designation + " " + S.job)
- var/message_a = say_quote(message)
+ var/message_a = say_quote(message, get_spans())
var/rendered = "Robotic Talk, [name][message_a]"
for(var/mob/M in player_list)
if(M.binarycheck() || (M in dead_mob_list))
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 83b20b450cb..1b730a52172 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -28,6 +28,11 @@
var/law_change_counter = 0
+/mob/living/silicon/Destroy()
+ radio = null
+ aicamera = null
+ return ..()
+
/mob/living/silicon/contents_explosion(severity, target)
return
@@ -361,7 +366,7 @@
/mob/living/silicon/attack_alien(mob/living/carbon/alien/humanoid/M)
if(..()) //if harm or disarm intent
- var/damage = rand(10, 20)
+ var/damage = 20
if (prob(90))
add_logs(M, src, "attacked")
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
@@ -381,7 +386,19 @@
/mob/living/silicon/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
- adjustBruteLoss(damage)
+ switch(M.melee_damage_type)
+ if(BRUTE)
+ adjustBruteLoss(damage)
+ if(BURN)
+ adjustFireLoss(damage)
+ if(TOX)
+ adjustToxLoss(damage)
+ if(OXY)
+ adjustOxyLoss(damage)
+ if(CLONE)
+ adjustCloneLoss(damage)
+ if(STAMINA)
+ adjustStaminaLoss(damage)
updatehealth()
/mob/living/silicon/attack_paw(mob/living/user)
diff --git a/code/modules/mob/living/simple_animal/bot_swarm/swarmer.dm b/code/modules/mob/living/simple_animal/bot_swarm/swarmer.dm
new file mode 100644
index 00000000000..92d395b2615
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/bot_swarm/swarmer.dm
@@ -0,0 +1,600 @@
+////Deactivated swarmer shell////
+/obj/item/unactivated_swarmer
+ name = "unactivated swarmer"
+ desc = "A currently unactivated swarmer. Swarmers can self activate at any time, it would be wise to immediately dispose of this."
+ icon = 'icons/mob/swarmer.dmi'
+ icon_state = "swarmer_unactivated"
+
+/obj/item/unactivated_swarmer/New()
+ notify_ghosts("An unactivated swarmer has been created in [get_area(src)]! (Click to enter)")
+ ..()
+
+/obj/item/unactivated_swarmer/Topic(href, href_list)
+ if(href_list["ghostjoin"])
+ var/mob/dead/observer/ghost = usr
+ if(istype(ghost))
+ attack_ghost(ghost)
+
+/obj/item/unactivated_swarmer/attack_ghost(mob/user)
+ var/be_swarmer = alert("Become a swarmer? (Warning, You can no longer be cloned!)",,"Yes","No")
+ if(be_swarmer == "No")
+ return
+ if(qdeleted(src))
+ user << "Swarmer has been occupied by someone else."
+ return
+ var/mob/living/simple_animal/hostile/swarmer/S = new /mob/living/simple_animal/hostile/swarmer(get_turf(loc))
+ S.key = user.key
+ qdel(src)
+
+////The Mob itself////
+
+/mob/living/simple_animal/hostile/swarmer
+ name = "Swarmer"
+ unique_name = 1
+ icon = 'icons/mob/swarmer.dmi'
+ desc = "A robot of unknown design, they seek only to consume materials and replicate themselves indefinitely."
+ speak_emote = list("tones")
+ health = 40
+ maxHealth = 40
+ status_flags = CANPUSH
+ icon_state = "swarmer"
+ icon_living = "swarmer"
+ icon_dead = "swarmer_unactivated"
+ icon_gib = null
+ wander = 0
+ harm_intent_damage = 5
+ minbodytemp = 0
+ maxbodytemp = 500
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
+ unsuitable_atmos_damage = 0
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ melee_damage_type = STAMINA
+ ignored_damage_types = list(BRUTE = 0, BURN = 0, TOX = 1, CLONE = 1, STAMINA = 1, OXY = 1)
+ languages = SWARMER
+ environment_smash = 0
+ attacktext = "shocks"
+ attack_sound = 'sound/effects/EMPulse.ogg'
+ friendly = "pinches"
+ speed = 0
+ faction = list("swarmer")
+ AIStatus = AI_OFF
+ projectiletype = /obj/item/projectile/beam/disabler
+ pass_flags = PASSTABLE
+ ventcrawler = 2
+ ranged = 1
+ projectiletype = /obj/item/projectile/beam/disabler
+ ranged_cooldown_cap = 2
+ projectilesound = 'sound/weapons/taser2.ogg'
+ var/resources = 0 //Resource points, generated by consuming metal/glass
+
+/mob/living/simple_animal/hostile/swarmer/Login()
+ ..()
+ src << "You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate."
+ src << "Ctrl + Click provides most of your swarmer specific interactions, such as cannibalizing metal or glass, destroying the environment, or teleporting mobs away from you."
+ src << "Objectives:"
+ src << "1. Consume resources and replicate until there are no more resources left."
+ src << "2. Ensure that the station is fit for invasion at a later date, do not perform actions that would render it dangerous or inhospitable."
+ src << "3. Biological resources will be harvested at a later date, do not harm them."
+
+/mob/living/simple_animal/hostile/swarmer/New()
+ ..()
+ verbs -= /mob/living/verb/pulled
+
+/mob/living/simple_animal/hostile/swarmer/Stat()
+ ..()
+ if(statpanel("Status"))
+ stat("Resources:",resources)
+
+/mob/living/simple_animal/hostile/swarmer/death(gibbed)
+ ..(gibbed)
+ new /obj/effect/decal/cleanable/robot_debris(src.loc)
+ ghostize()
+ qdel(src)
+
+/mob/living/simple_animal/hostile/swarmer/emp_act()
+ if(health > 1)
+ health = 1
+ return
+ else
+ death()
+
+/mob/living/simple_animal/hostile/swarmer/CanPass(atom/movable/O)
+ if(istype(O, /obj/item/projectile/beam/disabler))//Allows for swarmers to fight as a group without wasting their shots hitting each other
+ return 1
+ if(isswarmer(O))
+ return 1
+ ..()
+
+////CTRL CLICK FOR SWARMERS AND SWARMER_ACT()'S////
+/mob/living/simple_animal/hostile/swarmer/CtrlClickOn(atom/A)
+ face_atom(A)
+ if(!isturf(loc))
+ return
+ if(next_move > world.time)
+ return
+ if(!A.Adjacent(src))
+ return
+ A.swarmer_act(src)
+ return
+
+/atom/proc/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S.DisIntegrate(src)
+
+/obj/item/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S.Integrate(src)
+
+/obj/item/weapon/gun/swarmer_act()//Stops you from eating the entire armory
+ return
+
+/turf/simulated/floor/swarmer_act()//ex_act() on turf calls it on its contents, this is to prevent attacking mobs by DisIntegrate()'ing the floor
+ return
+
+/obj/machinery/atmospherics/swarmer_act()
+ return
+
+/obj/structure/disposalpipe/swarmer_act()
+ return
+
+/obj/machinery/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S.DismantleMachine(src)
+
+/obj/machinery/light/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S.DisIntegrate(src)
+
+/obj/machinery/door/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S.DisIntegrate(src)
+
+/obj/machinery/camera/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S.DisIntegrate(src)
+ deactivate(S, 0)
+
+/obj/machinery/particle_accelerator/control_box/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S.DisIntegrate(src)
+
+/obj/machinery/field/generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S.DisIntegrate(src)
+
+/obj/machinery/gravity_generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S.DisIntegrate(src)
+
+/obj/machinery/vending/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)//It's more visually interesting than dismantling the machine
+ S.DisIntegrate(src)
+
+/obj/machinery/turretid/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S.DisIntegrate(src)
+
+/obj/machinery/chem_dispenser/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "The volatile chemicals in this machine would destroy us. Aborting."
+
+/obj/machinery/nuclearbomb/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "This device's destruction would result in the extermination of everything in the area. Aborting."
+
+/obj/machinery/dominator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "This device is attempting to corrupt our entire network; attempting to interact with it is too risky. Aborting."
+
+/obj/effect/decal/cleanable/crayon/gang/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "Searching... sensor malfunction! Target lost. Aborting."
+
+/obj/effect/rune/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "Searching... sensor malfunction! Target lost. Aborting."
+
+/obj/structure/reagent_dispensers/fueltank/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "Destroying this object would cause a chain reaction. Aborting."
+
+/obj/structure/cable/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "Disrupting the power grid would bring no benefit to us. Aborting."
+
+/obj/machinery/portable_atmospherics/canister/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "An inhospitable area may be created as a result of destroying this object. Aborting."
+
+/obj/machinery/telecomms/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "This communications relay should be preserved, it will be a useful resource to our masters in the future. Aborting."
+
+/obj/machinery/message_server/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "This communications relay should be preserved, it will be a useful resource to our masters in the future. Aborting."
+
+/obj/machinery/blackbox_recorder/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "This machine has recorded large amounts of data on this structure and its inhabitants, it will be a useful resource to our masters in the future. Aborting. "
+
+/obj/machinery/power/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "Disrupting the power grid would bring no benefit to us. Aborting."
+
+/obj/machinery/gateway/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "This bluespace source will be important to us later. Aborting."
+
+/turf/simulated/wall/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ for(var/turf/T in range(1, src))
+ if(istype(T, /turf/space) || istype(T.loc, /area/space))
+ S << "Destroying this object has the potential to cause a hull breach. Aborting."
+ return
+ ..()
+
+/obj/structure/window/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ for(var/turf/T in range(1, src))
+ if(istype(T, /turf/space) || istype(T.loc, /area/space))
+ S << "Destroying this object has the potential to cause a hull breach. Aborting."
+ return
+ ..()
+
+/obj/item/stack/cable_coil/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)//Wiring would be too effective as a resource
+ S << "This object does not contain enough materials to work with."
+
+/obj/machinery/porta_turret/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "Attempting to dismantle this machine would result in an immediate counterattack. Aborting."
+
+/mob/living/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S.DisperseTarget(src)
+
+/mob/living/simple_animal/slime/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "This biological resource is somehow resisting our bluespace transceiver. Aborting."
+
+/obj/machinery/droneDispenser/swarmer/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ S << "This object is receiving unactivated swarmer shells to help us. Aborting."
+
+
+////END CTRL CLICK FOR SWARMERS////
+
+/mob/living/simple_animal/hostile/swarmer/proc/Fabricate(var/atom/fabrication_object,var/fabrication_cost = 0)
+ if(!isturf(loc))
+ src << "This is not a suitable location for fabrication. We need more space."
+ if(resources >= fabrication_cost)
+ resources -= fabrication_cost
+ else
+ src << "You do not have the necessary resources to fabricate this object."
+ return 0
+ new fabrication_object(loc)
+ return 1
+
+/mob/living/simple_animal/hostile/swarmer/proc/Integrate(var/obj/item/target)
+ if(resources >= 100)
+ src << "We cannot hold more materials!"
+ return
+ if((target.materials[MAT_METAL]) || (target.materials[MAT_GLASS]))
+ resources++
+ do_attack_animation(target)
+ changeNext_move(CLICK_CD_MELEE)
+ var/obj/effect/swarmer/integrate/I = new /obj/effect/swarmer/integrate(get_turf(target))
+ I.pixel_x = target.pixel_x
+ I.pixel_y = target.pixel_y
+ I.pixel_z = target.pixel_z
+ if(istype(target, /obj/item/stack))
+ var/obj/item/stack/S = target
+ S.use(1)
+ if(S.amount)
+ return
+ qdel(target)
+ else
+ src << "\the [target] is incompatible with our internal matter recycler."
+ return
+
+/mob/living/simple_animal/hostile/swarmer/proc/DisIntegrate(var/atom/movable/target)
+ new /obj/effect/swarmer/disintegration(get_turf(target))
+ do_attack_animation(target)
+ changeNext_move(CLICK_CD_MELEE)
+ target.ex_act(3)
+ return
+
+/mob/living/simple_animal/hostile/swarmer/proc/DisperseTarget(var/mob/living/target)
+ if(target != src)
+ src << "Attempting to remove this being from our presence."
+ if(src.z != ZLEVEL_STATION)
+ src << "Our bluespace transceiver cannot locate a viable bluespace link, our teleportation abilities are useless in this area."
+ return
+ if(do_mob(src, target, 30))
+ var/cycle
+ for(cycle=0,cycle<100,cycle++)
+ var/random_location = locate(rand(37,202),rand(75,192),ZLEVEL_STATION)//Drunk dial a turf in the general ballpark of the station
+ if(istype(random_location, /turf/simulated/floor))
+ var/turf/simulated/floor/F = random_location
+ if(F.air)
+ var/datum/gas_mixture/A = F.air
+ if(A.oxygen >= 16 && !A.toxins && A.carbon_dioxide < 10 && !A.trace_gases.len)//Can most things breathe in this location?
+ if((A.temperature > 270) && (A.temperature < 360))//Not too hot, not too cold
+ var/pressure = A.return_pressure()
+ if((pressure > 20) && (pressure < 550))//Account for crushing pressure or vaccuums
+ if(ishuman(target))//If we're getting rid of a human, slap some zipties on them to keep them away from us a little longer
+ var/obj/item/weapon/restraints/handcuffs/cable/zipties/Z = new /obj/item/weapon/restraints/handcuffs/cable/zipties(src)
+ var/mob/living/carbon/human/H = target
+ Z.apply_cuffs(H, src)
+ do_teleport(target, F, 0)
+ playsound(src,'sound/effects/sparks4.ogg',50,1)
+ break
+ return
+
+/mob/living/simple_animal/hostile/swarmer/proc/DismantleMachine(var/obj/machinery/target)
+ do_attack_animation(target)
+ src << "We begin to dismantle this machine. We will need to be uninterrupted."
+ var/obj/effect/swarmer/dismantle/D = new /obj/effect/swarmer/dismantle(get_turf(target))
+ D.pixel_x = target.pixel_x
+ D.pixel_y = target.pixel_y
+ D.pixel_z = target.pixel_z
+ if(do_mob(src, target, 100))
+ src << "Dismantling complete."
+ var/obj/item/stack/sheet/metal/M = new /obj/item/stack/sheet/metal(target.loc)
+ M.amount = 5
+ for(var/obj/item/I in target.component_parts)
+ I.loc = M.loc
+ var/obj/effect/swarmer/disintegration/N = new /obj/effect/swarmer/disintegration(get_turf(target))
+ N.pixel_x = target.pixel_x
+ N.pixel_y = target.pixel_y
+ N.pixel_z = target.pixel_z
+ target.dropContents()
+ if(istype(target, /obj/machinery/computer))
+ var/obj/machinery/computer/C = target
+ if(C.circuit)
+ C.circuit.loc = M.loc
+ qdel(target)
+
+
+/obj/effect/swarmer //Default swarmer effect object visual feedback
+ name = "swarmer ui"
+ desc = null
+ gender = NEUTER
+ icon = 'icons/mob/swarmer.dmi'
+ icon_state = "ui_light"
+ mouse_opacity = 0
+ layer = 4
+ unacidable = 1
+
+/obj/effect/swarmer/disintegration
+ icon_state = "disintegrate"
+
+/obj/effect/swarmer/disintegration/New()
+ playsound(src.loc, "sparks", 100, 1)
+ spawn(10)
+ qdel(src)
+
+/obj/effect/swarmer/dismantle
+ icon_state = "dismantle"
+
+/obj/effect/swarmer/dismantle/New()
+ spawn(25)
+ qdel(src)
+
+/obj/effect/swarmer/integrate
+ icon_state = "integrate"
+
+/obj/effect/swarmer/integrate/New()
+ spawn(5)
+ qdel(src)
+
+/obj/effect/swarmer/destructible //Default destroyable object for swarmer constructions
+ luminosity = 1
+ mouse_opacity = 1
+ var/health = 30
+
+/obj/effect/swarmer/destructible/proc/TakeDamage(damage)
+ health -= damage
+ if(health <= 0)
+ qdel(src)
+
+/obj/effect/swarmer/destructible/bullet_act(obj/item/projectile/Proj)
+ if(Proj.damage)
+ if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
+ TakeDamage(Proj.damage)
+ ..()
+
+/obj/effect/swarmer/destructible/attackby(obj/item/weapon/I, mob/living/user, params)
+ if(istype(I, /obj/item/weapon))
+ user.changeNext_move(CLICK_CD_MELEE)
+ user.do_attack_animation(src)
+ TakeDamage(I.force)
+ return
+
+/obj/effect/swarmer/destructible/ex_act()
+ qdel(src)
+ return
+
+/obj/effect/swarmer/destructible/blob_act()
+ qdel(src)
+ return
+
+/obj/effect/swarmer/destructible/emp_act()
+ qdel(src)
+ return
+
+/obj/effect/swarmer/destructible/attack_animal(mob/living/user)
+ if(isanimal(user))
+ var/mob/living/simple_animal/S = user
+ S.do_attack_animation(src)
+ user.changeNext_move(CLICK_CD_MELEE)
+ if(S.melee_damage_type == BRUTE || S.melee_damage_type == BURN)
+ TakeDamage(rand(S.melee_damage_lower, S.melee_damage_upper))
+ return
+
+/mob/living/simple_animal/hostile/swarmer/proc/CreateTrap()
+ set name = "Create trap"
+ set category = "Swarmer"
+ set desc = "Creates a simple trap that will non-lethally electrocute anything that steps on it. Costs 5 resources"
+ if(/obj/effect/swarmer/destructible/trap in loc)
+ src << "There is already a trap here. Aborting."
+ return
+ Fabricate(/obj/effect/swarmer/destructible/trap, 5)
+ return
+
+/obj/effect/swarmer/destructible/trap
+ name = "swarmer trap"
+ desc = "A quickly assembled trap that electrifies living beings and overwhelms machine sensors. Will not retain its form if damaged enough."
+ icon_state = "trap"
+ luminosity = 1
+ health = 10
+
+/obj/effect/swarmer/destructible/trap/Crossed(var/atom/movable/AM)
+ if(isliving(AM))
+ var/mob/living/L = AM
+ if(!istype(L, /mob/living/simple_animal/hostile/swarmer))
+ playsound(loc,'sound/effects/snap.ogg',50, 1, -1)
+ L.electrocute_act(0, src, 1, 1)
+ if(isrobot(L))
+ L.Weaken(5)
+ qdel(src)
+ ..()
+
+/mob/living/simple_animal/hostile/swarmer/proc/CreateBarricade()
+ set name = "Create barricade"
+ set category = "Swarmer"
+ set desc = "Creates a barricade that will stop anything but swarmers and disabler beams from passing through."
+ if(/obj/effect/swarmer/destructible/blockade in loc)
+ src << "There is already a blockade here. Aborting."
+ return
+ if(resources < 5)
+ src << "We do not have the resources for this!"
+ return
+ if(do_mob(src, src, 10))
+ Fabricate(/obj/effect/swarmer/destructible/blockade, 5)
+ return
+
+/obj/effect/swarmer/destructible/blockade
+ name = "swarmer blockade"
+ desc = "A quickly assembled energy blockade. Will not retain its form if damaged enough, but disabler beams and swarmers pass right through."
+ icon_state = "barricade"
+ luminosity = 1
+ health = 50
+ density = 1
+ anchored = 1
+
+/obj/effect/swarmer/destructible/blockade/CanPass(atom/movable/O)
+ if(isswarmer(O))
+ return 1
+ if(istype(O, /obj/item/projectile/beam/disabler))
+ return 1
+
+/mob/living/simple_animal/hostile/swarmer/proc/CreateSwarmer()
+ set name = "Replicate"
+ set category = "Swarmer"
+ set desc = "Creates a shell for a new swarmer. Swarmers will self activate."
+ src << "We are attempting to replicate ourselves. We will need to stand still until the process is complete."
+ if(resources < 50)
+ src << "We do not have the resources for this!"
+ return
+ if(!isturf(loc))
+ src << "This is not a suitable location for replicating ourselves. We need more room."
+ return
+ if(do_mob(src, src, 100))
+ if(Fabricate(/obj/item/unactivated_swarmer, 50))
+ playsound(loc,'sound/items/poster_being_created.ogg',50, 1, -1)
+
+/mob/living/simple_animal/hostile/swarmer/proc/RepairSelf()
+ set name = "Self Repair"
+ set category = "Swarmer"
+ set desc = "Attempts to repair damage to our body. You will have to remain motionless until repairs are complete."
+ if(!isturf(loc))
+ return
+ src << "Attempting to repair damage to our body, stand by..."
+ if(do_mob(src, src, 100))
+ adjustBruteLoss(-100)
+ src << "We successfully repaired ourselves."
+
+/mob/living/simple_animal/hostile/swarmer/proc/ToggleLight()
+ if(!luminosity)
+ SetLuminosity(3)
+ else
+ SetLuminosity(0)
+
+/mob/living/simple_animal/hostile/swarmer/proc/ContactSwarmers()
+ var/message = input(src, "Announce to other swarmers", "Swarmer contact")
+ if(message)
+ for(var/mob/M in mob_list)
+ if(isswarmer(M) || (M in dead_mob_list))
+ M << "Swarm communication - [src] states: [message]"
+
+
+
+////HUD NONSENSE////
+/obj/screen/swarmer
+ icon = 'icons/mob/swarmer.dmi'
+
+/obj/screen/swarmer/FabricateTrap
+ icon_state = "ui_trap"
+ name = "Create trap (Costs 5 Resources)"
+ desc = "Creates a trap that will nonlethally shock any non-swarmer that attempts to cross it. (Costs 5 resources)"
+
+/obj/screen/swarmer/FabricateTrap/Click()
+ if(isswarmer(usr))
+ var/mob/living/simple_animal/hostile/swarmer/S = usr
+ S.CreateTrap()
+
+/obj/screen/swarmer/Barricade
+ icon_state = "ui_barricade"
+ name = "Create barricade (Costs 5 Resources)"
+ desc = "Creates a destructible barricade that will stop any non swarmer from passing it. Also allows disabler beams to pass through. (Costs 5 resources)"
+
+/obj/screen/swarmer/Barricade/Click()
+ if(isswarmer(usr))
+ var/mob/living/simple_animal/hostile/swarmer/S = usr
+ S.CreateBarricade()
+
+/obj/screen/swarmer/Replicate
+ icon_state = "ui_replicate"
+ name = "Replicate (Costs 50 Resources)"
+ desc = "Creates a another of our kind."
+
+/obj/screen/swarmer/Replicate/Click()
+ if(isswarmer(usr))
+ var/mob/living/simple_animal/hostile/swarmer/S = usr
+ S.CreateSwarmer()
+
+/obj/screen/swarmer/RepairSelf
+ icon_state = "ui_self_repair"
+ name = "Repair self"
+ desc = "Repairs damage to our body."
+
+/obj/screen/swarmer/RepairSelf/Click()
+ if(isswarmer(usr))
+ var/mob/living/simple_animal/hostile/swarmer/S = usr
+ S.RepairSelf()
+
+/obj/screen/swarmer/ToggleLight
+ icon_state = "ui_light"
+ name = "Toggle light"
+ desc = "Toggles our inbuilt light on or off."
+
+/obj/screen/swarmer/ToggleLight/Click()
+ if(isswarmer(usr))
+ var/mob/living/simple_animal/hostile/swarmer/S = usr
+ S.ToggleLight()
+
+/obj/screen/swarmer/ContactSwarmers
+ icon_state = "ui_contact_swarmers"
+ name = "Contact swarmers"
+ desc = "Sends a message to all other swarmers, should they exist."
+
+/obj/screen/swarmer/ContactSwarmers/Click()
+ if(isswarmer(usr))
+ var/mob/living/simple_animal/hostile/swarmer/S = usr
+ S.ContactSwarmers()
+
+/datum/hud/proc/swarmer_hud(ui_style = 'icons/mob/screen_midnight.dmi')
+ adding = list()
+
+ var/obj/screen/using
+
+ using = new /obj/screen/swarmer/FabricateTrap()
+ using.screen_loc = ui_rhand
+ adding += using
+
+ using = new /obj/screen/swarmer/Barricade()
+ using.screen_loc = ui_lhand
+ adding += using
+
+ using = new /obj/screen/swarmer/Replicate()
+ using.screen_loc = ui_zonesel
+ adding += using
+
+ using = new /obj/screen/swarmer/RepairSelf()
+ using.screen_loc = ui_storage1
+ adding += using
+
+ using = new /obj/screen/swarmer/ToggleLight()
+ using.screen_loc = ui_back
+ adding += using
+
+ using = new /obj/screen/swarmer/ContactSwarmers()
+ using.screen_loc = ui_inventory
+ adding += using
+
+ mymob.client.screen = list()
+ mymob.client.screen += mymob.client.void
+ mymob.client.screen += adding
+
diff --git a/code/modules/mob/living/simple_animal/bot_swarm/swarmer_event.dm b/code/modules/mob/living/simple_animal/bot_swarm/swarmer_event.dm
new file mode 100644
index 00000000000..a95a3d17d16
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/bot_swarm/swarmer_event.dm
@@ -0,0 +1,30 @@
+/datum/round_event_control/spawn_swarmer
+ name = "Spawn Swarmer Shell"
+ typepath = /datum/round_event/spawn_swarmer
+ weight = 7
+ max_occurrences = 1 //Only once okay fam
+ earliest_start = 18000 //30 minutes
+
+
+/datum/round_event/spawn_swarmer
+
+
+/datum/round_event/spawn_swarmer/start()
+ if(find_swarmer())
+ return 0
+ if(!the_gateway)
+ return 0
+ new /obj/item/unactivated_swarmer(get_turf(the_gateway))
+ if(prob(25)) //25% chance to announce it to the crew
+ var/swarmer_report = "[command_name()] High-Priority Update
"
+ swarmer_report += "
Our long-range sensors have detected an odd signal emanating from your station's gateway. We recommend immediate investigation of your gateway, as something may have come \
+ through."
+ print_command_report(swarmer_report,"Classified [command_name()] Update")
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg')
+
+
+/datum/round_event/spawn_swarmer/proc/find_swarmer()
+ for(var/mob/living/M in mob_list)
+ if(istype(M, /mob/living/simple_animal/hostile/swarmer) && M.client) //If there is a swarmer with an active client, we've found our swarmer
+ return 1
+ return 0
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index a0f2e39fca2..00068884b21 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -16,6 +16,7 @@
attack_sound = 'sound/weapons/punch1.ogg'
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
+ healable = 0
faction = list("cult")
flying = 1
unique_name = 1
diff --git a/code/modules/mob/living/simple_animal/friendly/butterfly.dm b/code/modules/mob/living/simple_animal/friendly/butterfly.dm
index b1af5b5230e..a020baf05a9 100644
--- a/code/modules/mob/living/simple_animal/friendly/butterfly.dm
+++ b/code/modules/mob/living/simple_animal/friendly/butterfly.dm
@@ -16,6 +16,7 @@
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
ventcrawler = 2
mob_size = MOB_SIZE_TINY
+ gold_core_spawnable = 2
/mob/living/simple_animal/butterfly/New()
..()
diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm
index 3268bd3007e..9c253d5d9c1 100644
--- a/code/modules/mob/living/simple_animal/friendly/cat.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cat.dm
@@ -20,6 +20,7 @@
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
+ gold_core_spawnable = 2
//RUNTIME IS ALIVE! SQUEEEEEEEE~
/mob/living/simple_animal/pet/cat/Runtime
@@ -31,6 +32,7 @@
gender = FEMALE
var/turns_since_scan = 0
var/mob/living/simple_animal/mouse/movement_target
+ gold_core_spawnable = 0
/mob/living/simple_animal/pet/cat/Runtime/Life()
//MICE!
@@ -69,6 +71,7 @@
/mob/living/simple_animal/pet/cat/Proc
name = "Proc"
+ gold_core_spawnable = 0
/mob/living/simple_animal/pet/cat/kitten
name = "kitten"
diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm
index ef3ce5448ad..7bf0522ab86 100644
--- a/code/modules/mob/living/simple_animal/friendly/crab.dm
+++ b/code/modules/mob/living/simple_animal/friendly/crab.dm
@@ -19,6 +19,7 @@
ventcrawler = 2
var/obj/item/inventory_head
var/obj/item/inventory_mask
+ gold_core_spawnable = 2
/mob/living/simple_animal/crab/Life()
..()
@@ -40,4 +41,5 @@
desc = "It's Coffee, the other pet!"
response_help = "pets"
response_disarm = "gently pushes aside"
- response_harm = "stomps"
\ No newline at end of file
+ response_harm = "stomps"
+ gold_core_spawnable = 0
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm
index bc0ebe9883b..fa542a77592 100644
--- a/code/modules/mob/living/simple_animal/friendly/dog.dm
+++ b/code/modules/mob/living/simple_animal/friendly/dog.dm
@@ -29,6 +29,7 @@
var/obj/item/inventory_head
var/obj/item/inventory_back
var/facehugger
+ gold_core_spawnable = 2
/mob/living/simple_animal/pet/dog/pug
name = "\improper pug"
@@ -39,6 +40,7 @@
icon_living = "pug"
icon_dead = "pug_dead"
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/pug = 3)
+ gold_core_spawnable = 2
/mob/living/simple_animal/pet/dog/corgi/New()
..()
@@ -53,12 +55,6 @@
..()
regenerate_icons()
-/mob/living/simple_animal/pet/dog/corgi/sac_act(obj/effect/rune/R, victim) //Still the best thing in this game
- usr << "Even dark gods from another plane have standards, sicko."
- usr.reagents.add_reagent("hell_water", 2)
- R.stone_or_gib(victim)
-
-
/mob/living/simple_animal/pet/dog/corgi/show_inv(mob/user)
user.set_machine(src)
if(user.stat) return
@@ -275,7 +271,9 @@
return valid
/mob/living/simple_animal/pet/dog/corgi/proc/update_corgi_fluff()
- switch(src.inventory_head.type)
+ if(!inventory_head)
+ return
+ switch(inventory_head.type)
if(/obj/item/clothing/head/helmet)
name = "Sergeant [real_name]"
desc = "The ever-loyal, the ever-vigilant."
@@ -388,6 +386,7 @@
response_help = "pets"
response_disarm = "bops"
response_harm = "kicks"
+ gold_core_spawnable = 0
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
..()
@@ -511,6 +510,7 @@
response_harm = "kicks"
var/turns_since_scan = 0
var/puppies = 0
+ gold_core_spawnable = 0
//Lisa already has a cute bow!
/mob/living/simple_animal/pet/dog/corgi/Lisa/Topic(href, href_list)
@@ -532,7 +532,7 @@
dir = i
sleep(1)
-/mob/living/simple_animal/pet/pug/Life()
+/mob/living/simple_animal/pet/dog/pug/Life()
..()
if(!stat && !resting && !buckled)
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index 4b349ee1ddb..2c60049656a 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -24,6 +24,7 @@
wander = 0
speed = 0
ventcrawler = 2
+ healable = 0
density = 0
pass_flags = PASSTABLE | PASSMOB
sight = (SEE_TURFS | SEE_OBJS)
@@ -79,7 +80,7 @@
/mob/living/simple_animal/drone/Destroy()
qdel(access_card) //Otherwise it ends up on the floor!
- ..()
+ return ..()
/mob/living/simple_animal/drone/Login()
..()
diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
index 96b24a86fe7..2a1a2e140e7 100644
--- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
@@ -25,11 +25,14 @@
melee_damage_upper = 2
environment_smash = 0
stop_automated_movement_when_pulled = 1
- var/datum/reagents/udder = null
+ var/obj/udder/udder = null
/mob/living/simple_animal/hostile/retaliate/goat/New()
- udder = new(50)
- udder.my_atom = src
+ udder = new()
+ ..()
+/mob/living/simple_animal/hostile/retaliate/goat/Destroy()
+ qdel(udder)
+ udder = null
..()
/mob/living/simple_animal/hostile/retaliate/goat/Life()
@@ -43,15 +46,11 @@
enemies = list()
LoseTarget()
src.visible_message("[src] calms down.")
-
if(stat == CONSCIOUS)
- if(udder && prob(5))
- udder.add_reagent("milk", rand(5, 10))
-
+ udder.generateMilk()
if(locate(/obj/effect/spacevine) in loc)
var/obj/effect/spacevine/SV = locate(/obj/effect/spacevine) in loc
SV.eat(src)
-
if(!pulledby)
for(var/direction in shuffle(list(1,2,4,8,5,6,9,10)))
var/step = get_step(src, direction)
@@ -70,18 +69,12 @@
var/obj/effect/spacevine/SV = locate(/obj/effect/spacevine) in loc
SV.eat(src)
-
/mob/living/simple_animal/hostile/retaliate/goat/attackby(obj/item/O, mob/user, params)
if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass))
- user.visible_message("[user] milks [src] using \the [O].", "You milk [src] using \the [O].")
- var/obj/item/weapon/reagent_containers/glass/G = O
- var/transfered = udder.trans_id_to(G, "milk", rand(5,10))
- if(G.reagents.total_volume >= G.volume)
- user << "[O] is full!"
- if(!transfered)
- user << "The udder is dry! Wait a bit longer..."
+ udder.milkAnimal(O, user)
else
..()
+
//cow
/mob/living/simple_animal/cow
name = "cow"
@@ -104,30 +97,28 @@
attacktext = "kicks"
attack_sound = 'sound/weapons/punch1.ogg'
health = 50
- var/datum/reagents/udder = null
+ var/obj/udder/udder = null
+ gold_core_spawnable = 2
/mob/living/simple_animal/cow/New()
- udder = new(50)
- udder.my_atom = src
+ udder = new()
+ ..()
+
+/mob/living/simple_animal/cow/Destroy()
+ qdel(udder)
+ udder = null
..()
/mob/living/simple_animal/cow/attackby(obj/item/O, mob/user, params)
if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass))
- user.visible_message("[user] milks [src] using \the [O].", "You milk [src] using \the [O].")
- var/obj/item/weapon/reagent_containers/glass/G = O
- var/transfered = udder.trans_id_to(G, "milk", rand(5,10))
- if(G.reagents.total_volume >= G.volume)
- user << "[O] is full."
- if(!transfered)
- user << "The udder is dry. Wait a bit longer..."
+ udder.milkAnimal(O, user)
else
..()
/mob/living/simple_animal/cow/Life()
. = ..()
if(stat == CONSCIOUS)
- if(udder && prob(5))
- udder.add_reagent("milk", rand(5, 10))
+ udder.generateMilk()
/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M)
if(!stat && M.a_intent == "disarm" && icon_state != icon_dead)
@@ -169,6 +160,7 @@
var/amount_grown = 0
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_TINY
+ gold_core_spawnable = 2
/mob/living/simple_animal/chick/New()
..()
@@ -219,6 +211,7 @@ var/global/chicken_count = 0
var/list/feedMessages = list("It clucks happily.","It clucks happily.")
var/list/layMessage = list("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.")
var/list/validColors = list("brown","black","white")
+ gold_core_spawnable = 2
/mob/living/simple_animal/chicken/New()
..()
@@ -274,3 +267,29 @@ var/global/chicken_count = 0
qdel(src)
else
SSobj.processing.Remove(src)
+
+/obj/udder
+
+/obj/udder/New()
+ reagents = new(50)
+ reagents.my_atom = src
+ reagents.add_reagent("milk", 20)
+
+/obj/udder/proc/generateMilk()
+ if(prob(5))
+ reagents.add_reagent("milk", rand(5, 10))
+
+/obj/udder/proc/milkAnimal(obj/O, mob/user)
+ var/obj/item/weapon/reagent_containers/glass/G = O
+ if(G.reagents.total_volume >= G.volume)
+ user << "[O] is full."
+ return
+ var/transfered = reagents.trans_id_to(G, "milk", rand(5,10))
+ if(transfered)
+ user.visible_message("[user] milks [src] using \the [O].", "You milk [src] using \the [O].")
+ else
+ user << "The udder is dry. Wait a bit longer..."
+
+/obj/udder/Destroy()
+ qdel(reagents)
+ ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/friendly/fox.dm b/code/modules/mob/living/simple_animal/friendly/fox.dm
index fefd67e907a..2371ba8c00a 100644
--- a/code/modules/mob/living/simple_animal/friendly/fox.dm
+++ b/code/modules/mob/living/simple_animal/friendly/fox.dm
@@ -1,7 +1,7 @@
//Foxxy
/mob/living/simple_animal/pet/fox
name = "fox"
- desc = "It's a fox. I wonder what it says?"
+ desc = "It's a fox."
icon = 'icons/mob/pets.dmi'
icon_state = "fox"
icon_living = "fox"
@@ -17,8 +17,10 @@
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
+ gold_core_spawnable = 2
//Captain fox
/mob/living/simple_animal/pet/fox/Renault
name = "Renault"
- desc = "Renault, the Captain's trustworthy fox. I wonder what it says?"
\ No newline at end of file
+ desc = "Renault, the Captain's trustworthy fox."
+ gold_core_spawnable = 0
diff --git a/code/modules/mob/living/simple_animal/friendly/lizard.dm b/code/modules/mob/living/simple_animal/friendly/lizard.dm
index b03101df7f1..e958eea35e9 100644
--- a/code/modules/mob/living/simple_animal/friendly/lizard.dm
+++ b/code/modules/mob/living/simple_animal/friendly/lizard.dm
@@ -18,3 +18,4 @@
density = 0
pass_flags = PASSTABLE | PASSMOB
mob_size = MOB_SIZE_SMALL
+ gold_core_spawnable = 2
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index 9b0bc3afd0c..fbe54636bcb 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -22,6 +22,7 @@
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_TINY
var/body_color //brown, gray and white, leave blank for random
+ gold_core_spawnable = 2
/mob/living/simple_animal/mouse/New()
..()
@@ -77,6 +78,7 @@
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "splats"
+ gold_core_spawnable = 0
/obj/item/trash/deadmouse
name = "dead mouse"
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index b102ef80167..6940476fed3 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -23,6 +23,8 @@
melee_damage_lower = 15
melee_damage_upper = 15
butcher_results = list(/obj/item/weapon/ectoplasm = 1)
+ AIStatus = AI_OFF
+ var/animated_manifest = FALSE
var/cooldown = 0
var/damage_transfer = 1 //how much damage from each attack we transfer to the owner
var/mob/living/summoner
@@ -70,7 +72,10 @@
src.summoner.adjustBruteLoss(damage)
if(damage)
src.summoner << "Your [src.name] is under attack! You take damage!"
-
+ src.summoner.visible_message("Blood sprays from [summoner] as [src] takes damage!")
+ if(src.summoner.stat == UNCONSCIOUS)
+ src.summoner << "Your body can't take the strain of sustaining [src.name] in this condition, it begins to fall apart!"
+ src.summoner.adjustCloneLoss(damage/2)
/mob/living/simple_animal/hostile/guardian/ex_act(severity, target)
switch (severity)
@@ -98,6 +103,11 @@
if(src.loc == summoner)
src.loc = get_turf(summoner)
cooldown = world.time + 30
+ if(animated_manifest)
+ var/end_icon = icon_state
+ icon_state = "parasite_forming"
+ spawn(6)
+ icon_state = end_icon
/mob/living/simple_animal/hostile/guardian/verb/Recall()
set name = "Recall"
@@ -106,6 +116,7 @@
if(cooldown > world.time)
return
src.loc = summoner
+ buckled = null
cooldown = world.time + 30
/mob/living/simple_animal/hostile/guardian/verb/Communicate()
@@ -113,9 +124,10 @@
set category = "Guardian"
set desc = "Communicate telepathically with your summoner."
var/input = stripped_input(src, "Please enter a message to tell your summoner.", "Guardian", "")
+ if(!input) return
for(var/mob/M in mob_list)
- if(M == src.summoner)
+ if(M == src.summoner || (M in dead_mob_list))
M << "[src]: [input]"
src << "[src]: [input]"
@@ -124,9 +136,14 @@
set category = "Guardian"
set desc = "Communicate telepathically with your guardian."
var/input = stripped_input(src, "Please enter a message to tell your guardian.", "Message", "")
+ if(!input) return
- for(var/mob/living/simple_animal/hostile/guardian/M in mob_list)
- if(M.summoner == src)
+ for(var/mob/M in mob_list)
+ if(istype (M, /mob/living/simple_animal/hostile/guardian))
+ var/mob/living/simple_animal/hostile/guardian/G = M
+ if(G.summoner == src)
+ G << "[src]: [input]"
+ else if (M in dead_mob_list)
M << "[src]: [input]"
src << "[src]: [input]"
@@ -142,32 +159,51 @@
melee_damage_upper = 10
attack_sound = 'sound/items/Welder.ogg'
attacktext = "sears"
- damage_transfer = 0.7
+ damage_transfer = 0.8
range = 10
- playstyle_string = "As a fire type, you have only light damage resistance, but will ignite any enemy you bump into."
+ playstyle_string = "As a Chaos type, you have only light damage resistance, but will ignite any enemy you bump into. In addition, your melee attacks will randomly teleport enemies."
environment_smash = 1
- magic_fluff_string = "..And draw Atmosia, bringer of cleansing fires!"
- tech_fluff_string = "Boot sequence complete. Incendiary combat modules loaded. Nanoswarm online."
- bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of igniting enemies on touch."
+ magic_fluff_string = "..And draw the Wizard, bringer of endless chaos!"
+ tech_fluff_string = "Boot sequence complete. Crowd control modules activated. Holoparasite swarm online."
+ bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, ready to sow havoc at random."
+/mob/living/simple_animal/hostile/guardian/fire/Life() //Dies if the summoner dies
+ ..()
+ if(summoner)
+ summoner.ExtinguishMob()
+ summoner.adjust_fire_stacks(-20)
+
+/mob/living/simple_animal/hostile/guardian/fire/AttackingTarget()
+ ..()
+ if(prob(30))
+ if(istype(target, /atom/movable))
+ var/atom/movable/M = target
+ if(!M.anchored && M != src.summoner)
+ do_teleport(M, M, 10)
/mob/living/simple_animal/hostile/guardian/fire/Crossed(AM as mob|obj)
if(istype(AM, /mob/living/))
var/mob/living/M = AM
if(AM != src.summoner)
- M.adjust_fire_stacks(10)
+ M.adjust_fire_stacks(7)
M.IgniteMob()
+/mob/living/simple_animal/hostile/guardian/fire/Bumped(AM as mob|obj)
+ if(istype(AM, /mob/living/))
+ var/mob/living/M = AM
+ if(AM != src.summoner)
+ M.adjust_fire_stacks(7)
+ M.IgniteMob()
//Standard
/mob/living/simple_animal/hostile/guardian/punch
- melee_damage_lower = 25
- melee_damage_upper = 25
+ melee_damage_lower = 20
+ melee_damage_upper = 20
damage_transfer = 0.5
playstyle_string = "As a standard type you have no special abilities, but have a high damage resistance and a powerful attack capable of smashing through walls."
environment_smash = 2
magic_fluff_string = "..And draw the Assistant, faceless and generic, but never to be underestimated."
- tech_fluff_string = "Boot sequence complete. Standard combat modules loaded. Nanoswarm online."
+ tech_fluff_string = "Boot sequence complete. Standard combat modules loaded. Holoparasite swarm online."
bio_fluff_string = "Your scarab swarm stirs to life, ready to tear apart your enemies."
var/battlecry = "AT"
@@ -191,121 +227,209 @@
playsound(loc, src.attack_sound, 50, 1, 1)
playsound(loc, src.attack_sound, 50, 1, 1)
-
-
-
-//Fast Standard. Does less damage, has less resistance, but moves faster, has higher range
-
-/mob/living/simple_animal/hostile/guardian/fast
- melee_damage_lower = 20
- melee_damage_upper = 20
- damage_transfer = 0.7
- speed = -1
- range = 15
- attacktext = "slices"
- attack_sound = 'sound/weapons/bladeslice.ogg'
- playstyle_string = "As a fast standard type, you have no special abilities and only light damage resistance, but deal high damage at high speed."
- environment_smash = 1
- magic_fluff_string = "..And draw the Shoes, bringer of great speed. The card is badly damaged, and barely legible."
- tech_fluff_string = "Boot sequence complete. High speed combat modules active. Nanoswarm online."
- bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of moving at blinding speed."
-
-//Defender. Does no damage, takes no damage, moves slowly.
-/mob/living/simple_animal/hostile/guardian/shield
- melee_damage_lower = 0
- melee_damage_upper = 0
- speed = 1
- range = 10
- damage_transfer = 0
- friendly = "stares down"
- status_flags = CANPUSH
- playstyle_string = "As a defensive type, you are incapable of attacking and move slowly, but completely nullify any attack that hits you."
- magic_fluff_string = "..And draw the Juggernaut, an invincible, unstoppable force."
- tech_fluff_string = "Boot sequence complete. Defensive modules active. Nanoswarm online."
- bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, helpless, but invulnerable."
-
-//Scout. No damage, high range, high mobility, low resistance
-
-/mob/living/simple_animal/hostile/guardian/scout
- range = 255
- incorporeal_move = 1
- damage_transfer = 1.2
- melee_damage_lower = 0
- melee_damage_upper = 0
- alpha = 60
- friendly = "quietly assesses"
- playstyle_string = "As a scout type, you are incapable of attacking, but have infinite range, can pass through walls, and crawl through vents."
- magic_fluff_string = "..And draw the AI, all seeing and all knowing."
- tech_fluff_string = "Boot sequence complete. Surveillance modules loaded. Nanoswarm online."
- bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, helpless, but near invsible, and capable of near unlimited travel."
-
//Healer
/mob/living/simple_animal/hostile/guardian/healer
- a_intent = "help"
+ a_intent = "harm"
friendly = "heals"
- speed = 1
- melee_damage_lower = 0
- melee_damage_upper = 0
- playstyle_string = "As a healer type, you are incapable of attacking, but can mend any wound simply by touching a target."
- magic_fluff_string = "..And draw the CMO, a potent force of life and health."
- tech_fluff_string = "Boot sequence complete. Medical modules active. Nanoswarm online."
- bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of mending wounds."
+ speed = 0
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ playstyle_string = "As a Support type, you may toggle your basic attacks to a healing mode. In addition, Shift-Clicking on an adjacent mob will warp them to your bluespace beacon after a short delay."
+ magic_fluff_string = "..And draw the CMO, a potent force of life...and death."
+ tech_fluff_string = "Boot sequence complete. Medical modules active. Bluespace modules activated. Holoparasite swarm online."
+ bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of mending wounds and travelling via bluespace."
+ var/turf/simulated/floor/beacon
+ var/beacon_cooldown = 0
+ var/toggle = FALSE
/mob/living/simple_animal/hostile/guardian/healer/AttackingTarget()
..()
+ if(toggle == TRUE)
+ if(src.loc == summoner)
+ src << "You must be manifested to heal!"
+ return
+ if(iscarbon(target))
+ var/mob/living/carbon/C = target
+ C.adjustBruteLoss(-5)
+ C.adjustFireLoss(-5)
+ C.adjustOxyLoss(-5)
+ C.adjustToxLoss(-5)
+
+/mob/living/simple_animal/hostile/guardian/healer/verb/ToggleMode()
+ set name = "Toggle Mode"
+ set category = "Guardian"
+ set desc = "Toggle between combat and healing modes."
if(src.loc == summoner)
- src << "You must be manifested to heal!"
+ if(toggle)
+ a_intent = "harm"
+ speed = 0
+ damage_transfer = 0.7
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ src << "You switch to combat mode."
+ toggle = FALSE
+ else
+ a_intent = "help"
+ speed = 1
+ damage_transfer = 1
+ melee_damage_lower = 0
+ melee_damage_upper = 0
+ src << "You switch to healing mode."
+ toggle = TRUE
+ else
+ src << "You have to be recalled to toggle modes!"
+
+
+/mob/living/simple_animal/hostile/guardian/healer/verb/Beacon()
+ set name = "Place Bluespsace Beacon"
+ set category = "Guardian"
+ set desc = "Mark a floor as your beacon point, allowing you to warp targets to it. Your beacon will not work in unfavorable atmospheric conditions."
+ if(beacon_cooldownBeacon placed! You may now warp targets to it, including your user, via Shift+Click. "
+ if(beacon)
+ beacon.ChangeTurf(/turf/simulated/floor/plating)
+ beacon = F
+ beacon_cooldown = world.time+3000
+
+ else
+ src << "Your power is on cooldown. You must wait five minutes between placing beacons."
+
+/mob/living/simple_animal/hostile/guardian/healer/ShiftClickOn(atom/movable/A)
+ if(src.loc == summoner)
+ src << "You must be manifested to warp a target!"
return
- if(iscarbon(target))
- var/mob/living/carbon/C = target
- C.adjustBruteLoss(-5)
- C.adjustFireLoss(-5)
- C.adjustOxyLoss(-5)
- C.adjustToxLoss(-5)
+ if(!beacon)
+ src << "You need a beacon placed to warp things!"
+ return
+ if(!Adjacent(A))
+ src << "You must be adjacent to your target!"
+ return
+ if((A.anchored))
+ src << "Your target can not be anchored!"
+ return
+ src << "You begin to warp [A]"
+ if(do_mob(src, A, 50))
+ if(!A.anchored)
+ if(src.beacon) //Check that the beacon still exists and is in a safe place. No instant kills.
+ if(beacon.air)
+ var/datum/gas_mixture/Z = beacon.air
+ if(Z.oxygen >= 16 && !Z.toxins && Z.carbon_dioxide < 10 && !Z.trace_gases.len)
+ if((Z.temperature > 270) && (Z.temperature < 360))
+ var/pressure = Z.return_pressure()
+ if((pressure > 20) && (pressure < 550))
+ do_teleport(A, beacon, 0)
+ else
+ src << "The beacon isn't in a safe location!"
+ else
+ src << "The beacon isn't in a safe location!"
+ else
+ src << "You need a beacon to warp things!"
+ else
+ src << "You need to hold still!"
+
+
+///////////////////Ranged
/obj/item/projectile/guardian
name = "crystal spray"
icon_state = "guardian"
- damage = 4
+ damage = 5
damage_type = BRUTE
/mob/living/simple_animal/hostile/guardian/ranged
a_intent = "help"
+ friendly = "quietly assesses"
melee_damage_lower = 10
melee_damage_upper = 10
- damage_transfer = 1.2
+ damage_transfer = 0.9
projectiletype = /obj/item/projectile/guardian
ranged_cooldown_cap = 0
projectilesound = 'sound/effects/hit_on_shattered_glass.ogg'
ranged = 1
range = 13
- playstyle_string = "As a ranged type, you have only light damage resistance, but are capable of spraying shards of crystal at incredibly high speed."
+ playstyle_string = "As a ranged type, you have only light damage resistance, but are capable of spraying shards of crystal at incredibly high speed. You can also deploy surveillance snares to monitor enemy movement. Finally, you can switch to scout mode, in which you can't attack, but can move without limit."
magic_fluff_string = "..And draw the Sentinel, an alien master of ranged combat."
- tech_fluff_string = "Boot sequence complete. Ranged combat modules active. Nanoswarm online."
+ tech_fluff_string = "Boot sequence complete. Ranged combat modules active. Holoparasite swarm online."
bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of spraying shards of crystal."
+ var/list/snares = list()
+ var/toggle = FALSE
+
+/mob/living/simple_animal/hostile/guardian/ranged/verb/ToggleMode()
+ set name = "Toggle Mode"
+ set category = "Guardian"
+ set desc = "Toggle between combat and scout modes."
+ if(src.loc == summoner)
+ if(toggle)
+ ranged = 1
+ melee_damage_lower = 10
+ melee_damage_upper = 10
+ alpha = 255
+ range = 13
+ incorporeal_move = 0
+ src << "You switch to combat mode."
+ toggle = FALSE
+ else
+ ranged = 0
+ melee_damage_lower = 0
+ melee_damage_upper = 0
+ alpha = 60
+ range = 255
+ incorporeal_move = 1
+ src << "You switch to scout mode."
+ toggle = TRUE
+ else
+ src << "You have to be recalled to toggle modes!"
+
+/mob/living/simple_animal/hostile/guardian/ranged/verb/Snare()
+ set name = "Set Surveillance Trap"
+ set category = "Guardian"
+ set desc = "Set an invisible trap that will alert you when living creatures walk over it. Max of 5"
+ if(src.snares.len <6)
+ var/turf/snare_loc = get_turf(src.loc)
+ var/obj/item/effect/snare/S = new /obj/item/effect/snare(snare_loc)
+ S.spawner = src
+ S.name = "[get_area(snare_loc)] trap ([rand(1, 1000)])"
+ src.snares |= S
+ src << "Surveillance trap deployed!"
+ else
+ src << "You have too many traps deployed. Delete some first."
+
+/mob/living/simple_animal/hostile/guardian/ranged/verb/DisarmSnare()
+ set name = "Remove Surveillance Trap"
+ set category = "Guardian"
+ set desc = "Disarm unwanted surveillance traps."
+ var/picked_snare = input(src, "Pick which trap to disarm", "Disarm Trap") as null|anything in src.snares
+ if(picked_snare)
+ src.snares -= picked_snare
+ qdel(picked_snare)
+ src << "Snare disarmed."
+
+/obj/item/effect/snare
+ name = "snare"
+ desc = "You shouldn't be seeing this!"
+ var/mob/living/spawner
+ invisibility = 1
-/mob/living/simple_animal/hostile/guardian/bluespace
- ranged = 1
- range = 15
- melee_damage_lower = 15
- melee_damage_upper = 15
- speed = -1
- attack_sound = 'sound/weapons/emitter.ogg'
- projectiletype = /obj/item/projectile/magic/teleport
- projectilesound = 'sound/weapons/emitter.ogg'
- playstyle_string = "As a bluespace type, you have only light damage resistance, but are capable of shooting teleporation bolts as well as flinging enemies away with your standard attack."
- magic_fluff_string = "..And draw the Wizard, master of teleportation."
- tech_fluff_string = "Boot sequence complete. Experimental bluespace combat modules active. Nanoswarm online."
- bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, crackling with bluespace energy."
+/obj/item/effect/snare/Crossed(AM as mob|obj)
+ if(istype(AM, /mob/living/))
+ var/turf/snare_loc = get_turf(src.loc)
+ if(spawner)
+ spawner << "[AM] has crossed your surveillance trap at [get_area(snare_loc)]."
+ if(istype(spawner, /mob/living/simple_animal/hostile/guardian))
+ var/mob/living/simple_animal/hostile/guardian/G = spawner
+ if(G.summoner)
+ G.summoner << "[AM] has crossed your surveillance trap at [get_area(snare_loc)]."
-/mob/living/simple_animal/hostile/guardian/bluespace/AttackingTarget()
- ..()
- if(istype(target, /atom/movable))
- var/atom/movable/M = target
- if(!M.anchored && M != src.summoner)
- do_teleport(M, M, 10)
+////Bomb
/mob/living/simple_animal/hostile/guardian/bomb
melee_damage_lower = 15
@@ -314,7 +438,7 @@
range = 13
playstyle_string = "As an explosive type, you have only moderate close combat abilities, but are capable of converting any adjacent item into a disguised bomb via shift click."
magic_fluff_string = "..And draw the Scientist, master of explosive death."
- tech_fluff_string = "Boot sequence complete. Explosive modules active. Nanoswarm online."
+ tech_fluff_string = "Boot sequence complete. Explosive modules active. Holoparasite swarm online."
bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of stealthily booby trapping items."
var/bomb_cooldown = 0
@@ -339,7 +463,6 @@
var/mob/living/spawner
-
/obj/item/weapon/guardian_bomb/proc/disguise(var/obj/A)
A.loc = src
stored_obj = A
@@ -373,15 +496,6 @@
user << "Looks odd!"
-
-
-
-
-
-
-
-
-
////////Creation
/obj/item/weapon/guardiancreator
@@ -395,10 +509,18 @@
var/use_message = "You shuffle the deck..."
var/used_message = "All the cards seem to be blank now."
var/failure_message = "..And draw a card! It's...blank? Maybe you should try again later."
- var/list/possible_guardians = list("Fire", "Standard", "Scout", "Shield", "Ranged", "Healer", "Fast", "Explosive")
+ var/ling_failure = "The deck refuses to respond to a souless creature such as you."
+ var/list/possible_guardians = list("Chaos", "Standard", "Ranged", "Support", "Explosive")
var/random = TRUE
/obj/item/weapon/guardiancreator/attack_self(mob/living/user)
+ for(var/mob/living/simple_animal/hostile/guardian/G in living_mob_list)
+ if (G.summoner == user)
+ user << "You already have a [mob_name]!"
+ return
+ if(user.mind && user.mind.changeling)
+ user << "[ling_failure]"
+ return
if(used == TRUE)
user << "[used_message]"
return
@@ -439,44 +561,29 @@
if(random)
gaurdiantype = pick(possible_guardians)
else
- gaurdiantype = input(user, "Pick the type pf [mob_name]", "[mob_name] Creation") as null|anything in possible_guardians
+ gaurdiantype = input(user, "Pick the type of [mob_name]", "[mob_name] Creation") as null|anything in possible_guardians
var/pickedtype = /mob/living/simple_animal/hostile/guardian/punch
var/picked_color = randomColor(0)
switch(gaurdiantype)
- if("Fire")
+ if("Chaos")
pickedtype = /mob/living/simple_animal/hostile/guardian/fire
if("Standard")
pickedtype = /mob/living/simple_animal/hostile/guardian/punch
- if("Scout")
- pickedtype = /mob/living/simple_animal/hostile/guardian/scout
-
- if("Shield")
- pickedtype = /mob/living/simple_animal/hostile/guardian/shield
-
if("Ranged")
pickedtype = /mob/living/simple_animal/hostile/guardian/ranged
- if("Healer")
+ if("Support")
pickedtype = /mob/living/simple_animal/hostile/guardian/healer
- if("Fast")
- pickedtype = /mob/living/simple_animal/hostile/guardian/fast
-
- if("Bluespace")
- pickedtype = /mob/living/simple_animal/hostile/guardian/bluespace
-
if("Explosive")
pickedtype = /mob/living/simple_animal/hostile/guardian/bomb
var/mob/living/simple_animal/hostile/guardian/G = new pickedtype(user)
G.summoner = user
G.key = key
- G.name = "[mob_name] [capitalize(picked_color)]"
- G.real_name = "[mob_name] [capitalize(picked_color)]"
- G.color = color2hex(picked_color)
G << "You are a [mob_name] bound to serve [user.real_name]."
G << "You are capable of manifesting or recalling to your master with verbs in the Guardian tab. You will also find a verb to communicate with them privately there."
G << "While personally invincible, you will die if [user.real_name] does, and any damage dealt to you will have a portion passed on to them as you feed upon them to sustain yourself."
@@ -484,37 +591,42 @@
user.verbs += /mob/living/proc/guardian_comm
switch (theme)
if("magic")
+ G.name = "[mob_name] [capitalize(picked_color)]"
+ G.color = color2hex(picked_color)
+ G.real_name = "[mob_name] [capitalize(picked_color)]"
user << "[G.magic_fluff_string]."
if("tech")
+ var/colour = pick("orange", "neon", "pink", "red", "blue", "green")
+ G.name = "[mob_name] [capitalize(colour)]"
+ G.real_name = "[mob_name] [capitalize(colour)]"
+ G.icon_living = "parasite[colour]"
+ G.icon_state = "parasite[colour]"
+ G.animated_manifest = TRUE
user << "[G.tech_fluff_string]."
- G.attacktext = "swarms"
G.speak_emote = list("states")
if("bio")
user << "[G.bio_fluff_string]."
G.attacktext = "swarms"
G.speak_emote = list("chitters")
-
-
/obj/item/weapon/guardiancreator/choose
random = FALSE
/obj/item/weapon/guardiancreator/tech
- name = "parasitic nanomachine injector"
- desc = "Though powerful in combat, these nanomachines require a living host as a source of fuel and home base."
+ name = "holoparasite injector"
+ desc = "It contains alien nanoswarm of unknown origin. Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, it requires an organic host as a home base and source of fuel."
icon = 'icons/obj/syringe.dmi'
icon_state = "combat_hypo"
theme = "tech"
- mob_name = "Nanomachine Swarm"
+ mob_name = "Holoparasite"
use_message = "You start to power on the injector..."
used_message = "The injector has already been used."
failure_message = "...ERROR. BOOT SEQUENCE ABORTED. AI FAILED TO INTIALIZE. PLEASE CONTACT SUPPORT OR TRY AGAIN LATER."
+ ling_failure = "The holoparasites recoil in horror. They want nothing to do with a creature like you."
/obj/item/weapon/guardiancreator/tech/choose
random = FALSE
-
-
/obj/item/weapon/guardiancreator/biological
name = "scarab egg cluster"
desc = "A parasitic species that will nest in the closest living creature upon birth. While not great for your health, they'll defend their new 'hive' to the death."
@@ -528,3 +640,34 @@
/obj/item/weapon/guardiancreator/biological/choose
random = FALSE
+
+
+/obj/item/weapon/paper/guardian
+ name = "Holoparasite Guide"
+ icon_state = "alienpaper_words"
+ info = {"A list of Holoparasite Types
+
+
+ Chaos: Ignites mobs on touch. teleports them at random on attack. Automatically extinguishes the user if they catch fire.
+
+ Standard:Devestating close combat attacks and high damage resist. No special powers.
+
+ Ranged: Has two modes. Ranged: Extremely weak, highly spammable projectile attack. Scout: Can not attack, but can move through walls. Can lay surveillance snares in either mode.
+
+ Support:Has two modes. Combat: Medium power attacks and damage resist. Healer: Attacks heal damage, but low damage resist and slow movemen. Can deploy a bluespace beacon and warp targets to it (including you) in either mode.
+
+ Explosive: High damage resist and medium power attack. Can turn any object into a bomb, dealing explosive damage to the next person to touch it. The object will return to normal after the trap is triggered.
+"}
+
+/obj/item/weapon/paper/guardian/update_icon()
+ return
+
+
+/obj/item/weapon/storage/box/syndie_kit/guardian
+ name = "holoparasite injector kit"
+
+/obj/item/weapon/storage/box/syndie_kit/guardian/New()
+ ..()
+ new /obj/item/weapon/guardiancreator/tech/choose(src)
+ new /obj/item/weapon/paper/guardian(src)
+ return
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index 08ca902017d..56465782b39 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -29,6 +29,7 @@
see_in_dark = 8
see_invisible = SEE_INVISIBLE_MINIMUM
unique_name = 1
+ gold_core_spawnable = 1
/mob/living/simple_animal/hostile/alien/drone
name = "alien drone"
@@ -130,6 +131,7 @@
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 10,
/obj/item/stack/sheet/animalhide/xeno = 2)
mob_size = MOB_SIZE_LARGE
+ gold_core_spawnable = 0
/obj/item/projectile/neurotox
name = "neurotoxin"
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index 651d97dcb56..6121354b335 100644
--- a/code/modules/mob/living/simple_animal/hostile/bear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bear.dm
@@ -14,7 +14,7 @@
taunt_chance = 25
turns_per_move = 5
see_in_dark = 6
- butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/bear = 5)
+ butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/bear = 5, /obj/item/clothing/head/bearpelt = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
@@ -33,6 +33,7 @@
maxbodytemp = 1500
faction = list("russian")
+ gold_core_spawnable = 1
//SPACE BEARS! SQUEEEEEEEE~ OW! FUCK! IT BIT MY HAND OFF!!
/mob/living/simple_animal/hostile/bear/Hudson
diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm
index 5c9265578f8..7e1e6677337 100644
--- a/code/modules/mob/living/simple_animal/hostile/bees.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bees.dm
@@ -21,6 +21,7 @@
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_SMALL
flying = 1
+ gold_core_spawnable = 1
//Spaceborn beings don't get hurt by space
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm
index dd872f00853..1fdef2619ff 100644
--- a/code/modules/mob/living/simple_animal/hostile/carp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/carp.dm
@@ -31,6 +31,7 @@
faction = list("carp")
flying = 1
+ gold_core_spawnable = 1
/mob/living/simple_animal/hostile/carp/Process_Spacemove(movement_dir = 0)
return 1 //No drifting in space for space carp! //original comments do not steal
@@ -45,6 +46,7 @@
icon_state = "holocarp"
icon_living = "holocarp"
maxbodytemp = INFINITY
+ gold_core_spawnable = 0
/mob/living/simple_animal/hostile/carp/holocarp/death()
..(1)
diff --git a/code/modules/mob/living/simple_animal/hostile/creature.dm b/code/modules/mob/living/simple_animal/hostile/creature.dm
index 173d8ff913f..66dc786c974 100644
--- a/code/modules/mob/living/simple_animal/hostile/creature.dm
+++ b/code/modules/mob/living/simple_animal/hostile/creature.dm
@@ -13,4 +13,4 @@
attack_sound = 'sound/weapons/bite.ogg'
faction = list("creature")
speak_emote = list("screams")
-
+ gold_core_spawnable = 1
diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm
index c74afd3be1b..a85c82a9cf9 100644
--- a/code/modules/mob/living/simple_animal/hostile/faithless.dm
+++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm
@@ -26,6 +26,7 @@
minbodytemp = 0
faction = list("faithless")
+ gold_core_spawnable = 1
/mob/living/simple_animal/hostile/faithless/Process_Spacemove(movement_dir = 0)
return 1
diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
index 9eb111c521e..f1ce0df13fc 100644
--- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
@@ -45,6 +45,7 @@
attacktext = "bites"
attack_sound = 'sound/weapons/bite.ogg'
unique_name = 1
+ gold_core_spawnable = 1
//nursemaids - these create webs and eggs
/mob/living/simple_animal/hostile/poison/giant_spider/nurse
@@ -154,7 +155,7 @@
busy = SPINNING_WEB
src.visible_message("\the [src] begins to secrete a sticky substance.")
stop_automated_movement = 1
- spawn(40)
+ if(do_after(src, 40, target = T))
if(busy == SPINNING_WEB && src.loc == T)
new /obj/effect/spider/stickyweb(T)
busy = 0
@@ -185,7 +186,7 @@
src.visible_message("\the [src] begins to secrete a sticky substance around \the [cocoon_target].")
stop_automated_movement = 1
walk(src,0)
- spawn(50)
+ if(do_after(src, 50, target = src))
if(busy == SPINNING_COCOON)
if(cocoon_target && istype(cocoon_target.loc, /turf) && get_dist(src,cocoon_target) <= 1)
var/obj/effect/spider/cocoon/C = new(cocoon_target.loc)
@@ -235,7 +236,7 @@
busy = LAYING_EGGS
src.visible_message("\the [src] begins to lay a cluster of eggs.")
stop_automated_movement = 1
- spawn(50)
+ if(do_after(src, 50, target = src.loc))
if(busy == LAYING_EGGS)
E = locate() in get_turf(src)
if(!E)
diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm
index 587e686d67d..43d9a143831 100644
--- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm
+++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm
@@ -1,13 +1,13 @@
#define EGG_INCUBATION_TIME 120
/mob/living/simple_animal/hostile/headcrab
- name = "Headslug"
+ name = "headslug"
desc = "Absolutely not de-beaked or harmless. Keep away from corpses."
icon_state = "headcrab"
icon_living = "headcrab"
icon_dead = "headcrab_dead"
- health = 20
- maxHealth = 20
+ health = 50
+ maxHealth = 50
melee_damage_lower = 5
melee_damage_upper = 5
attacktext = "chomps"
@@ -20,6 +20,7 @@
ventcrawler = 2
var/datum/mind/origin
var/egg_lain = 0
+ gold_core_spawnable = 1 //are you sure about this??
/mob/living/simple_animal/hostile/headcrab/proc/Infect(mob/living/carbon/victim)
var/obj/item/organ/internal/body_egg/changeling_egg/egg = new(victim)
@@ -30,7 +31,8 @@
egg.origin = mind
for(var/obj/item/organ/internal/I in src)
I.loc = egg
- visible_message("[src] lays an egg in a [victim].")
+ visible_message("[src] plants something in [victim]'s flesh!", \
+ "We inject our egg into [victim]'s body!")
egg_lain = 1
/mob/living/simple_animal/hostile/headcrab/AttackingTarget()
@@ -42,7 +44,7 @@
var/mob/living/carbon/C = target
if(C.stat == DEAD)
Infect(target)
- src << "With your egg laid you feel your death rapidly approaching, time to die..."
+ src << "With our egg laid, our death approaches rapidly..."
spawn(100)
death()
return
@@ -78,8 +80,12 @@
if(origin)
origin.transfer_to(M)
- if(origin.changeling)
- origin.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null)
+ if(!origin.changeling)
+ M.make_changeling()
+ if(origin.changeling.can_absorb_dna(M, owner))
+ origin.changeling.add_profile(owner, M)
+
+ origin.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null)
M.key = origin.key
owner.gib()
diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
index ce67552c952..ca434c387aa 100644
--- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
@@ -11,6 +11,7 @@
icon_dead = "basic"
health = 15
maxHealth = 15
+ healable = 0
melee_damage_lower = 2
melee_damage_upper = 3
attacktext = "claws"
@@ -21,6 +22,7 @@
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
speak_emote = list("states")
+ gold_core_spawnable = 1
/mob/living/simple_animal/hostile/hivebot/range
name = "hivebot"
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 1f24ed85e1c..12a73e8edc4 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -215,31 +215,29 @@
//////////////END HOSTILE MOB TARGETTING AND AGGRESSION////////////
/mob/living/simple_animal/hostile/death(gibbed)
- LoseAggro()
+ LoseTarget()
..(gibbed)
- walk(src, 0)
/mob/living/simple_animal/hostile/proc/OpenFire(the_target)
var/target = the_target
visible_message("[src] [ranged_message] at [target]!")
- var/tturf = get_turf(target)
if(rapid)
spawn(1)
- Shoot(tturf, src.loc, src)
+ Shoot(target, src.loc, src)
if(casingtype)
new casingtype(get_turf(src))
spawn(4)
- Shoot(tturf, src.loc, src)
+ Shoot(target, src.loc, src)
if(casingtype)
new casingtype(get_turf(src))
spawn(6)
- Shoot(tturf, src.loc, src)
+ Shoot(target, src.loc, src)
if(casingtype)
new casingtype(get_turf(src))
else
- Shoot(tturf, src.loc, src)
+ Shoot(target, src.loc, src)
if(casingtype)
new casingtype
ranged_cooldown = ranged_cooldown_cap
@@ -249,17 +247,16 @@
if(target == start)
return
- var/obj/item/projectile/A = new projectiletype(user:loc)
+ var/obj/item/projectile/A = new projectiletype(src.loc)
playsound(user, projectilesound, 100, 1)
if(!A) return
-
- if (!istype(target, /turf))
- qdel(A)
- return
A.current = target
A.firer = src
A.yo = target:y - start:y
A.xo = target:x - start:x
+ if(AIStatus == AI_OFF)//Don't want mindless mobs to have their movement screwed up firing in space
+ newtonian_move(get_dir(target, user))
+ A.original = target
A.fire()
return
diff --git a/code/modules/mob/living/simple_animal/hostile/killertomato.dm b/code/modules/mob/living/simple_animal/hostile/killertomato.dm
index 4677cb50cc9..5c032e21bc7 100644
--- a/code/modules/mob/living/simple_animal/hostile/killertomato.dm
+++ b/code/modules/mob/living/simple_animal/hostile/killertomato.dm
@@ -23,3 +23,4 @@
atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 150
maxbodytemp = 500
+ gold_core_spawnable = 1
diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm
index 4c99fd62ca2..877739d8bd8 100644
--- a/code/modules/mob/living/simple_animal/hostile/mimic.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm
@@ -1,7 +1,3 @@
-//
-// Abstract Class
-//
-
/mob/living/simple_animal/hostile/mimic
name = "crate"
desc = "A rectangular steel crate."
@@ -30,6 +26,7 @@
faction = list("mimic")
move_to_delay = 9
+ gold_core_spawnable = 1
/mob/living/simple_animal/hostile/mimic/death()
..(1)
@@ -37,19 +34,10 @@
ghostize()
qdel(src)
-
-
-//
-// Crate Mimic
-//
-
-
// Aggro when you try to open them. Will also pickup loot when spawns and drop it when dies.
/mob/living/simple_animal/hostile/mimic/crate
-
attacktext = "bites"
speak_emote = list("clatters")
-
stop_automated_movement = 1
wander = 0
var/attempt_open = 0
@@ -96,7 +84,6 @@
icon_state = initial(icon_state)
/mob/living/simple_animal/hostile/mimic/crate/death()
-
var/obj/structure/closet/crate/C = new(get_turf(src))
// Put loot in crate
for(var/obj/O in src)
@@ -113,21 +100,19 @@
C.visible_message("\The [src] knocks down \the [C]!", \
"\The [src] knocks you down!")
-//
-// Copy Mimic
-//
+
var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/cable, /obj/structure/window)
/mob/living/simple_animal/hostile/mimic/copy
-
health = 100
maxHealth = 100
var/mob/living/creator = null // the creator
var/destroy_objects = 0
var/knockdown_people = 0
+ gold_core_spawnable = 0
-/mob/living/simple_animal/hostile/mimic/copy/New(loc, var/obj/copy, var/mob/living/creator, var/destroy_original = 0)
+/mob/living/simple_animal/hostile/mimic/copy/New(loc, obj/copy, mob/living/creator, destroy_original = 0)
..(loc)
CopyObject(copy, creator, destroy_original)
@@ -137,13 +122,11 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca
death()
/mob/living/simple_animal/hostile/mimic/copy/death()
-
for(var/atom/movable/M in src)
M.loc = get_turf(src)
..()
/mob/living/simple_animal/hostile/mimic/copy/ListTargets()
- // Return a list of targets that isn't the creator
. = ..()
return . - creator
@@ -159,9 +142,7 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca
return 0
/mob/living/simple_animal/hostile/mimic/copy/proc/CopyObject(obj/O, mob/living/creator, destroy_original = 0)
-
if(destroy_original || CheckObject(O))
-
O.loc = src
name = O.name
desc = O.desc
@@ -169,7 +150,6 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca
icon_state = O.icon_state
icon_living = icon_state
overlays = O.overlays
-
if(istype(O, /obj/structure) || istype(O, /obj/machinery))
health = (anchored * 50) + 50
destroy_objects = 1
@@ -183,15 +163,13 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca
melee_damage_lower = 2 + I.force
melee_damage_upper = 2 + I.force
move_to_delay = 2 * I.w_class + 1
-
maxHealth = health
if(creator)
- src.creator = creator
+ creator = creator
faction += "\ref[creator]" // very unique
if(destroy_original)
qdel(O)
return 1
- return
/mob/living/simple_animal/hostile/mimic/copy/DestroySurroundings()
if(destroy_objects)
@@ -207,9 +185,7 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca
C.visible_message("\The [src] knocks down \the [C]!", \
"\The [src] knocks you down!")
-//
-// Machine Mimics (Made by Malf AI)
-//
+
/mob/living/simple_animal/hostile/mimic/copy/machine
speak = list("HUMANS ARE IMPERFECT!", "YOU SHALL BE ASSIMILATED!", "YOU ARE HARMING YOURSELF", "You have been deemed hazardous. Will you comply?", \
@@ -225,93 +201,57 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca
return 0
return ..()
-//
-//animated blasters, wands, etc
-//
+
/mob/living/simple_animal/hostile/mimic/copy/ranged
- name = "animated shooty gun"
- desc = "there's something fishy here."
- environment_smash = 0 //needed? seems weird for them to do so
- ranged = 1
- retreat_distance = 1 //just enough to shoot
- minimum_distance = 6
- projectiletype = /obj/item/projectile/magic/
- projectilesound = 'sound/items/bikehorn.ogg'
- casingtype = null
- emote_see = list("aims menacingly")
var/obj/item/weapon/gun/TrueGun = null
- var/obj/item/weapon/gun/magic/Zapstick = list()
- var/obj/item/weapon/gun/projectile/Pewgun = list()
- var/obj/item/weapon/gun/energy/Zapgun = list()
-
-/mob/living/simple_animal/hostile/mimic/copy/ranged/New(loc, var/obj/copy, var/mob/living/creator, var/destroy_original = 0)
- ..()
-
+ var/obj/item/weapon/gun/magic/Zapstick
+ var/obj/item/weapon/gun/projectile/Pewgun
+ var/obj/item/weapon/gun/energy/Zapgun
/mob/living/simple_animal/hostile/mimic/copy/ranged/CopyObject(obj/O, mob/living/creator, destroy_original = 0)
- if(destroy_original || CheckObject(O))
-
- O.loc = src
- name = O.name
- desc = O.desc
- icon = O.icon
- icon_state = O.icon_state
- icon_living = icon_state
-
- if(istype(O, /obj/item/weapon/gun)) //leaving for sanity i guess
- var/obj/item/weapon/gun/G = O
- health = 15 * G.w_class
- melee_damage_upper = G.force
- melee_damage_lower = G.force - max(0, (G.force / 2))
- move_to_delay = 2 * G.w_class + 1
- projectilesound = G.fire_sound
- TrueGun = G
-
- if(istype(G, /obj/item/weapon/gun/magic))
- Zapstick = G
- var/obj/item/ammo_casing/magic/Zapshot = new Zapstick.ammo_type //this is done because ammo_type.proj_type can't be directly checked
- projectiletype = Zapshot.projectile_type
- qdel(Zapshot) //is this needed? i dare not risk piles of nullspace bullets
-
- if(istype(G, /obj/item/weapon/gun/projectile))
- Pewgun = G
- var/obj/item/ammo_box/magazine/Pewmag = new Pewgun.mag_type //same problem, mag_type.ammo_type.proj_type can't be checked directly
- var/obj/item/ammo_casing/Pewshot = new Pewmag.ammo_type
- projectiletype = Pewshot.projectile_type
- casingtype = Pewmag.ammo_type
- qdel(Pewshot)
- qdel(Pewmag)
-
- if(istype(G, /obj/item/weapon/gun/energy))
- Zapgun = G
- var/selectfiresetting = Zapgun.select
- var/obj/item/ammo_casing/energy/Energyammotype = Zapgun.ammo_type[selectfiresetting]
- projectiletype = Energyammotype.projectile_type
-
- maxHealth = health
- if(creator)
- src.creator = creator
- faction += "\ref[creator]"
- if(destroy_original)
- qdel(O)
- return 1
- return
+ if(..())
+ emote_see = list("aims menacingly")
+ environment_smash = 0 //needed? seems weird for them to do so
+ ranged = 1
+ retreat_distance = 1 //just enough to shoot
+ minimum_distance = 6
+ var/obj/item/weapon/gun/G = O
+ melee_damage_upper = G.force
+ melee_damage_lower = G.force - max(0, (G.force / 2))
+ move_to_delay = 2 * G.w_class + 1
+ projectilesound = G.fire_sound
+ TrueGun = G
+ if(istype(G, /obj/item/weapon/gun/magic))
+ Zapstick = G
+ var/obj/item/ammo_casing/magic/M = Zapstick.ammo_type
+ projectiletype = initial(M.projectile_type)
+ if(istype(G, /obj/item/weapon/gun/projectile))
+ Pewgun = G
+ var/obj/item/ammo_box/magazine/M = Pewgun.mag_type
+ var/obj/item/ammo_casing/A = initial(M.ammo_type)
+ projectiletype = initial(A.projectile_type)
+ casingtype = initial(M.ammo_type)
+ if(istype(G, /obj/item/weapon/gun/energy))
+ Zapgun = G
+ var/selectfiresetting = Zapgun.select
+ var/obj/item/ammo_casing/energy/E = Zapgun.ammo_type[selectfiresetting]
+ projectiletype = initial(E.projectile_type)
/mob/living/simple_animal/hostile/mimic/copy/ranged/OpenFire(the_target)
if(Zapgun)
- if(Zapgun.power_supply) //sanity
+ if(Zapgun.power_supply)
var/obj/item/ammo_casing/energy/shot = Zapgun.ammo_type[Zapgun.select]
- if(Zapgun.power_supply.charge >= shot.e_cost) //if she can zap
+ if(Zapgun.power_supply.charge >= shot.e_cost)
Zapgun.power_supply.use(shot.e_cost)
Zapgun.update_icon()
- ..() //zap 'em
- if(Zapstick)
+ ..()
+ else if(Zapstick)
if(Zapstick.charges)
Zapstick.charges--
Zapstick.update_icon()
..()
- if(Pewgun)
+ else if(Pewgun)
if(Pewgun.chambered)
if(Pewgun.chambered.BB)
qdel(Pewgun.chambered.BB)
@@ -320,7 +260,7 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca
..()
else
visible_message("The [src] clears a jam!")
- Pewgun.chambered.loc = src.loc //rip revolver immersions, blame shotgun snowflake procs
+ Pewgun.chambered.loc = loc //rip revolver immersions, blame shotgun snowflake procs
Pewgun.chambered = null
if(Pewgun.magazine && Pewgun.magazine.stored_ammo.len)
Pewgun.chambered = Pewgun.magazine.get_round(0)
@@ -330,11 +270,10 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca
Pewgun.chambered = Pewgun.magazine.get_round(0)
Pewgun.chambered.loc = Pewgun
visible_message("The [src] cocks itself!")
-
- else //if somehow the mimic has no weapon
- src.ranged = 0 //BANZAIIII
- src.retreat_distance = 0
- src.minimum_distance = 1
- src.icon_state = TrueGun.icon_state
- src.icon_living = TrueGun.icon_state
- return
\ No newline at end of file
+ else
+ ranged = 0 //BANZAIIII
+ retreat_distance = 0
+ minimum_distance = 1
+ return
+ icon_state = TrueGun.icon_state
+ icon_living = TrueGun.icon_state
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
index 7e01e2942ef..0be7a54e261 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
@@ -17,7 +17,8 @@
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
- icon_state = icon_aggro
+ if(vision_range != aggro_vision_range)
+ icon_state = icon_aggro
/mob/living/simple_animal/hostile/asteroid/LoseAggro()
..()
@@ -42,7 +43,7 @@
..()
/mob/living/simple_animal/hostile/asteroid/death(gibbed)
- feedback_add_details("mobs_killed_mining","[src.name]")
+ feedback_add_details("mobs_killed_mining","[src.type]")
..(gibbed)
/mob/living/simple_animal/hostile/asteroid/basilisk
@@ -96,11 +97,11 @@
/mob/living/simple_animal/hostile/asteroid/basilisk/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
gib()
- if(2.0)
+ if(2)
adjustBruteLoss(140)
- if(3.0)
+ if(3)
adjustBruteLoss(110)
/mob/living/simple_animal/hostile/asteroid/basilisk/death(gibbed)
@@ -251,25 +252,42 @@
OpenFire()
/mob/living/simple_animal/hostile/asteroid/hivelord/death(gibbed)
- new /obj/item/asteroid/hivelord_core(src.loc)
+ new /obj/item/organ/internal/hivelord_core(src.loc)
mouse_opacity = 1
..(gibbed)
-/obj/item/asteroid/hivelord_core
+/obj/item/organ/internal/hivelord_core
name = "hivelord remains"
desc = "All that remains of a hivelord, it seems to be what allows it to break pieces of itself off without being hurt... its healing properties will soon become inert if not used quickly."
- icon = 'icons/obj/food/food.dmi'
- icon_state = "boiledrorocore"
+ icon_state = "roro core 2"
+ flags = NOBLUDGEON
+ slot = "hivecore"
+ force = 0
var/inert = 0
-/obj/item/asteroid/hivelord_core/New()
- spawn(1200)
- inert = 1
- desc = "The remains of a hivelord that have become useless, having been left alone too long after being harvested."
+/obj/item/organ/internal/hivelord_core/New()
+ ..()
+ spawn(2400)
+ if(!owner)
+ inert = 1
+ desc = "The remains of a hivelord that have become useless, having been left alone too long after being harvested."
-/obj/item/asteroid/hivelord_core/attack(mob/living/M, mob/living/user)
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
+/obj/item/organ/internal/hivelord_core/on_life()
+ ..()
+
+ owner.adjustBruteLoss(-1)
+ owner.adjustFireLoss(-1)
+ owner.adjustOxyLoss(-2)
+ if(ishuman(owner))
+ var/mob/living/carbon/human/H = owner
+ var/datum/reagent/blood/B = locate() in H.vessel.reagent_list //Grab some blood
+ var/blood_volume = round(H.vessel.get_reagent_amount("blood"))
+ if(B && blood_volume < 560 && blood_volume)
+ B.volume += 2 // Fast blood regen
+
+/obj/item/organ/internal/hivelord_core/afterattack(atom/target, mob/user, proximity_flag)
+ if(proximity_flag && ishuman(target))
+ var/mob/living/carbon/human/H = target
if(inert)
user << "[src] have become inert, its healing properties are no more."
return
@@ -285,6 +303,9 @@
qdel(src)
..()
+/obj/item/organ/internal/hivelord_core/prepare_eat()
+ return null
+
/mob/living/simple_animal/hostile/asteroid/hivelordbrood
name = "hivelord brood"
desc = "A fragment of the original Hivelord, rallying behind its original. One isn't much of a threat, but..."
@@ -424,10 +445,10 @@
/obj/effect/goliath_tentacle/proc/Trip()
for(var/mob/living/M in src.loc)
+ visible_message("The [src.name] grabs hold of [M.name]!")
M.Stun(5)
M.adjustBruteLoss(rand(10,15))
latched = 1
- visible_message("The [src.name] grabs hold of [M.name]!")
if(!latched)
qdel(src)
else
@@ -485,3 +506,131 @@
adjustBruteLoss(2)
else if(bodytemperature > maxbodytemp)
adjustBruteLoss(20)
+
+
+/mob/living/simple_animal/hostile/asteroid/fugu
+ name = "wumborian fugu"
+ desc = "The wumborian fugu rapidly increases its body mass in order to ward off its prey. Great care should be taken to avoid it while it's in this state as it is nearly invincible, but it cannot maintain its form forever."
+ icon = 'icons/mob/animal.dmi'
+ icon_state = "Fugu"
+ icon_living = "Fugu"
+ icon_aggro = "Fugu"
+ icon_dead = "Fugu_dead"
+ icon_gib = "syndicate_gib"
+ attack_sound = 'sound/weapons/punch4.ogg'
+ mouse_opacity = 2
+ move_to_delay = 5
+ friendly = "floats near"
+ speak_emote = list("puffs")
+ vision_range = 5
+ speed = 0
+ maxHealth = 50
+ health = 50
+ harm_intent_damage = 5
+ melee_damage_lower = 0
+ melee_damage_upper = 0
+ attacktext = "chomps"
+ attack_sound = 'sound/weapons/punch1.ogg'
+ throw_message = "is avoided by the"
+ aggro_vision_range = 9
+ idle_vision_range = 5
+ mob_size = MOB_SIZE_SMALL
+ environment_smash = 0
+ var/wumbo = 0
+ var/inflate_cooldown = 0
+
+/mob/living/simple_animal/hostile/asteroid/fugu/Life()
+ if(!wumbo)
+ inflate_cooldown = max((inflate_cooldown - 1), 0)
+ if(target && AIStatus == AI_ON)
+ Inflate()
+ ..()
+
+/mob/living/simple_animal/hostile/asteroid/fugu/adjustBruteLoss(var/damage)
+ if(wumbo)
+ return
+ ..()
+
+/mob/living/simple_animal/hostile/asteroid/fugu/Aggro()
+ ..()
+ Inflate()
+
+/mob/living/simple_animal/hostile/asteroid/fugu/verb/Inflate()
+ set name = "Inflate"
+ set category = "Fugu"
+ set desc = "Temporarily increases your size, and makes you significantly more dangerous and tough."
+ if(wumbo)
+ src << "You're already inflated."
+ return
+ if(inflate_cooldown)
+ src << "We need time to gather our strength."
+ return
+ if(buffed)
+ src << "Something is interfering with our growth."
+ return
+ wumbo = 1
+ icon_state = "Fugu_big"
+ melee_damage_lower = 15
+ melee_damage_upper = 20
+ harm_intent_damage = 0
+ throw_message = "is absorbed by the girth of the"
+ retreat_distance = null
+ minimum_distance = 1
+ move_to_delay = 6
+ transform *= 2
+ environment_smash = 2
+ mob_size = MOB_SIZE_LARGE
+ speed = 1
+ spawn(100)
+ Deflate()
+
+/mob/living/simple_animal/hostile/asteroid/fugu/proc/Deflate()
+ if(wumbo)
+ walk(src, 0)
+ wumbo = 0
+ icon_state = "Fugu"
+ melee_damage_lower = 0
+ melee_damage_upper = 0
+ harm_intent_damage = 5
+ throw_message = "is avoided by the"
+ retreat_distance = 9
+ minimum_distance = 9
+ move_to_delay = 2
+ transform /= 2
+ inflate_cooldown = 4
+ environment_smash = 0
+ mob_size = MOB_SIZE_SMALL
+ speed = 0
+
+/mob/living/simple_animal/hostile/asteroid/fugu/death(gibbed)
+ Deflate()
+ var/obj/item/asteroid/fugu_gland/F = new /obj/item/asteroid/fugu_gland(src.loc)
+ F.layer = 4.1
+ ..(gibbed)
+
+/obj/item/asteroid/fugu_gland
+ name = "wumborian fugu gland"
+ desc = "The key to the wumborian fugu's ability to increase its mass arbitrarily, this disgusting remnant can apply the same effect to other creatures, giving them great strength."
+ icon = 'icons/obj/surgery.dmi'
+ icon_state = "fugu_gland"
+ flags = NOBLUDGEON
+ w_class = 3
+ layer = 4
+ origin_tech = "biotech=6"
+ var/list/banned_mobs()
+
+/obj/item/asteroid/fugu_gland/afterattack(atom/target, mob/user, proximity_flag)
+ if(proximity_flag && istype(target, /mob/living/simple_animal))
+ var/mob/living/simple_animal/A = target
+ if(A.buffed || (A.type in banned_mobs) || A.stat)
+ user << "Something's interfering with the [src]'s effects. It's no use."
+ return
+ A.buffed++
+ A.maxHealth *= 1.5
+ A.health = min(A.maxHealth,A.health*1.5)
+ A.melee_damage_lower = max((A.melee_damage_lower * 2), 10)
+ A.melee_damage_upper = max((A.melee_damage_upper * 2), 10)
+ A.transform *= 2
+ A.environment_smash += 2
+ user << "You increase the size of [A], giving it a surge of strength!"
+ qdel(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm
index 8ff2d451a10..d5b8135442b 100644
--- a/code/modules/mob/living/simple_animal/hostile/statue.dm
+++ b/code/modules/mob/living/simple_animal/hostile/statue.dm
@@ -16,6 +16,7 @@
speed = -1
maxHealth = 50000
health = 50000
+ healable = 0
harm_intent_damage = 70
melee_damage_lower = 68
@@ -44,6 +45,7 @@
var/cannot_be_seen = 1
var/mob/living/creator = null
+ gold_core_spawnable = 1
// No movement while seen code.
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index 38987cf6d27..f04ded89b18 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -132,8 +132,9 @@
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
mob_size = MOB_SIZE_TINY
- flying
+ flying = 1
speak_emote = list("states")
+ gold_core_spawnable = 1
/mob/living/simple_animal/hostile/viscerator/death(gibbed)
..(gibbed)
diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm
index 0acc9aad7ef..872d9ec94d3 100644
--- a/code/modules/mob/living/simple_animal/hostile/tree.dm
+++ b/code/modules/mob/living/simple_animal/hostile/tree.dm
@@ -27,12 +27,26 @@
emote_taunt = list("growls")
taunt_chance = 20
- //Space carp aren't affected by atmos.
- atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
+ atmos_requirements = list("min_oxy" = 2, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
+ unsuitable_atmos_damage = 5
minbodytemp = 0
+ maxbodytemp = 1200
faction = list("hostile")
var/drop_type = /obj/item/stack/sheet/mineral/wood
+ gold_core_spawnable = 1
+
+/mob/living/simple_animal/hostile/tree/Life()
+ ..()
+ if(istype(src.loc, /turf/simulated))
+ var/turf/simulated/T = src.loc
+ if(T.air)
+ var/co2 = T.air.carbon_dioxide
+ if(co2 > 0)
+ if(prob(25))
+ var/amt = min(co2, 9)
+ T.air.carbon_dioxide -= amt
+ T.atmos_spawn_air(SPAWN_OXYGEN, amt)
/mob/living/simple_animal/hostile/tree/AttackingTarget()
..()
diff --git a/code/modules/mob/living/simple_animal/morph/morph.dm b/code/modules/mob/living/simple_animal/morph/morph.dm
index e543a67193c..c815f567578 100644
--- a/code/modules/mob/living/simple_animal/morph/morph.dm
+++ b/code/modules/mob/living/simple_animal/morph/morph.dm
@@ -1,9 +1,9 @@
#define MORPH_COOLDOWN 50
/mob/living/simple_animal/hostile/morph
- name = "Morph"
- real_name = "Morph"
- desc = "some amorphous blob"
+ name = "morph"
+ real_name = "morph"
+ desc = "A revolting, pulsating pile of flesh."
speak_emote = list("gurgles")
emote_hear = list("gurgles")
icon = 'icons/mob/animal.dmi'
@@ -20,6 +20,7 @@
minbodytemp = 0
maxHealth = 150
health = 150
+ healable = 0
environment_smash = 1
melee_damage_lower = 20
melee_damage_upper = 20
@@ -27,16 +28,25 @@
see_invisible = SEE_INVISIBLE_MINIMUM
idle_vision_range = 1 // Only attack when target is close
wander = 0
+ attacktext = "glomps"
+ attack_sound = 'sound/effects/blobattack.ogg'
var/morphed = 0
var/atom/movable/form = null
var/morph_time = 0
+ var/playstyle_string = "You are a morph, an abomination of science created primarily with changeling cells. \
+ You may take the form of anything nearby by middle-clicking it. This process will alert any nearby \
+ observers, and can only be performed once every five seconds. While morphed, you move faster, but do \
+ less damage. In addition, anyone within three tiles will note an uncanny wrongness if examining you. \
+ You can attack any item or dead creature to consume it - creatures will fully restore your health. \
+ Finally, you can restore yourself to your original form while morphed by middle-clicking yourself."
+
/mob/living/simple_animal/hostile/morph/examine(mob/user)
if(morphed)
form.examine(user) // Refactor examine to return desc so it's static? Not sure if worth it
if(get_dist(user,src)<=3)
- user << "Looks odd!"
+ user << "It doesn't look quite right..."
else
..()
return
@@ -56,6 +66,7 @@
if(istype(A) && allowed(A))
assume(A)
else
+ src << "Your chameleon skin is still repairing itself!"
..()
/mob/living/simple_animal/hostile/morph/proc/assume(atom/movable/target)
@@ -71,11 +82,15 @@
else
overlays = target.overlays.Copy()
+ visible_message("[src] suddenly twists and changes shape, becoming a copy of [target]!", \
+ "You twist your body and assume the form of [target].")
+
name = target.name
icon = target.icon
icon_state = target.icon_state
overlays = target.overlays
+
//Morphed is weaker
melee_damage_lower = 5
melee_damage_upper = 5
@@ -92,6 +107,8 @@
//anim(loc,src,'icons/mob/mob.dmi',,"morph",,src.dir)
+ visible_message("[src] suddenly collapses in on itself, dissolving into a pile of green flesh!", \
+ "You reform to your normal body.")
name = initial(name)
icon = initial(icon)
icon_state = initial(icon_state)
@@ -107,7 +124,8 @@
/mob/living/simple_animal/hostile/morph/death()
if(morphed)
- visible_message("The [src] dissolves!")
+ visible_message("[src] twists and dissolves into a pile of green flesh!", \
+ "Your skin ruptures! Your flesh breaks apart! No disguise can ward off de--")
restore()
//Dump eaten stuff
@@ -147,7 +165,7 @@
var/mob/living/L = target
if(L.stat == DEAD)
if(do_after(src, 30, target = L))
- visible_message("[src] swallows the [target] whole!")
+ visible_message("[src] swallows [target] whole!")
L.loc = src
adjustBruteLoss(-50)
return
@@ -155,7 +173,7 @@
var/obj/item/I = target
if(!I.anchored)
if(do_after(src,20, target = I))
- visible_message("[src] swallows the [target] whole!")
+ visible_message("[src] swallows [target] whole!")
I.loc = src
return
target.attack_animal(src)
@@ -197,15 +215,10 @@
player_mind.assigned_role = "Morph"
player_mind.special_role = "Morph"
ticker.mode.traitors |= player_mind
- var/info = {"You are a Morph, a shapeshifting alien creature.
- You can assume the shape of anything in sight by Shift-Clicking it.
- You can only transform every 5 seconds.
- To return to your basic form Shift-Click on yourself.
- Base form is slow but strong, you're much weaker and faster when disguised.
- You can eat items and corpses by clicking on them,eating corpses will heal you."}
- S << info
- message_admins("[key_of_morph] has been made into Morph by an event.")
- log_game("[key_of_morph] was spawned as a Morph by an event.")
+ S << S.playstyle_string
+ S << 'sound/magic/Mutate.ogg'
+ message_admins("[key_of_morph] has been made into morph by an event.")
+ log_game("[key_of_morph] was spawned as a morph by an event.")
return 1
/datum/round_event/morph/start()
@@ -213,11 +226,11 @@
/datum/round_event/morph/proc/find_morph()
- message_admins("Attempted to spawn a Morph but there was no players available. Will try again momentarily.")
+ message_admins("Attempted to spawn a morph but there was no players available. Will try again momentarily.")
spawn(50)
if(get_morph(1))
- message_admins("Situation has been resolved, [key_of_morph] has been spawned as a Morph.")
- log_game("[key_of_morph] was spawned as a Morph by an event.")
+ message_admins("Situation has been resolved, [key_of_morph] has been spawned as a morph.")
+ log_game("[key_of_morph] was spawned as a morph by an event.")
return 0
- message_admins("Unfortunately, no candidates were available for becoming a Morph. Shutting down.")
+ message_admins("Unfortunately, no candidates were available for becoming a morph. Shutting down.")
return kill()
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index 41c36669023..f600071a076 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -56,6 +56,7 @@
friendly = "grooms"
mob_size = MOB_SIZE_SMALL
flying = 1
+ gold_core_spawnable = 2
var/parrot_damage_upper = 10
var/parrot_state = PARROT_WANDER //Hunt for a perch when created
@@ -809,6 +810,7 @@
name = "Poly"
desc = "Poly the Parrot. An expert on quantum cracker theory."
speak = list("Poly wanna cracker!", ":e Check the singlo, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN HARDSUITS?",":e OH GOD ITS FREE CALL THE SHUTTLE")
+ gold_core_spawnable = 0
/mob/living/simple_animal/parrot/Poly/New()
ears = new /obj/item/device/radio/headset/headset_eng(src)
diff --git a/code/modules/mob/living/simple_animal/revenant/revenant.dm b/code/modules/mob/living/simple_animal/revenant/revenant.dm
index cb99c234248..c90283d76ba 100644
--- a/code/modules/mob/living/simple_animal/revenant/revenant.dm
+++ b/code/modules/mob/living/simple_animal/revenant/revenant.dm
@@ -3,57 +3,65 @@
//Don't hear deadchat and are NOT normal ghosts
//Admin-spawn or random event
+#define INVISIBILITY_REVENANT 30
+
/mob/living/simple_animal/revenant
name = "revenant"
desc = "A malevolent spirit."
icon = 'icons/mob/mob.dmi'
icon_state = "revenant_idle"
incorporeal_move = 3
- invisibility = INVISIBILITY_OBSERVER
+ invisibility = INVISIBILITY_REVENANT
health = 25
maxHealth = 25
- see_in_dark = 255
- see_invisible = SEE_INVISIBLE_OBSERVER
+ healable = 0
+ see_invisible = INVISIBILITY_REVENANT
languages = ALL
response_help = "passes through"
response_disarm = "swings at"
- response_harm = "punches"
+ response_harm = "punches through"
+ unsuitable_atmos_damage = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = INFINITY
- harm_intent_damage = 5
- speak_emote = list("hisses", "spits", "growls")
+ harm_intent_damage = 0
friendly = "touches"
status_flags = 0
wander = 0
density = 0
+ flying = 1
+ anchored = 1
- var/essence = 25 //The resource of revenants. Max health is equal to twice this amount
+ var/essence = 25 //The resource of revenants. Max health is equal to three times this amount
var/essence_regen_cap = 25 //The regeneration cap of essence (go figure); regenerates every Life() tick up to this amount.
- var/essence_regen = 1 //If the revenant regenerates essence or not; 1 for yes, 0 for no
+ var/essence_regenerating = 1 //If the revenant regenerates essence or not; 1 for yes, 0 for no
+ var/essence_regen_amount = 2 //How much essence regenerates
var/essence_min = 1 //The minimum amount of essence a revenant can have; by default, it never drops below one
- var/strikes = 0 //How many times a revenant can die before dying for good
+ var/essence_accumulated = 0 //How much essence the revenant has stolen
var/revealed = 0 //If the revenant can take damage from normal sources.
var/inhibited = 0 //If the revenant's abilities are blocked by a chaplain's power.
+ var/essence_drained = 0 //How much essence the revenant has drained.
+ var/draining = 0 //If the revenant is draining someone.
+ var/list/drained_mobs = list() //Cannot harvest the same mob twice
/mob/living/simple_animal/revenant/Life()
..()
if(essence < essence_min)
essence = essence_min
- if(strikes > 0)
- strikes--
- src << "Your essence has dropped below critical levels. You barely manage to save yourself - [strikes ? "you can't keep this up!" : "next time, it's death."]"
- else if(strikes <= 0)
- death()
- maxHealth = essence * 2
+ if(essence_regenerating && !inhibited && essence < essence_regen_cap) //While inhibited, essence will not regenerate
+ essence += essence_regen_amount
+ if(essence > essence_regen_cap)
+ essence = essence_regen_cap
+ maxHealth = essence * 3
if(!revealed)
health = maxHealth //Heals to full when not revealed
- if(essence_regen && !inhibited && essence < essence_regen_cap) //While inhibited, essence will not regenerate
- essence++
/mob/living/simple_animal/revenant/ex_act(severity, target)
return 1 //Immune to the effects of explosions.
+/mob/living/simple_animal/revenant/blob_act()
+ return //blah blah blobs aren't in tune with the spirit world, or something.
+
/mob/living/simple_animal/revenant/ClickOn(atom/A, params) //Copypaste from ghost code - revenants can't interact with the world directly.
if(client.buildmode)
build_click(src, client.buildmode, params, A)
@@ -76,14 +84,85 @@
if(world.time <= next_move)
return
A.attack_ghost(src)
+ if(ishuman(A) && in_range(src, A))
+ Harvest(A)
+
+
+/mob/living/simple_animal/revenant/proc/Harvest(mob/living/carbon/human/target)
+ if(!castcheck(0))
+ return
+ if(draining)
+ src << "You are already siphoning the essence of a soul!"
+ return
+ if(target in drained_mobs)
+ src << "[target]'s soul is dead and empty."
+ return
+ if(!target.stat)
+ src << "This being's soul is too strong to harvest."
+ if(prob(10))
+ target << "You feel as if you are being watched."
+ return
+ draining = 1
+ essence_drained = 2
+ src << "You search for the soul of [target]."
+ if(do_after(src, 10, 3, 0, target)) //did they get deleted in that second?
+ if(target.ckey)
+ src << "Their soul burns with intelligence."
+ essence_drained += 2
+ if(target.stat != DEAD)
+ src << "Their soul blazes with life!"
+ essence_drained += 2
+ else
+ src << "Their soul is weak and faltering."
+ if(do_after(src, 20, 6, 0, target)) //did they get deleted NOW?
+ switch(essence_drained)
+ if(1 to 2)
+ src << "[target] will not yield much essence. Still, every bit counts."
+ if(3 to 4)
+ src << "[target] will yield an average amount of essence."
+ if(5 to INFINITY)
+ src << "Such a feast! [target] will yield much essence to you."
+ if(do_after(src, 30, 9, 0, target)) //how about now
+ if(!target.stat)
+ src << "They are now powerful enough to fight off your draining."
+ target << "You feel something tugging across your body before subsiding."
+ draining = 0
+ return //hey, wait a minute...
+ src << "You begin siphoning essence from [target]'s soul."
+ if(target.stat != DEAD)
+ target << "You feel a horribly unpleasant draining sensation as your grip on life weakens..."
+ icon_state = "revenant_draining"
+ reveal(65)
+ stun(65)
+ target.visible_message("[target] suddenly rises slightly into the air, their skin turning an ashy gray.")
+ target.Beam(src,icon_state="drain_life",icon='icons/effects/effects.dmi',time=60)
+ if(target) //As one cannot prove the existance of ghosts, ghosts cannot prove the existance of the target they were draining.
+ change_essence_amount(essence_drained * 5, 0, target)
+ src << "[target]'s soul has been considerably weakened and will yield no more essence for the time being."
+ target.visible_message("[target] slumps onto the ground.", \
+ "Violets lights, dancing in your vision, getting clo--")
+ drained_mobs.Add(target)
+ target.death(0)
+ icon_state = "revenant_idle"
+ else
+ src << "You are not close enough to siphon [target]'s soul. The link has been broken."
+ draining = 0
+ return
+ draining = 0
+ return
+
/mob/living/simple_animal/revenant/say(message)
- return 0 //Revenants cannot speak out loud.
+ for(var/mob/M in mob_list)
+ if(istype(M, /mob/living/simple_animal/revenant) || M.stat == DEAD)
+ M << "REVENANT: [src] says, \"[message]\"" //Can commune with the dead
+ return
/mob/living/simple_animal/revenant/Stat()
..()
if(statpanel("Status"))
stat(null, "Current essence: [essence]E")
+ stat(null, "Stolen essence: [essence_accumulated]E")
/mob/living/simple_animal/revenant/New()
..()
@@ -101,35 +180,24 @@
src << "You do not remember anything of your past lives, nor will you remember anything about this one after your death."
src << "Be sure to read the wiki page at https://tgstation13.org/wiki/Revenant to learn more."
var/datum/objective/revenant/objective = new
- objective.owner = src
+ objective.owner = src.mind
src.mind.objectives += objective
src << "Objective #1: [objective.explanation_text]"
var/datum/objective/revenantFluff/objective2 = new
- objective2.owner = src
+ objective2.owner = src.mind
src.mind.objectives += objective2
src << "Objective #2: [objective2.explanation_text]"
ticker.mode.traitors |= src.mind //Necessary for announcing
- if(!src.giveSpells())
- message_admins("Revenant was created but has no mind. Trying again in five seconds.")
- spawn(50)
- if(!src.giveSpells())
- message_admins("Revenant still has no mind. Deleting...")
- qdel(src)
-
-/mob/living/simple_animal/revenant/proc/giveSpells()
- if(src.mind)
- src.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/revenant_harvest
- src.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/revenant_transmit
- src.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/revenant_light
- src.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/revenantDefile
- return 1
- return 0
+ AddSpell(new /obj/effect/proc_holder/spell/targeted/revenant_transmit(null))
+ AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant_light(null))
+ AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant_defile(null))
+ AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant_malf(null))
/mob/living/simple_animal/revenant/death()
- if(strikes)
- return 0 //Impossible to die with strikes still active
+ if(!revealed) //Revenants cannot die if they aren't revealed
+ return 0
..(1)
- src << "NO! No... it's too late, you can feel yourself fading..."
+ src << "NO! No... it's too late, you can feel yourself fading..."
notransform = 1
revealed = 1
invisibility = 0
@@ -139,75 +207,86 @@
for(var/i = alpha, i > 0, i -= 10)
sleep(0.1)
alpha = i
- visible_message("[src]'s body breaks apart into blue dust.")
- new /obj/item/weapon/ectoplasm/revenant(get_turf(src))
+ visible_message("[src]'s body breaks apart into a fine pile of blue dust.")
+ var/obj/item/weapon/ectoplasm/revenant/R = new (get_turf(src))
+ R.client_to_revive = src.client //If the essence reforms, the old revenant is put back in the body
ghostize()
qdel(src)
return
/mob/living/simple_animal/revenant/attackby(obj/item/W, mob/living/user, params)
- ..()
if(istype(W, /obj/item/weapon/nullrod))
visible_message("[src] violently flinches!", \
- "The null rod invokes agony in you! You feel your essence draining away!")
+ "As the null rod passes through you, you feel your essence draining away!")
essence -= 25 //hella effective
inhibited = 1
spawn(30)
inhibited = 0
-
+ ..()
/mob/living/simple_animal/revenant/proc/castcheck(essence_cost)
- var/mob/living/simple_animal/revenant/user = usr
- if(!istype(user) || !user)
+ if(!src)
return
- var/turf/T = get_turf(usr)
+ var/turf/T = get_turf(src)
if(istype(T, /turf/simulated/wall))
- user << "You cannot use abilities from inside of a wall."
+ src << "You cannot use abilities from inside of a wall."
return 0
- if(!user.change_essence_amount(essence_cost, 1))
- user << "You lack the essence to use that ability."
+ if(src.inhibited)
+ src << "Your powers have been suppressed by nulling energy!"
return 0
- if(user.inhibited)
- user << "Your powers have been suppressed by holy energies!"
+ if(!src.change_essence_amount(essence_cost, 1))
+ src << "You lack the essence to use that ability."
return 0
return 1
/mob/living/simple_animal/revenant/proc/change_essence_amount(essence_amt, silent = 0, source = null)
- var/mob/living/simple_animal/revenant/user = usr
- if(!istype(usr) || !usr)
+ if(!src)
return
- if(user.essence + essence_amt <= 0)
+ if(essence + essence_amt <= 0)
return
- user.essence += essence_amt
- user.essence = Clamp(user.essence, 0, INFINITY)
+ essence += essence_amt
+ essence = max(0, essence)
+ if(essence_amt > 0)
+ essence_accumulated += essence_amt
+ essence_accumulated = max(0, essence_accumulated)
if(!silent)
if(essence_amt > 0)
- user << "Gained [essence_amt]E from [source]."
+ src << "Gained [essence_amt]E from [source]."
else
- user << "Lost [essence_amt]E from [source]."
+ src << "Lost [essence_amt]E from [source]."
return 1
-/mob/living/simple_animal/revenant/proc/reveal(time, stun)
- var/mob/living/simple_animal/revenant/R = usr
- if(!istype(usr) || !usr)
+/mob/living/simple_animal/revenant/proc/reveal(time)
+ if(!src)
return
- R.revealed = 1
- R.invisibility = 0
- if(stun)
- R.notransform = 1
- R << "You have been revealed [stun ? "and cannot move" : ""]."
+ if(time <= 0)
+ return
+ revealed = 1
+ invisibility = 0
+ src << "You have been revealed."
spawn(time)
- R.revealed = 0
- R.invisibility = INVISIBILITY_OBSERVER
- if(stun)
- R.notransform = 0
- R << "You are once more concealed [stun ? "and can move again" : ""]."
+ revealed = 0
+ invisibility = INVISIBILITY_REVENANT
+ src << "You are once more concealed."
+
+/mob/living/simple_animal/revenant/proc/stun(time)
+ if(!src)
+ return
+ if(time <= 0)
+ return
+ notransform = 1
+ src << "You cannot move!"
+ spawn(time)
+ notransform = 0
+ src << "You can move again!"
+
+
/datum/objective/revenant
dangerrating = 10
@@ -215,17 +294,17 @@
/datum/objective/revenant/New()
targetAmount = rand(100,200)
- explanation_text = "Absorb [targetAmount] points of essence."
+ explanation_text = "Absorb [targetAmount] points of essence from humans."
..()
/datum/objective/revenant/check_completion()
- if(!istype(owner.current, /mob/living/simple_animal/revenant) || !owner.current)
+ if(!istype(owner.current, /mob/living/simple_animal/revenant))
return 0
var/mob/living/simple_animal/revenant/R = owner.current
if(!R || R.stat == DEAD)
return 0
- var/essenceAccumulated = R.essence
- if(essenceAccumulated < targetAmount)
+ var/essence_stolen = R.essence_accumulated
+ if(essence_stolen < targetAmount)
return 0
return 1
@@ -253,26 +332,22 @@
icon_state = "revenantEctoplasm"
w_class = 2
var/reforming = 0
- var/reformed = 0
+ var/inert = 0
+ var/client/client_to_revive
/obj/item/weapon/ectoplasm/revenant/New()
..()
reforming = 1
- spawn(1800) //3 minutes
+ spawn(600) //1 minute
if(src && reforming)
return reform()
if(src && !reforming)
+ reforming = 1
visible_message("[src] settles down and seems lifeless.")
return
-/obj/item/weapon/ectoplasm/revenant/attack_hand(mob/user)
- if(reformed)
- user << "[src] keeps slipping out of your hands, you can't get a hold on it!"
- return
- ..()
-
/obj/item/weapon/ectoplasm/revenant/attack_self(mob/user)
- if(!reforming)
+ if(!reforming || inert)
return ..()
user.visible_message("[user] scatters [src] in all directions.", \
"You scatter [src] across the area. The particles slowly fade away.")
@@ -281,6 +356,8 @@
/obj/item/weapon/ectoplasm/revenant/throw_impact(atom/hit_atom)
..()
+ if(inert)
+ return
visible_message("[src] breaks into particles upon impact, which fade away to nothingness.")
qdel(src)
@@ -294,20 +371,29 @@
/obj/item/weapon/ectoplasm/revenant/proc/reform()
if(!reforming || !src)
return
- message_admins("Revenant ectoplasm was left undestroyed for 3 minutes and has reformed into a new revenant.")
+ var/key_of_revenant
+ message_admins("Revenant ectoplasm was left undestroyed for 1 minute and has reformed into a new revenant.")
loc = get_turf(src) //In case it's in a backpack or someone's hand
visible_message("[src] suddenly rises into the air before fading away.")
var/mob/living/simple_animal/revenant/R = new(get_turf(src))
- qdel(src)
- var/list/candidates = get_candidates(BE_REVENANT)
- if(!candidates.len)
- message_admins("No candidates were found for the new revenant. Oh well!")
- return 0
- var/client/C = pick(candidates)
- var/key_of_revenant = C.key
- if(!key_of_revenant)
- message_admins("No ckey was found for the new revenant. Oh well!")
- return 0
+ if(client_to_revive)
+ for(var/mob/M in mob_list)
+ if(M.client == client_to_revive && M.stat == DEAD) //Only recreates the mob if the mob the client is in is dead
+ message_admins("[R.client] was a revenant and died. Re-making them into the new revenant formed by ectoplasm.")
+ R.client = client_to_revive
+ key_of_revenant = client_to_revive.key
+ break
+ message_admins("The new revenant's old client either could not be found or is in a new, living mob - grabbing a random candidate instead...")
+ else
+ var/list/candidates = get_candidates(BE_REVENANT)
+ if(!candidates.len)
+ message_admins("No candidates were found for the new revenant. Oh well!")
+ return 0
+ var/client/C = pick(candidates)
+ key_of_revenant = C.key
+ if(!key_of_revenant)
+ message_admins("No ckey was found for the new revenant. Oh well!")
+ return 0
var/datum/mind/player_mind = new /datum/mind(key_of_revenant)
player_mind.active = 1
player_mind.transfer_to(R)
@@ -316,4 +402,7 @@
ticker.mode.traitors |= player_mind
message_admins("[key_of_revenant] has been made into a revenant by reforming ectoplasm.")
log_game("[key_of_revenant] was spawned as a revenant by reforming ectoplasm.")
+ qdel(src)
+ if(src) //Should never happen, but just in case
+ inert = 1
return 1
diff --git a/code/modules/mob/living/simple_animal/revenant/revenant_abilities.dm b/code/modules/mob/living/simple_animal/revenant/revenant_abilities.dm
index b4f47647871..a8d198286b8 100644
--- a/code/modules/mob/living/simple_animal/revenant/revenant_abilities.dm
+++ b/code/modules/mob/living/simple_animal/revenant/revenant_abilities.dm
@@ -1,99 +1,16 @@
-//Harvest Essence: The bread and butter of the revenant. The basic way of harvesting additional essence.
-/obj/effect/proc_holder/spell/targeted/revenant_harvest
- name = "Harvest (0E)"
- desc = "Siphons the lingering spectral essence from a human, empowering yourself."
- panel = "Revenant Abilities"
- charge_max = 100 //Short cooldown
- clothes_req = 0
- range = 5
- var/essence_drained = 0
- var/draining
- var/list/drained_mobs = list() //Cannot harvest the same mob twice
-
-/obj/effect/proc_holder/spell/targeted/revenant_harvest/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
- if(!user.castcheck(0))
- charge_counter = charge_max
- return
- for(var/mob/living/carbon/human/target in targets)
- spawn(0)
- if(draining)
- user << "You are already siphoning the essence of a soul!"
- return
- if(target in drained_mobs)
- user << "[target]'s soul is dead and empty."
- return
- if(target.stat != DEAD)
- user << "This being's soul is too strong to harvest."
- if(prob(10))
- target << "You feel as if you are being watched."
- return
- draining = 1
- essence_drained = 1
- user << "You search for the still-living soul of [target]."
- sleep(10)
- if(target.ckey)
- user << "Their soul burns with intelligence."
- essence_drained += 3
- sleep(20)
- switch(essence_drained)
- if(1 to 2)
- user << "[target] will not yield much essence. Still, every bit counts."
- if(3 to 4)
- user << "[target] will yield an average amount of essence."
- if(5 to INFINITY)
- user << "Such a feast! [target] will yield much essence to you."
- sleep(30)
- if(!in_range(user, target))
- user << "You are not close enough to siphon [target]'s soul. The link has been broken."
- draining = 0
- return
- if(!target.stat)
- user << "They are now powerful enough to fight off your draining."
- target << "You feel something tugging across your body before subsiding."
- user << "You begin siphoning essence from [target]'s soul. You can not move while this is happening."
- if(target.stat != DEAD)
- target << "You feel a horribly unpleasant draining sensation as your grip on life weakens..."
- user.icon_state = "revenant_draining"
- user.notransform = 1
- user.revealed = 1
- user.invisibility = 0
- target.visible_message("[target] suddenly rises slightly into the air, their skin turning an ashy gray.")
- target.Beam(user,icon_state="drain_life",icon='icons/effects/effects.dmi',time=80)
- target.death(0)
- target.visible_message("[target] gently slumps back onto the ground.")
- user.icon_state = "revenant_idle"
- user.change_essence_amount(essence_drained * 5, 0, target)
- user << "[target]'s soul has been considerably weakened and will yield no more essence for the time being."
- user.revealed = 0
- user.notransform = 0
- user.invisibility = INVISIBILITY_OBSERVER
- drained_mobs.Add(target)
- draining = 0
-
-
//Transmit: the revemant's only direct way to communicate. Sends a single message silently to a single mob for 5E.
/obj/effect/proc_holder/spell/targeted/revenant_transmit
- name = "Transmit (5E)"
+ name = "Transmit"
desc = "Telepathically transmits a message to the target."
- panel = "Revenant Abilities (Locked)"
- charge_max = 50
+ panel = "Revenant Abilities"
+ charge_max = 0
clothes_req = 0
- range = -1
- include_user = 1
- var/locked = 1
+ range = 7
+ include_user = 0
+ action_icon_state = "r_transmit"
+ action_background_icon_state = "bg_revenant"
/obj/effect/proc_holder/spell/targeted/revenant_transmit/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
- if(!user.castcheck(-5))
- charge_counter = charge_max
- return
- if(locked)
- usr << "You have unlocked Transmit!"
- locked = 0
- charge_counter = charge_max
- panel = "Revenant Abilities"
- range = 7
- include_user = 0
- return
for(var/mob/living/M in targets)
spawn(0)
var/msg = stripped_input(usr, "What do you wish to tell [M]?", null, "")
@@ -101,28 +18,36 @@
charge_counter = charge_max
return
usr << "You transmit to [M]: [msg]"
- M << "A strange voice resonates in your head... [msg]"
+ M << "An alien voice resonates from all around... [msg]"
//Overload Light: Breaks a light that's online and sends out lightning bolts to all nearby people.
/obj/effect/proc_holder/spell/aoe_turf/revenant_light
- name = "Overload Light (25E)"
- desc = "Directs a large amount of essence into an electrical light, causing an impressive light show."
+ name = "Overload Lights (30E)"
+ desc = "Directs a large amount of essence into nearby electrical lights, causing lights to shock those nearby."
panel = "Revenant Abilities (Locked)"
- charge_max = 300
+ charge_max = 200
clothes_req = 0
range = 1
+ var/reveal = 80
+ var/stun = 20
var/locked = 1
+ action_icon_state = "overload_lights"
+ action_background_icon_state = "bg_revenant"
/obj/effect/proc_holder/spell/aoe_turf/revenant_light/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
- if(!user.castcheck(-25))
- charge_counter = charge_max
- return
if(locked)
- user << "You have unlocked Overload Light!"
+ if(!user.castcheck(-30))
+ charge_counter = charge_max
+ return
+ user << "You have unlocked Overload Lights!"
+ name = "Overload Lights (20E)"
panel = "Revenant Abilities"
locked = 0
- range = 5
+ range = 2
+ charge_counter = charge_max
+ return
+ if(!user.castcheck(-20))
charge_counter = charge_max
return
for(var/turf/T in targets)
@@ -132,57 +57,118 @@
if(!L.on)
return
L.visible_message("\The [L] suddenly flares brightly and begins to spark!")
- sleep(20)
- for(var/mob/living/M in orange(4, L))
+ sleep(10)
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(4, 1, L)
+ s.start()
+ sleep(10)
+ for(var/mob/living/M in range(4, L))
if(M == user)
return
M.Beam(L,icon_state="lightning",icon='icons/effects/effects.dmi',time=5)
M.electrocute_act(25, "[L.name]")
+ var/datum/effect/effect/system/spark_spread/z = new /datum/effect/effect/system/spark_spread
+ z.set_up(4, 1, M)
+ z.start()
playsound(M, 'sound/machines/defib_zap.ogg', 50, 1, -1)
- user.reveal(50, 1)
+ user.reveal(reveal)
+ user.stun(stun)
//Defile: Corrupts nearby stuff, unblesses floor tiles.
-/obj/effect/proc_holder/spell/aoe_turf/revenantDefile
- name = "Defile (30E)"
- desc = "Twists and corrupts certain nearby objects. Also dispels holy auras on floors, but not salt lines."
+/obj/effect/proc_holder/spell/aoe_turf/revenant_defile
+ name = "Defile (20E)"
+ desc = "Twists and corrupts the nearby area. Also dispels holy auras on floors."
panel = "Revenant Abilities (Locked)"
- charge_max = 300
+ charge_max = 200
clothes_req = 0
range = 1
+ var/reveal = 100
+ var/stun = 20
var/locked = 1
+ action_icon_state = "defile"
+ action_background_icon_state = "bg_revenant"
-/obj/effect/proc_holder/spell/aoe_turf/revenantDefile/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
- if(!user.castcheck(-30))
- charge_counter = charge_max
- return
+/obj/effect/proc_holder/spell/aoe_turf/revenant_defile/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
if(locked)
+ if(!user.castcheck(-35))
+ charge_counter = charge_max
+ return
user << "You have unlocked Defile!"
+ name = "Defile (10E)"
panel = "Revenant Abilities"
locked = 0
- range = 4
+ range = 3
+ charge_counter = charge_max
+ return
+ if(!user.castcheck(-20))
charge_counter = charge_max
return
for(var/turf/T in targets)
spawn(0)
if(T.flags & NOJAUNT)
T.flags -= NOJAUNT
- for(var/obj/machinery/bot/secbot/secbot in T.contents) //Not including ED-209
- secbot.emagged = 2
- secbot.Emag(null)
- for(var/obj/machinery/bot/cleanbot/cleanbot in T.contents)
- cleanbot.emagged = 2
- cleanbot.Emag(null)
for(var/mob/living/carbon/human/human in T.contents)
human << "You suddenly feel tired."
- human.adjustStaminaLoss(25)
- for(var/mob/living/silicon/robot/robot in T.contents)
- robot.visible_message("[robot] lets out an alarm!", \
- "01001111 01010110 01000101 01010010 01001100 01001111 01000001 01000100") //Translates to "OVERLOAD"
- robot << 'sound/misc/interference.ogg'
- playsound(robot, 'sound/machines/warning-buzzer.ogg', 50, 1)
+ human.adjustStaminaLoss(35)
for(var/obj/structure/window/window in T.contents)
- window.hit(rand(10,50))
+ window.hit(rand(50,125))
for(var/obj/machinery/light/light in T.contents)
light.flicker() //spooky
- user.reveal(30, 1)
+ user.reveal(reveal)
+ user.stun(stun)
+
+
+//Malfunction: Makes bad stuff happen to robots and machines.
+/obj/effect/proc_holder/spell/aoe_turf/revenant_malf
+ name = "Malfunction (50E)"
+ desc = "Corrupts and damages nearby machines and mechanical objects."
+ panel = "Revenant Abilities (Locked)"
+ charge_max = 150
+ clothes_req = 0
+ range = 1
+ var/reveal = 60
+ var/stun = 30
+ var/locked = 1
+ action_icon_state = "malfunction"
+ action_background_icon_state = "bg_revenant"
+
+/obj/effect/proc_holder/spell/aoe_turf/revenant_malf/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
+ if(locked)
+ if(!user.castcheck(-50))
+ charge_counter = charge_max
+ return
+ user << "You have unlocked Malfunction!"
+ name = "Malfunction (15E)"
+ panel = "Revenant Abilities"
+ locked = 0
+ range = 4
+ charge_counter = charge_max
+ return
+ if(!user.castcheck(-15))
+ charge_counter = charge_max
+ return
+ for(var/turf/T in targets)
+ spawn(0)
+ for(var/obj/machinery/bot/bot in T.contents)
+ if(!bot.emagged)
+ bot.locked = 0
+ bot.open = 1
+ bot.Emag(null)
+ for(var/obj/machinery/mach in T.contents)
+ if(istype(mach, /obj/machinery/dominator) || istype(mach, /obj/machinery/power/apc)) //Doesn't work on dominators and APCs, to prevent kekkery
+ continue
+ if(prob(10))
+ mach.emag_act(null)
+ else
+ mach.emp_act(1)
+ for(var/mob/living/silicon/robot/S in T.contents) //Only works on cyborgs, not AI
+ S << "ERROR $!(@ ERROR )#^! SENSORY OVERLOAD \[$(!@#"
+ S << 'sound/misc/interference.ogg'
+ playsound(S, 'sound/machines/warning-buzzer.ogg', 50, 1)
+ var/datum/effect/effect/system/spark_spread/sp = new /datum/effect/effect/system/spark_spread
+ sp.set_up(5, 1, S)
+ sp.start()
+ S.Weaken(6)
+ user.reveal(reveal)
+ user.stun(stun)
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/revenant/revenant_spawn_event.dm b/code/modules/mob/living/simple_animal/revenant/revenant_spawn_event.dm
index 25516b51619..0cb19dab3da 100644
--- a/code/modules/mob/living/simple_animal/revenant/revenant_spawn_event.dm
+++ b/code/modules/mob/living/simple_animal/revenant/revenant_spawn_event.dm
@@ -3,9 +3,9 @@
/datum/round_event_control/revenant
name = "Spawn Revenant"
typepath = /datum/round_event/revenant
- weight = 0 //Admin only
+ weight = 7
max_occurrences = 3
- earliest_start = 0 //Meant to mix things up early-game.
+ earliest_start = 6000 //Meant to mix things up early-game.
/datum/round_event/revenant
diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm
index cb43847c32c..3914c74e65c 100644
--- a/code/modules/mob/living/simple_animal/shade.dm
+++ b/code/modules/mob/living/simple_animal/shade.dm
@@ -7,6 +7,7 @@
icon_living = "shade"
maxHealth = 50
health = 50
+ healable = 0
speak_emote = list("hisses")
emote_hear = list("wails.","screeches.")
response_help = "puts their hand through"
@@ -15,7 +16,7 @@
speak_chance = 1
melee_damage_lower = 5
melee_damage_upper = 15
- attacktext = "drains the life from"
+ attacktext = "metaphysically strikes"
minbodytemp = 0
maxbodytemp = 4000
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 64a70739e32..fb57e9a55f5 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -18,7 +18,6 @@
var/turns_per_move = 1
var/turns_since_move = 0
- var/list/butcher_results = null
var/stop_automated_movement = 0 //Use this to temporarely stop random movement or to if you write special movement code for animals.
var/wander = 1 // Does the mob wander around when idle?
var/stop_automated_movement_when_pulled = 1 //When set to 1 this stops the animal from moving when someone is pulling it.
@@ -34,6 +33,9 @@
var/minbodytemp = 250
var/maxbodytemp = 350
+ //Healable by medical stacks? Defaults to yes.
+ var/healable = 1
+
//Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage
var/list/atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) //Leaving something at 0 means it's off - has no maximum
var/unsuitable_atmos_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above
@@ -41,6 +43,8 @@
//LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly
var/melee_damage_lower = 0
var/melee_damage_upper = 0
+ var/melee_damage_type = BRUTE //Damage type of a simple mob's melee attack, should it do damage.
+ var/list/ignored_damage_types = list(BRUTE = 0, BURN = 0, TOX = 0, CLONE = 0, STAMINA = 1, OXY = 0) //Set 0 to receive that damage type, 1 to ignore
var/attacktext = "attacks"
var/attack_sound = null
var/friendly = "nuzzles" //If the mob does no damage with it's attack
@@ -57,6 +61,9 @@
var/obj/item/weapon/card/id/access_card = null //innate access uses an internal ID card
var/flying = 0 //whether it's flying or touching the ground.
+ var/buffed = 0 //In the event that you want to have a buffing effect on the mob, but don't want it to stack with other effects, any outside force that applies a buff to a simple mob should at least set this to 1, so we have something to check against
+ var/gold_core_spawnable = 0 //if 1 can be spawned by plasma with gold core, 2 are 'friendlies' spawned with blood
+
/mob/living/simple_animal/New()
..()
verbs -= /mob/verb/observe
@@ -250,7 +257,7 @@
/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
- attack_threshold_check(damage)
+ attack_threshold_check(damage,M.melee_damage_type)
return 1
/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj)
@@ -260,8 +267,21 @@
Proj.on_hit(src)
return 0
+/mob/living/simple_animal/adjustBruteLoss(amount)
+ if(!ignored_damage_types[BRUTE])
+ ..()
+
/mob/living/simple_animal/adjustFireLoss(amount)
- adjustBruteLoss(amount)
+ if(!ignored_damage_types[BURN])
+ adjustBruteLoss(amount)
+
+/mob/living/simple_animal/adjustToxLoss(amount)
+ if(!ignored_damage_types[TOX])
+ ..(amount)
+
+/mob/living/simple_animal/adjustCloneLoss(amount)
+ if(!ignored_damage_types[CLONE])
+ ..(amount)
/mob/living/simple_animal/adjustStaminaLoss(amount)
return
@@ -331,8 +351,8 @@
attack_threshold_check(damage)
return 1
-/mob/living/simple_animal/proc/attack_threshold_check(damage)
- if(damage <= force_threshold)
+/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE)
+ if(damage <= force_threshold || ignored_damage_types[damagetype])
visible_message("[src] looks unharmed.")
else
adjustBruteLoss(damage)
@@ -343,39 +363,6 @@
if(O.flags & NOBLUDGEON)
return
- if(istype(O, /obj/item/stack/medical))
- user.changeNext_move(CLICK_CD_MELEE)
- if(stat != DEAD)
- var/obj/item/stack/medical/MED = O
- if(health < maxHealth)
- if(MED.amount >= 1)
- if(MED.heal_brute >= 1)
- adjustBruteLoss(-MED.heal_brute)
- MED.amount -= 1
- if(MED.amount <= 0)
- qdel(MED)
- visible_message("[user] applies [MED] on [src].")
- return
- else
- user << "[MED] won't help at all."
- return
- else
- user << "[src] is at full health."
- return
- else
- user << "[src] is dead, medical items won't bring it back to life."
- return
-
- if((butcher_results) && (stat == DEAD))
- user.changeNext_move(CLICK_CD_MELEE)
- var/sharpness = is_sharp(O)
- if(sharpness)
- user << "You begin to butcher [src]..."
- playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1)
- if(do_mob(user, src, 80/sharpness))
- harvest(user)
- return
-
..()
/mob/living/simple_animal/movement_delay()
@@ -404,14 +391,14 @@
/mob/living/simple_animal/ex_act(severity, target)
..()
switch (severity)
- if (1.0)
+ if (1)
gib()
return
- if (2.0)
+ if (2)
adjustBruteLoss(60)
- if(3.0)
+ if(3)
adjustBruteLoss(30)
updatehealth()
@@ -470,11 +457,6 @@
if(alone && partner && children < 3)
new childtype(loc)
-// Harvest an animal's delicious byproducts
-/mob/living/simple_animal/proc/harvest(mob/living/user)
- visible_message("[user] butchers [src].")
- gib()
-
/mob/living/simple_animal/stripPanelUnequip(obj/item/what, mob/who, where, child_override)
if(!child_override)
src << "You don't have the dexterity to do this!"
diff --git a/code/modules/mob/living/simple_animal/slaughter/slaughter.dm b/code/modules/mob/living/simple_animal/slaughter/slaughter.dm
index ff0c9866215..e616aa4fb42 100644
--- a/code/modules/mob/living/simple_animal/slaughter/slaughter.dm
+++ b/code/modules/mob/living/simple_animal/slaughter/slaughter.dm
@@ -1,9 +1,9 @@
//////////////////The Monster
/mob/living/simple_animal/slaughter
- name = "Slaughter Demon"
- real_name = "Slaughter Demon"
- desc = "You should run."
+ name = "slaughter demon"
+ real_name = "slaughter demon"
+ desc = "A large, menacing creature covered in armored black scales."
speak_emote = list("gurgles")
emote_hear = list("wails","screeches")
response_help = "thinks better of touching"
@@ -23,6 +23,7 @@
attacktext = "wildly tears into"
maxHealth = 200
health = 200
+ healable = 0
environment_smash = 1
melee_damage_lower = 30
melee_damage_upper = 30
@@ -30,10 +31,18 @@
var/boost = 0
bloodcrawl = BLOODCRAWL_EAT
see_invisible = SEE_INVISIBLE_MINIMUM
- var/playstyle_string = "You are the Slaughter Demon, a terible creature from another existence. You have a single desire: To kill. \
- You may Ctrl+Click on blood pools to travel through them, appearing and dissaapearing from the station at will. \
- Pulling a dead or critical mob while you enter a pool will pull them in with you, allowing you to feast. \
- You move quickly upon leaving a pool of blood, but the material world will soon sap your strength and leave you sluggish. "
+ var/list/consumed_mobs = list()
+ var/playstyle_string = "You are a slaughter demon, a terrible creature from another realm. You have a single desire: To kill. \
+ You may use the \"Blood Crawl\" ability near blood pools to travel through them, appearing and dissaapearing from the station at will. \
+ Pulling a dead or unconscious mob while you enter a pool will pull them in with you, allowing you to feast and regain your health. \
+ You move quickly upon leaving a pool of blood, but the material world will soon sap your strength and leave you sluggish. "
+
+/mob/living/simple_animal/slaughter/New()
+ ..()
+ var/obj/effect/proc_holder/spell/bloodcrawl/bloodspell = new
+ AddSpell(bloodspell)
+ if(istype(loc, /obj/effect/dummy/slaughter))
+ bloodspell.phased = 1
/mob/living/simple_animal/slaughter/Life()
..()
@@ -44,33 +53,63 @@
/mob/living/simple_animal/slaughter/death()
..(1)
- new /obj/effect/decal/cleanable/blood (src.loc)
- new /obj/item/weapon/demonheart (src.loc)
+ new /obj/effect/decal/cleanable/blood (get_turf(src))
+ var/obj/effect/decal/cleanable/blood/innards = new (get_turf(src))
+ innards.icon = 'icons/obj/surgery.dmi'
+ innards.icon_state = "innards"
+ innards.name = "pile of viscera"
+ innards.desc = "A repulsive pile of guts and gore."
+ new /obj/item/organ/internal/heart/demon (src.loc)
playsound(get_turf(src),'sound/magic/demon_dies.ogg', 200, 1)
- visible_message("The [src] screams in anger as its form collapes into a pool of viscera.")
+ visible_message("[src] screams in anger as it collapses into a puddle of viscera, its most recent meals spilling out of it.")
+ for(var/mob/living/M in consumed_mobs)
+ M.loc = get_turf(src)
ghostize()
qdel(src)
return
/mob/living/simple_animal/slaughter/phasein()
- ..()
+ . = ..()
speed = 0
- boost = world.time + 30
+ boost = world.time + 60
-//////////The Loot
-
-/obj/item/weapon/demonheart
- name = "demon's heart"
- desc = "It's still faintly beating with rage"
+//The loot from killing a slaughter demon - can be consumed to allow the user to blood crawl
+/obj/item/organ/internal/heart/demon
+ name = "demon heart"
+ desc = "Still it beats furiously, emanating an aura of utter hate."
icon = 'icons/obj/surgery.dmi'
- icon_state = "heart-on"
+ icon_state = "demon_heart"
origin_tech = "combat=5;biotech=8"
-/obj/item/weapon/demonheart/attack_self(mob/living/user)
- visible_message("[user] feasts upon the [src].")
- user << "You absorb some of the demon's power!"
- user.bloodcrawl = BLOODCRAWL
- qdel(src)
+/obj/item/organ/internal/heart/demon/attack(mob/M, mob/living/carbon/user, obj/target)
+ if(M != user)
+ return ..()
+ user.visible_message("[user] raises [src] to their mouth and tears into it with their teeth!", \
+ "An unnatural hunger consumes you. You raise [src] your mouth and devour it!")
+ playsound(user, 'sound/magic/Demon_consume.ogg', 50, 1)
+ for(var/obj/effect/proc_holder/spell/knownspell in user.mind.spell_list)
+ if(knownspell.type == /obj/effect/proc_holder/spell/bloodcrawl)
+ user <<"...and you don't feel any different."
+ qdel(src)
+ return
+ user.visible_message("[user]'s eyes flare a deep crimson!", \
+ "You feel a strange power seep into your body... you have absorbed the demon's blood-travelling powers!")
+ /*for(var/obj/item/organ/internal/O in user.internal_organs)
+ if(istype(O, /obj/item/organ/internal/heart))
+ O.Remove(user, 1)
+ O.loc = get_turf(user)
+ qdel(O)*/
+ user.drop_item()
+ src.Insert(user) //Consuming the heart literally replaces your heart with a demon heart. H A R D C O R E
+/obj/item/organ/internal/heart/demon/Insert(mob/living/carbon/M, special = 0)
+ ..()
+ if(M.mind)
+ M.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl(null))
+
+/obj/item/organ/internal/heart/demon/Remove(mob/living/carbon/M, special = 0)
+ ..()
+ if(M.mind)
+ M.mind.remove_spell(/obj/effect/proc_holder/spell/bloodcrawl)
diff --git a/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm b/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm
index de3e477ab6d..cbc845bc69d 100644
--- a/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm
+++ b/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm
@@ -44,9 +44,10 @@
player_mind.special_role = "Slaughter Demon"
ticker.mode.traitors |= player_mind
S << S.playstyle_string
- S << "You are currently not currently in the same plane of existence as the station. Ctrl+Click a blood pool to manifest."
- message_admins("[key_of_slaughter] has been made into a Slaughter Demon by an event.")
- log_game("[key_of_slaughter] was spawned as a Slaughter Demon by an event.")
+ S << "You are currently not currently in the same plane of existence as the station. Blood Crawl near a blood pool to manifest."
+ S << 'sound/magic/demon_dies.ogg'
+ message_admins("[key_of_slaughter] has been made into a slaughter demon by an event.")
+ log_game("[key_of_slaughter] was spawned as a slaughter demon by an event.")
return 1
@@ -57,11 +58,11 @@
/datum/round_event/slaughter/proc/find_slaughter()
- message_admins("Attempted to spawn a Slaughter Demon but there was no players available. Will try again momentarily.")
+ message_admins("Attempted to spawn a slaughter demon but there was no players available. Will try again momentarily.")
spawn(50)
if(get_slaughter(1))
- message_admins("Situation has been resolved, [key_of_slaughter] has been spawned as a Slaughter Demon.")
- log_game("[key_of_slaughter] was spawned as a Slaughter Demon by an event.")
+ message_admins("Situation has been resolved, [key_of_slaughter] has been spawned as a slaughter demon.")
+ log_game("[key_of_slaughter] was spawned as a slaughter demon by an event.")
return 0
- message_admins("Unfortunately, no candidates were available for becoming a Slaugter Demon. Shutting down.")
+ message_admins("Unfortunately, no candidates were available for becoming a slaughter demon. Shutting down.")
return kill()
diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm
index 5531fcd6a85..c0756da1c8b 100644
--- a/code/modules/mob/living/simple_animal/slime/life.dm
+++ b/code/modules/mob/living/simple_animal/slime/life.dm
@@ -251,9 +251,8 @@
if(istype(L, /mob/living/carbon/human)) //Ignore slime(wo)men
var/mob/living/carbon/human/H = L
- if(H.dna)
- if(src.type in H.dna.species.ignored_by)
- continue
+ if(src.type in H.dna.species.ignored_by)
+ continue
if(!L.canmove) // Only one slime can latch on at a time.
var/notarget = 0
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 6c2582fe005..045b5c31410 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -24,6 +24,7 @@
maxHealth = 150
health = 150
+ healable = 0
gender = NEUTER
nutrition = 700
diff --git a/code/modules/mob/living/simple_animal/worm.dm b/code/modules/mob/living/simple_animal/worm.dm
index 273d14d2c90..f17d5a6ad9a 100644
--- a/code/modules/mob/living/simple_animal/worm.dm
+++ b/code/modules/mob/living/simple_animal/worm.dm
@@ -168,7 +168,7 @@
if(die)
newHead.Die()
- del(src)
+ qdel(src)
proc/ProcessStomach()
for(var/atom/movable/stomachContent in contents)
@@ -177,16 +177,16 @@
if(!istype(stomachContent,/obj/item/stack/sheet/mineral/plasma))
var/obj/item/stack/oldStack = stomachContent
new /obj/item/stack/sheet/mineral/plasma(src, oldStack.amount)
- del(oldStack)
+ qdel(oldStack)
continue
else if(istype(stomachContent,/obj/item)) //converts to plasma, keeping the w_class
var/obj/item/oldItem = stomachContent
new /obj/item/stack/sheet/mineral/plasma(src, oldItem.w_class)
- del(oldItem)
+ qdel(oldItem)
continue
else
new /obj/item/stack/sheet/mineral/plasma(src, flatPlasmaValue) //just flat amount
- del(stomachContent)
+ qdel(stomachContent)
continue
if(previous)
diff --git a/code/modules/mob/living/ventcrawling.dm b/code/modules/mob/living/ventcrawling.dm
index c0531581a36..a44e4865897 100644
--- a/code/modules/mob/living/ventcrawling.dm
+++ b/code/modules/mob/living/ventcrawling.dm
@@ -37,7 +37,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/components/unary
if(vent_found)
- var/datum/pipeline/vent_found_parent = vent_found.parents[PARENT1]
+ var/datum/pipeline/vent_found_parent = vent_found.PARENT1
if(vent_found_parent && (vent_found_parent.members.len || vent_found_parent.other_atmosmch))
visible_message("[src] begins climbing into the ventilation system..." ,"You begin climbing into the ventilation system...")
@@ -70,7 +70,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/components/unary
if(!istype(starting_machine) || !starting_machine.returnPipenet())
return
var/list/totalMembers = list()
- var/datum/pipeline/starting_machine_parent = starting_machine.parents[PARENT1]
+ var/datum/pipeline/starting_machine_parent = starting_machine.PARENT1
totalMembers += starting_machine_parent.members
totalMembers += starting_machine_parent.other_atmosmch
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index c6b61942361..f262ddefc1f 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -30,7 +30,7 @@
client.images = null //remove the images such as AIs being unable to see runes
client.screen = list() //remove hud items just in case
- if(hud_used) del(hud_used) //remove the hud objects
+ if(hud_used) qdel(hud_used) //remove the hud objects
hud_used = new /datum/hud(src)
next_move = 1
diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm
index 1892a98a99a..4c7da6069be 100644
--- a/code/modules/mob/logout.dm
+++ b/code/modules/mob/logout.dm
@@ -5,8 +5,6 @@
if(admin_datums[src.ckey])
if (ticker && ticker.current_state == GAME_STATE_PLAYING) //Only report this stuff if we are currently playing.
var/admins_number = admins.len
-
- message_admins("Admin logout: [key_name(src)]")
if(admins_number == 0) //Apparently the admin logging out is no longer an admin at this point, so we have to check this towards 0 and not towards 1. Awell.
var/cheesy_message = pick( list( \
"I have no admins online!",\
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 3c0e579eb5f..46dc37f5cf0 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -8,7 +8,7 @@
for(var/infection in viruses)
qdel(infection)
ghostize()
- ..()
+ return ..()
/mob/proc/sac_act(obj/effect/rune/R, mob/victim)
return
@@ -376,7 +376,7 @@ var/list/slot_equipment_priority = list( \
//this and stop_pulling really ought to be /mob/living procs
/mob/proc/start_pulling(atom/movable/AM)
- if ( !AM || !src || src==AM || !isturf(src.loc) ) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort!
+ if ( !AM || !src || src==AM || !isturf(AM.loc) ) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort!
return
if (!( AM.anchored ))
AM.add_fingerprint(src)
@@ -975,4 +975,4 @@ var/list/slot_equipment_priority = list( \
//override to avoid rotating pixel_xy on mobs
/mob/shuttleRotate(rotation)
- dir = angle2dir(rotation+dir2angle(dir))
\ No newline at end of file
+ dir = angle2dir(rotation+dir2angle(dir))
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 265a428ba71..54262819d23 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -83,7 +83,7 @@
var/a_intent = "help"//Living
var/m_intent = "run"//Living
var/lastKnownIP = null
- var/obj/structure/stool/bed/buckled = null//Living
+ var/obj/buckled = null//Living
var/obj/item/l_hand = null//Living
var/obj/item/r_hand = null//Living
var/obj/item/weapon/storage/s_active = null//Carbon
@@ -106,9 +106,6 @@
var/radiation = 0//Carbon
- var/list/mutations = list() //Carbon -- Doohl
- //see: setup.dm for list of mutations
-
var/voice_name = "unidentifiable voice"
var/list/faction = list("neutral") //A list of factions that this mob is currently in, for hostile mob targetting, amongst other things
@@ -139,6 +136,9 @@
var/area/lastarea = null
var/digitalcamo = 0 // Can they be tracked by the AI?
+ var/digitalinvis = 0 //Are they ivisible to the AI?
+ var/image/digitaldisguise = null //what does the AI see instead of them?
+
var/weakeyes = 0 //Are they vulnerable to flashes?
var/has_unlimited_silicon_privilege = 0 // Can they interact with station electronics
diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm
index fa3a9bb4bbc..084327a2b75 100644
--- a/code/modules/mob/mob_grab.dm
+++ b/code/modules/mob/mob_grab.dm
@@ -14,7 +14,7 @@
layer = 21
item_state = "nothing"
- w_class = 5.0
+ w_class = 5
/obj/item/weapon/grab/New(mob/user, mob/victim)
@@ -44,7 +44,7 @@
assailant.client.screen -= hud
assailant = null
qdel(hud)
- ..()
+ return ..()
//Used by throw code to hand over the mob, instead of throwing the grab. The grab is then deleted by the throw code.
/obj/item/weapon/grab/proc/get_mob_if_throwable()
@@ -207,9 +207,9 @@
var/mob/living/carbon/attacker = user
user.visible_message("[user] is attempting to devour [affecting]!")
if(istype(user, /mob/living/carbon/alien/humanoid/hunter))
- if(!do_mob(user, affecting)||!do_after(user, 30, target = affecting)) return
+ if(!do_mob(user, affecting, 60)) return
else
- if(!do_mob(user, affecting)||!do_after(user, 100, target = affecting)) return
+ if(!do_mob(user, affecting, 130)) return
user.visible_message("[user] devours [affecting]!")
affecting.loc = user
attacker.stomach_contents.Add(affecting)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 857b7f35181..f7cc8017d76 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -125,6 +125,11 @@
return 1
return 0
+/proc/isswarmer(A)
+ if(istype(A, /mob/living/simple_animal/hostile/swarmer))
+ return 1
+ return 0
+
/proc/islimb(A)
if(istype(A, /obj/item/organ/limb))
return 1
@@ -448,9 +453,6 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
return 1
return 0
-/mob/proc/has_mutation(mutation)
- return mutation in src.mutations ? 1 : 0
-
/proc/get_both_hands(mob/living/carbon/M)
var/list/hands = list(M.l_hand, M.r_hand)
return hands
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index d65438f65e7..4866385934b 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -200,8 +200,15 @@
M.animate_movement = 2
return
- if(mob.confused && IsEven(world.time))
- step(mob, pick(cardinal))
+ if(mob.confused)
+ if(mob.confused > 40)
+ step(mob, pick(cardinal))
+ else if(prob(mob.confused * 1.5))
+ step(mob, angle2dir(dir2angle(direct) + pick(90, -90)))
+ else if(prob(mob.confused * 3))
+ step(mob, angle2dir(dir2angle(direct) + pick(45, -45)))
+ else
+ step(mob, direct)
else
. = ..()
diff --git a/code/modules/mob/mob_transformation_simple.dm b/code/modules/mob/mob_transformation_simple.dm
index 3b9b6021b15..4d1e46f595a 100644
--- a/code/modules/mob/mob_transformation_simple.dm
+++ b/code/modules/mob/mob_transformation_simple.dm
@@ -40,15 +40,11 @@
M.name = src.name
M.real_name = src.real_name
- if(check_dna_integrity(src) && istype(M, /mob/living/carbon))
+ if(has_dna() && M.has_dna())
var/mob/living/carbon/C = src
var/mob/living/carbon/D = M
- D.dna = C.dna
- updateappearance(D)
- else
- if(istype(M, /mob/living/carbon/human))
- src.client.prefs.copy_to(M)
- ready_dna(M)
+ C.dna.transfer_identity(D)
+ D.updateappearance(mutcolor_update=1, mutations_overlay_update=1)
if(mind && istype(M, /mob/living))
mind.transfer_to(M)
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 2b4776c12b7..a274a75ccde 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -318,7 +318,7 @@
if(SHUTTLE_ESCAPE)
dat += "
The station has been evacuated.
"
if(SHUTTLE_CALL)
- if(SSshuttle.emergency.timeLeft() < 0.5 * initial(SSshuttle.emergencyCallTime)) //Shuttle is past the point of no recall
+ if(!SSshuttle.canRecall())
dat += "
The station is currently undergoing evacuation procedures.
"
var/available_job_count = 0
@@ -362,21 +362,17 @@
var/mob/living/carbon/human/new_character = new(loc)
new_character.lastarea = get_area(loc)
- create_dna(new_character)
-
if(config.force_random_names || appearance_isbanned(src))
client.prefs.random_character()
client.prefs.real_name = client.prefs.pref_species.random_name(gender,1)
client.prefs.copy_to(new_character)
-
+ new_character.dna.update_dna_identity()
if(mind)
mind.active = 0 //we wish to transfer the key manually
mind.transfer_to(new_character) //won't transfer key since the mind is not active
new_character.name = real_name
- ready_dna(new_character, client.prefs.blood_type)
-
new_character.key = key //Manually transfer the key to log them in
new_character.stopLobbySound()
diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm
index 95ac2edf15f..71bd77ffef5 100644
--- a/code/modules/mob/say.dm
+++ b/code/modules/mob/say.dm
@@ -39,7 +39,7 @@
if(name != real_name)
alt_name = " (died as [real_name])"
- message = src.say_quote(message)
+ message = src.say_quote(message, get_spans())
var/rendered = "DEAD:[name][alt_name] [message]"
for(var/mob/M in player_list)
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index 674b88eacb6..7a2aa6fd408 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -1,4 +1,4 @@
-/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG), newname = null)
+/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG))
if (notransform)
return
//Handle items on mob
@@ -16,8 +16,11 @@
int_organs += I
I.Remove(src, 1)
+ if(tr_flags & TR_KEEPITEMS)
+ for(var/obj/item/W in (src.contents-implants-int_organs))
+ unEquip(W)
+
//Make mob invisible and spawn animation
- regenerate_icons()
notransform = 1
canmove = 0
stunned = 1
@@ -35,18 +38,18 @@
qdel(animation)
// hash the original name?
- if (tr_flags & TR_HASHNAME)
+ if(tr_flags & TR_HASHNAME)
O.name = "monkey ([copytext(md5(real_name), 2, 6)])"
O.real_name = "monkey ([copytext(md5(real_name), 2, 6)])"
- if (newname) //if there's a name as an argument, always take that one over the current name
- O.name = newname
- O.real_name = newname
//handle DNA and other attributes
- if(dna)
- dna.transfer_identity(O)
- if(tr_flags & TR_KEEPSE)
- O.dna.struc_enzymes = dna.struc_enzymes
+ dna.transfer_identity(O)
+ O.updateappearance(icon_update=0)
+
+ if(tr_flags & TR_KEEPSE)
+ O.dna.struc_enzymes = dna.struc_enzymes
+ var/datum/mutation/human/race/R = mutations_list[RACEMUT]
+ O.dna.struc_enzymes = R.set_se(O.dna.struc_enzymes, on=1)//we don't want to keep the race block inactive
if(suiciding)
O.suiciding = suiciding
@@ -59,6 +62,7 @@
viruses = list()
for(var/datum/disease/D in O.viruses)
D.affected_mob = O
+ D.holder = O
//keep damage?
if (tr_flags & TR_KEEPDAMAGE)
@@ -69,9 +73,10 @@
O.radiation = radiation
//re-add implants to new mob
- for(var/obj/item/weapon/implant/I in implants)
- I.loc = O
- I.implanted = O
+ if (tr_flags & TR_KEEPIMPLANTS)
+ for(var/obj/item/weapon/implant/I in implants)
+ I.loc = O
+ I.implanted = O
//re-add organs to new mob
if(tr_flags & TR_KEEPORGANS)
@@ -95,16 +100,14 @@
if(loc.vars[A] == src)
loc.vars[A] = O
- updateappearance(O)
. = O
- if ( !(tr_flags & TR_KEEPSRC) ) //flag should be used if monkeyize() is called inside another proc of src so that one does not crash
- qdel(src)
+ qdel(src)
////////////////////////// Humanize //////////////////////////////
//Could probably be merged with monkeyize but other transformations got their own procs, too
-/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG), newname = null)
+/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG))
if (notransform)
return
//Handle items on mob
@@ -124,7 +127,7 @@
//now the rest
if (tr_flags & TR_KEEPITEMS)
- for(var/obj/item/W in (src.contents-implants))
+ for(var/obj/item/W in (src.contents-implants-int_organs))
unEquip(W)
if (client)
client.screen -= W
@@ -133,11 +136,7 @@
W.dropped(src)
W.layer = initial(W.layer)
- // for(var/obj/item/W in src)
- // unEquip(W)
-
//Make mob invisible and spawn animation
- regenerate_icons()
notransform = 1
canmove = 0
stunned = 1
@@ -155,28 +154,21 @@
O.equip_to_appropriate_slot(C)
qdel(animation)
- O.gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE
+ dna.transfer_identity(O)
+ O.updateappearance(mutcolor_update=1)
- if(dna)
- dna.transfer_identity(O)
- O.update_icons()
- if(tr_flags & TR_KEEPSE)
- O.dna.struc_enzymes = dna.struc_enzymes
- domutcheck(O)
-
- if(!dna.species)
- hardset_dna(O, null, null, null, null, /datum/species/human)
+ if(cmptext("monkey",copytext(O.dna.real_name,1,7)))
+ O.real_name = random_unique_name(O.gender)
+ O.dna.generate_unique_enzymes(O)
else
- hardset_dna(O, null, null, null, null, dna.species.type)
-
- dna = null
- if(newname) //if there's a name as an argument, always take that one over the current name
- O.real_name = newname
- else
- if(cmptext("monkey",copytext(O.dna.real_name,1,7)))
- O.dna.real_name = random_unique_name(O.gender)
O.real_name = O.dna.real_name
- O.name = O.real_name
+ O.name = O.real_name
+
+ if(tr_flags & TR_KEEPSE)
+ O.dna.struc_enzymes = dna.struc_enzymes
+ var/datum/mutation/human/race/R = mutations_list[RACEMUT]
+ O.dna.struc_enzymes = R.set_se(O.dna.struc_enzymes, on=0)//we don't want to keep the race block active
+ O.domutcheck()
if(suiciding)
O.suiciding = suiciding
@@ -189,6 +181,7 @@
viruses = list()
for(var/datum/disease/D in O.viruses)
D.affected_mob = O
+ D.holder = O
O.med_hud_set_status()
//keep damage?
@@ -200,10 +193,11 @@
O.radiation = radiation
//re-add implants to new mob
- for(var/obj/item/weapon/implant/I in implants)
- I.loc = O
- I.implanted = O
- O.sec_hud_set_implants()
+ if (tr_flags & TR_KEEPIMPLANTS)
+ for(var/obj/item/weapon/implant/I in implants)
+ I.loc = O
+ I.implanted = O
+ O.sec_hud_set_implants()
if(tr_flags & TR_KEEPORGANS)
for(var/obj/item/organ/internal/I in O.internal_organs)
@@ -214,21 +208,23 @@
if(mind)
mind.transfer_to(O)
+ if(O.mind.changeling)
+ for(var/obj/effect/proc_holder/changeling/humanform/HF in O.mind.changeling.purchasedpowers)
+ mind.changeling.purchasedpowers -= HF
+
O.a_intent = "help"
if (tr_flags & TR_DEFAULTMSG)
O << "You are now a human."
O.update_pipe_vision()
- updateappearance(O)
. = O
for(var/A in loc.vars)
if(loc.vars[A] == src)
loc.vars[A] = O
- if ( !(tr_flags & TR_KEEPSRC) ) //don't delete src yet if it's needed to finish calling proc
- qdel(src)
+ qdel(src)
/mob/new_player/AIize()
@@ -430,14 +426,10 @@
/mob/living/carbon/human/proc/Blobize()
if (notransform)
return
- var/obj/effect/blob/core/new_blob = new /obj/effect/blob/core (loc)
- if(!client)
- for(var/mob/dead/observer/G in player_list)
- if(ckey == "@[G.ckey]")
- new_blob.create_overmind(G.client , 1)
- break
+ if(!client) //TOO BAD
+ new /obj/effect/blob/core (loc)
else
- new_blob.create_overmind(src.client , 1)
+ new /obj/effect/blob/core (loc,new_overmind = src.client)
gib(src)
diff --git a/code/modules/ninja/ninja_event.dm b/code/modules/ninja/ninja_event.dm
index 37e5ff55bd2..2e1e6528256 100644
--- a/code/modules/ninja/ninja_event.dm
+++ b/code/modules/ninja/ninja_event.dm
@@ -167,11 +167,10 @@ Contents:
/proc/create_space_ninja(spawn_loc)
var/mob/living/carbon/human/new_ninja = new(spawn_loc)
- if(prob(50)) new_ninja.gender = "female"
var/datum/preferences/A = new()//Randomize appearance for the ninja.
A.real_name = "[pick(ninja_titles)] [pick(ninja_names)]"
A.copy_to(new_ninja)
- ready_dna(new_ninja)
+ new_ninja.dna.update_dna_identity()
new_ninja.equip_space_ninja()
return new_ninja
diff --git a/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm b/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm
index 053931b171e..9af14584432 100644
--- a/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm
+++ b/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm
@@ -104,11 +104,11 @@ It is possible to destroy the net by the occupant or someone else.
/obj/effect/energy_net/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
health-=50
- if(2.0)
+ if(2)
health-=50
- if(3.0)
+ if(3)
health-=prob(50)?50:25
healthcheck()
return
diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm
index 107502ce151..c7a1f0f143d 100644
--- a/code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm
+++ b/code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm
@@ -18,7 +18,7 @@ Contents:
U << "You don't have enough power to enable Stealth!"
return
s_active=!s_active
- animate(U, U.alpha = 0,time = 15)
+ animate(U, alpha = 0,time = 15)
U.visible_message("[U.name] vanishes into thin air!", \
"You are now invisible to normal detection.")
return
@@ -30,7 +30,7 @@ Contents:
return 0
if(s_active)
s_active=!s_active
- animate(U, U.alpha = 255, time = 15)
+ animate(U, alpha = 255, time = 15)
U.visible_message("[U.name] appears from thin air!", \
"You are now visible.")
return 1
diff --git a/code/modules/ninja/suit/suit.dm b/code/modules/ninja/suit/suit.dm
index 5fcca544ae9..c3c27a16611 100644
--- a/code/modules/ninja/suit/suit.dm
+++ b/code/modules/ninja/suit/suit.dm
@@ -39,11 +39,11 @@ Contents:
//Main function variables.
var/s_initialized = 0//Suit starts off.
var/s_coold = 0//If the suit is on cooldown. Can be used to attach different cooldowns to abilities. Ticks down every second based on suit ntick().
- var/s_cost = 5.0//Base energy cost each ntick.
- var/s_acost = 25.0//Additional cost for additional powers active.
- var/s_delay = 40.0//How fast the suit does certain things, lower is faster. Can be overridden in specific procs. Also determines adverse probability.
- var/a_transfer = 20.0//How much reagent is transferred when injecting.
- var/r_maxamount = 80.0//How much reagent in total there is.
+ var/s_cost = 5//Base energy cost each ntick.
+ var/s_acost = 25//Additional cost for additional powers active.
+ var/s_delay = 40//How fast the suit does certain things, lower is faster. Can be overridden in specific procs. Also determines adverse probability.
+ var/a_transfer = 20//How much reagent is transferred when injecting.
+ var/r_maxamount = 80//How much reagent in total there is.
//Support function variables.
var/spideros = 0//Mode of SpiderOS. This can change so I won't bother listing the modes here (0 is hub). Check ninja_equipment.dm for how it all works.
@@ -51,8 +51,8 @@ Contents:
var/s_busy = 0//Is the suit busy with a process? Like AI hacking. Used for safety functions.
//Ability function variables.
- var/s_bombs = 10.0//Number of starting ninja smoke bombs.
- var/a_boost = 3.0//Number of adrenaline boosters.
+ var/s_bombs = 10//Number of starting ninja smoke bombs.
+ var/a_boost = 3//Number of adrenaline boosters.
/obj/item/clothing/suit/space/space_ninja/New()
@@ -86,7 +86,7 @@ Contents:
/obj/item/clothing/suit/space/space_ninja/Destroy()
if(affecting)
affecting << browse(null, "window=hack spideros")
- ..()
+ return ..()
//Simply deletes all the attachments and self, killing all related procs.
diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm
index 46ddcd420fd..8cb5ae8902c 100644
--- a/code/modules/paperwork/clipboard.dm
+++ b/code/modules/paperwork/clipboard.dm
@@ -4,7 +4,7 @@
icon_state = "clipboard"
item_state = "clipboard"
throwforce = 0
- w_class = 2.0
+ w_class = 2
throw_speed = 3
throw_range = 7
var/obj/item/weapon/pen/haspen //The stored pen.
diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm
index 09a345c0b3c..afbbe58bacb 100644
--- a/code/modules/paperwork/handlabeler.dm
+++ b/code/modules/paperwork/handlabeler.dm
@@ -68,4 +68,4 @@
desc = "A roll of paper. Use it on a hand labeler to refill it."
icon_state = "labeler_refill"
item_state = "electropack"
- w_class = 1.0
\ No newline at end of file
+ w_class = 1
\ No newline at end of file
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 411f5de8522..8dc2bf834cd 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -11,7 +11,7 @@
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "paper"
throwforce = 0
- w_class = 1.0
+ w_class = 1
throw_range = 1
throw_speed = 1
layer = 3
@@ -51,7 +51,11 @@
/obj/item/weapon/paper/examine(mob/user)
..()
- if(in_range(user, src))
+ if(istype(src, /obj/item/weapon/paper/talisman)) //Talismans cannot be read
+ if(!iscultist(user) && !user.stat)
+ user << "There are indecipherable images scrawled on the paper in what looks to be... blood?"
+ return
+ if(in_range(user, src) || isobserver(user))
if( !(ishuman(user) || isobserver(user) || issilicon(user)) )
user << browse("[name][stars(info)][stamps]", "window=[name]")
onclose(user, "[name]")
@@ -82,6 +86,9 @@
name = "paper[(n_name ? text("- '[n_name]'") : null)]"
add_fingerprint(usr)
+/obj/item/weapon/paper/suicide_act(mob/user)
+ user.visible_message("[user] scratches a grid on their wrist with the paper! It looks like \he's trying to commit sudoku..")
+ return (BRUTELOSS)
/obj/item/weapon/paper/attack_self(mob/user)
user.examinate(src)
@@ -286,6 +293,9 @@
else
user << "You don't know how to read or write."
return
+ if(istype(src, /obj/item/weapon/paper/talisman/))
+ user << "[P]'s ink fades away shortly after it is written."
+ return
else if(istype(P, /obj/item/weapon/stamp))
if(!in_range(src, usr) && loc != user && !istype(loc, /obj/item/weapon/clipboard) && loc.loc != user && user.get_active_hand() != P)
@@ -306,7 +316,7 @@
user << "You stamp the paper with your rubber stamp."
- if(is_hot(P))
+ if(P.is_hot())
if(user.disabilities & CLUMSY && prob(10))
user.visible_message("[user] accidentally ignites themselves!", \
"You miss the paper and accidentally light yourself on fire!")
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 6e0f9b5e979..414aaba7db2 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -3,6 +3,7 @@
* Pens
* Sleepy Pens
* Parapens
+ * Edaggers
*/
@@ -17,7 +18,7 @@
item_state = "pen"
slot_flags = SLOT_BELT | SLOT_EARS
throwforce = 0
- w_class = 1.0
+ w_class = 1
throw_speed = 3
throw_range = 7
materials = list(MAT_METAL=10)
@@ -48,13 +49,17 @@
if(!istype(M))
return
- if(M.can_inject(user, 1))
- user << "You stab [M] with the pen."
- if(!stealth)
- M << "You feel a tiny prick!"
- . = 1
+ if(!force)
+ if(M.can_inject(user, 1))
+ user << "You stab [M] with the pen."
+ if(!stealth)
+ M << "You feel a tiny prick!"
+ . = 1
- add_logs(user, M, "stabbed", src)
+ add_logs(user, M, "stabbed", src)
+
+ else
+ . = ..()
/*
* Sleepypens
@@ -78,3 +83,42 @@
reagents.add_reagent("mutetoxin", 15)
reagents.add_reagent("tirizene", 10)
..()
+
+/*
+ * (Alan) Edaggers
+ */
+/obj/item/weapon/pen/edagger
+ origin_tech = "combat=3;syndicate=5"
+ attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") //these wont show up if the pen is off
+ var/on = 0
+
+/obj/item/weapon/pen/edagger/attack_self(mob/living/user)
+ if(on)
+ on = 0
+ force = initial(force)
+ w_class = initial(w_class)
+ name = initial(name)
+ hitsound = initial(hitsound)
+ embed_chance = initial(embed_chance)
+ throwforce = initial(throwforce)
+ playsound(user, 'sound/weapons/saberoff.ogg', 5, 1)
+ user << "[src] can now be concealed."
+ else
+ on = 1
+ force = 18
+ w_class = 3
+ name = "energy dagger"
+ hitsound = 'sound/weapons/blade1.ogg'
+ embed_chance = 100 //rule of cool
+ throwforce = 35
+ playsound(user, 'sound/weapons/saberon.ogg', 5, 1)
+ user << "[src] is now active."
+ update_icon()
+
+/obj/item/weapon/pen/edagger/update_icon()
+ if(on)
+ icon_state = "edagger"
+ item_state = "edagger"
+ else
+ icon_state = initial(icon_state) //looks like a normal pen when off.
+ item_state = initial(item_state)
diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm
index 770673d47bb..835b33b40fb 100644
--- a/code/modules/paperwork/photography.dm
+++ b/code/modules/paperwork/photography.dm
@@ -16,7 +16,7 @@
desc = "A camera film cartridge. Insert it into a camera to reload it."
icon_state = "film"
item_state = "electropack"
- w_class = 1.0
+ w_class = 1
burn_state = 0 //Burnable
/*
@@ -27,7 +27,7 @@
icon = 'icons/obj/items.dmi'
icon_state = "photo"
item_state = "paper"
- w_class = 1.0
+ w_class = 1
burn_state = 0 //Burnable
burntime = 5
var/icon/img //Big photo image
@@ -105,7 +105,7 @@
desc = "A polaroid camera."
icon_state = "camera"
item_state = "electropack"
- w_class = 2.0
+ w_class = 2
flags = CONDUCT
slot_flags = SLOT_BELT
materials = list(MAT_METAL=2000)
@@ -131,6 +131,8 @@
set name = "Print Image"
set src in usr
+ if(usr.stat == DEAD)
+ return //won't work if dead
borgprint()
/obj/item/device/camera/attack(mob/living/carbon/human/M, mob/user)
diff --git a/code/modules/paperwork/stamps.dm b/code/modules/paperwork/stamps.dm
index 3fb4af902ad..36204ae1fc6 100644
--- a/code/modules/paperwork/stamps.dm
+++ b/code/modules/paperwork/stamps.dm
@@ -5,7 +5,7 @@
icon_state = "stamp-ok"
item_state = "stamp"
throwforce = 0
- w_class = 1.0
+ w_class = 1
throw_speed = 3
throw_range = 7
materials = list(MAT_METAL=60)
diff --git a/code/modules/power/antimatter/containment_jar.dm b/code/modules/power/antimatter/containment_jar.dm
index ff2d0043c42..decc6ab5498 100644
--- a/code/modules/power/antimatter/containment_jar.dm
+++ b/code/modules/power/antimatter/containment_jar.dm
@@ -17,18 +17,18 @@
/obj/item/weapon/am_containment/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
explosion(get_turf(src), 1, 2, 3, 5)//Should likely be larger but this works fine for now I guess
if(src)
qdel(src)
- if(2.0)
+ if(2)
if(prob((fuel/10)-stability))
explosion(get_turf(src), 1, 2, 3, 5)
if(src)
qdel(src)
return
stability -= 40
- if(3.0)
+ if(3)
stability -= 20
//check_stability()
return
diff --git a/code/modules/power/antimatter/control.dm b/code/modules/power/antimatter/control.dm
index 41be20dc92f..dd3bd7bd464 100644
--- a/code/modules/power/antimatter/control.dm
+++ b/code/modules/power/antimatter/control.dm
@@ -38,7 +38,7 @@
/obj/machinery/power/am_control_unit/Destroy()//Perhaps damage and run stability checks rather than just del on the others
for(var/obj/machinery/am_shielding/AMS in linked_shielding)
qdel(AMS)
- ..()
+ return ..()
/obj/machinery/power/am_control_unit/process()
diff --git a/code/modules/power/antimatter/shielding.dm b/code/modules/power/antimatter/shielding.dm
index 1631f501fa7..562b63310f7 100644
--- a/code/modules/power/antimatter/shielding.dm
+++ b/code/modules/power/antimatter/shielding.dm
@@ -68,7 +68,7 @@
if(processing) shutdown_core()
visible_message("The [src.name] melts!")
//Might want to have it leave a mess on the floor but no sprites for now
- ..()
+ return ..()
/obj/machinery/am_shielding/CanPass(atom/movable/mover, turf/target, height=0)
@@ -196,7 +196,7 @@
icon = 'icons/obj/machines/antimatter.dmi'
icon_state = "box"
item_state = "electronic"
- w_class = 4.0
+ w_class = 4
flags = CONDUCT
throwforce = 5
throw_speed = 1
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index cc411f25092..e22dae496c1 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -152,12 +152,13 @@
area.power_change()
if(occupier)
malfvacate(1)
- del(wires)
+ qdel(wires)
+ wires = null
if(cell)
qdel(cell)
if(terminal)
disconnect_terminal()
- ..()
+ return ..()
/obj/machinery/power/apc/proc/make_terminal()
// create a terminal object at the same position as original turf loc
@@ -172,7 +173,7 @@
if(cell_type)
src.cell = new/obj/item/weapon/stock_parts/cell(src)
cell.maxcharge = cell_type // cell_type is maximum charge (old default was 1000 or 2500 (values one and two respectively)
- cell.charge = start_charge * cell.maxcharge / 100.0 // (convert percentage to actual value)
+ cell.charge = start_charge * cell.maxcharge / 100 // (convert percentage to actual value)
var/area/A = src.loc.loc
@@ -398,7 +399,7 @@
user.visible_message(\
"[user.name] has removed the power control board from [src.name]!",\
"You remove the power control board.")
- new /obj/item/weapon/module/power_control(loc)
+ new /obj/item/weapon/electronics/apc(loc)
else if (opened!=2) //cover isn't removed
opened = 0
update_icon()
@@ -496,7 +497,7 @@
else if (istype(W, /obj/item/weapon/wirecutters) && terminal && opened && has_electronics!=2)
terminal.dismantle(user)
- else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && !((stat & BROKEN) || malfhack))
+ else if (istype(W, /obj/item/weapon/electronics/apc) && opened && has_electronics==0 && !((stat & BROKEN) || malfhack))
user.visible_message("[user.name] inserts the power control board into [src].", \
"You start to insert the power control board into the frame...")
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
@@ -505,7 +506,7 @@
has_electronics = 1
user << "You place the power control board inside the frame."
qdel(W)
- else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && ((stat & BROKEN) || malfhack))
+ else if (istype(W, /obj/item/weapon/electronics/apc) && opened && has_electronics==0 && ((stat & BROKEN) || malfhack))
user << "You cannot put the board inside, the frame is damaged!"
return
else if (istype(W, /obj/item/weapon/weldingtool) && opened && has_electronics==0 && !terminal)
@@ -525,13 +526,13 @@
"[user.name] has cut [src] apart with [W].",\
"You disassembled the broken APC frame.")
else
- new /obj/item/apc_frame(loc)
+ new /obj/item/wallframe/apc(loc)
user.visible_message(\
"[user.name] has cut [src] from the wall with [W].",\
"You cut the APC frame from the wall.")
qdel(src)
return
- else if (istype(W, /obj/item/apc_frame) && opened && emagged)
+ else if (istype(W, /obj/item/wallframe/apc) && opened && emagged)
emagged = 0
if (opened==2)
opened = 1
@@ -540,7 +541,7 @@
"You replace the damaged APC frontal panel with a new one.")
qdel(W)
update_icon()
- else if (istype(W, /obj/item/apc_frame) && opened && ((stat & BROKEN) || malfhack))
+ else if (istype(W, /obj/item/wallframe/apc) && opened && ((stat & BROKEN) || malfhack))
if (has_electronics)
user << "You cannot repair this APC until you remove the electronics still inside!"
return
@@ -559,7 +560,7 @@
if ( ((stat & BROKEN) || malfhack) \
&& !opened \
&& W.force >= 5 \
- && W.w_class >= 3.0 \
+ && W.w_class >= 3 \
&& prob(20) )
opened = 2
user.visible_message("[user.name] has knocked down the APC cover with the [W.name].", \
@@ -569,9 +570,7 @@
else
if (istype(user, /mob/living/silicon))
return src.attack_hand(user)
- if (!opened && wiresexposed && \
- (istype(W, /obj/item/device/multitool) || \
- istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/assembly/signaler)))
+ if (!opened && wiresexposed && wires.IsInteractionTool(W))
return src.attack_hand(user)
..()
@@ -1232,15 +1231,7 @@
#undef APC_UPDATE_ICON_COOLDOWN
/*Power module, used for APC construction*/
-/obj/item/weapon/module
- icon = 'icons/obj/module.dmi'
- icon_state = "std_module"
- w_class = 2.0
- item_state = "electronic"
- flags = CONDUCT
-
-
-/obj/item/weapon/module/power_control
+/obj/item/weapon/electronics/apc
name = "power control module"
icon_state = "power_mod"
desc = "Heavy-duty switching circuits for power control."
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index 4e380448a3f..35f77d258e8 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -90,7 +90,7 @@ By design, d1 is the smallest direction and d2 is the highest
if(powernet)
cut_cable_from_powernet() // update the powernets
cable_list -= src //remove it from global cable list
- ..() // then go ahead and delete the cable
+ return ..() // then go ahead and delete the cable
/obj/structure/cable/Deconstruct()
var/turf/T = loc
@@ -162,7 +162,7 @@ By design, d1 is the smallest direction and d2 is the highest
src.add_fingerprint(user)
// shock the user with probability prb
-/obj/structure/cable/proc/shock(mob/user, prb, siemens_coeff = 1.0)
+/obj/structure/cable/proc/shock(mob/user, prb, siemens_coeff = 1)
if(!prob(prb))
return 0
if (electrocute_mob(user, powernet, src, siemens_coeff))
@@ -432,12 +432,15 @@ By design, d1 is the smallest direction and d2 is the highest
P.disconnect_from_network() //remove from current network (and delete powernet)
return
+ var/obj/O = P_list[1]
// remove the cut cable from its turf and powernet, so that it doesn't get count in propagate_network worklist
loc = null
powernet.remove_cable(src) //remove the cut cable from its powernet
- var/datum/powernet/newPN = new()// creates a new powernet...
- propagate_network(P_list[1], newPN)//... and propagates it to the other side of the cable
+ spawn(0) //so we don't rebuild the network X times when singulo/explosion destroys a line of X cables
+ if(O && !qdeleted(O))
+ var/datum/powernet/newPN = new()// creates a new powernet...
+ propagate_network(O, newPN)//... and propagates it to the other side of the cable
// Disconnect machines connected to nodes
if(d1 == 0) // if we cut a node (O-X) cable
@@ -463,11 +466,12 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list ( \
icon = 'icons/obj/power.dmi'
icon_state = "coil_red"
item_state = "coil_red"
+ max_amount = MAXCOIL
amount = MAXCOIL
item_color = "red"
desc = "A coil of power cable."
throwforce = 0
- w_class = 2.0
+ w_class = 2
throw_speed = 3
throw_range = 5
materials = list(MAT_METAL=50, MAT_GLASS=20)
@@ -536,44 +540,16 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list ( \
icon_state = "coil_[item_color]"
name = "cable coil"
-
-// Items usable on a cable coil :
-// - Cable coil : merge cables
-/obj/item/stack/cable_coil/attackby(obj/item/weapon/W, mob/user, params)
- ..()
- if(istype(W, /obj/item/stack/cable_coil/cyborg))
- var/obj/item/stack/cable_coil/cyborg/C = W
- var/to_transfer = min(src.amount, round((C.source.max_energy - C.source.energy) / C.cost))
- C.add(to_transfer)
- src.use(to_transfer)
- else if(istype(W, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/C = W
- if(C.amount >= MAXCOIL)
- user << "The coil is too long, you cannot add any more cable to it!"
- return
-
- if( (C.amount + src.amount <= MAXCOIL) )
- user << "You join the cable coils together."
- C.give(src.amount) // give it cable
- src.use(src.amount) // make sure this one cleans up right
- return
-
- else
- var/amt = MAXCOIL - C.amount
- user << "You transfer [amt] length\s of cable from one coil to the other."
- C.give(amt)
- src.use(amt)
- return
-
-/obj/item/stack/cable_coil/use(used)
- . = ..()
- update_icon()
- return
+/obj/item/stack/cable_coil/attack_hand(mob/user)
+ var/obj/item/stack/cable_coil/new_cable = ..()
+ if(istype(new_cable))
+ new_cable.item_color = item_color
+ new_cable.update_icon()
//add cables to the stack
/obj/item/stack/cable_coil/proc/give(extra)
- if(amount + extra > MAXCOIL)
- amount = MAXCOIL
+ if(amount + extra > max_amount)
+ amount = max_amount
else
amount += extra
update_icon()
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index b99735503ee..7900a52ba01 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -5,8 +5,8 @@
icon_state = "cell"
item_state = "cell"
origin_tech = "powerstorage=1"
- force = 5.0
- throwforce = 5.0
+ force = 5
+ throwforce = 5
throw_speed = 2
throw_range = 5
w_class = 2
@@ -33,7 +33,7 @@
overlays += image('icons/obj/power.dmi', "cell-o1")
/obj/item/weapon/stock_parts/cell/proc/percent() // return % charge of cell
- return 100.0*charge/maxcharge
+ return 100*charge/maxcharge
// use power from a cell
/obj/item/weapon/stock_parts/cell/proc/use(amount)
@@ -43,7 +43,7 @@
if(charge < amount) return 0
charge = (charge - amount)
if(!istype(loc, /obj/machinery/power/apc))
- feedback_add_details("cell_used","[src.name]")
+ feedback_add_details("cell_used","[src.type]")
return 1
// recharge the cell
@@ -165,9 +165,9 @@
..()
charge = 0
-/obj/item/weapon/stock_parts/cell/pulse //80 pulse shots
+/obj/item/weapon/stock_parts/cell/pulse //200 pulse shots
name = "pulse rifle power cell"
- maxcharge = 16000
+ maxcharge = 40000
rating = 3
chargerate = 1500
diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm
index 60846ab54bb..60ef879bdf4 100644
--- a/code/modules/power/generator.dm
+++ b/code/modules/power/generator.dm
@@ -106,11 +106,11 @@
// update icon overlays only if displayed level has changed
if(hot_air)
- var/datum/gas_mixture/circ2_air1 = circ2.airs["a1"]
+ var/datum/gas_mixture/circ2_air1 = circ2.AIR1
circ2_air1.merge(hot_air)
if(cold_air)
- var/datum/gas_mixture/circ1_air1 = circ1.airs["a1"]
+ var/datum/gas_mixture/circ1_air1 = circ1.AIR1
circ1_air1.merge(cold_air)
var/genlev = max(0, min( round(11*lastgen / 100000), 11))
@@ -133,10 +133,10 @@
if(!powernet)
t += "Unable to connect to the power network!"
else if(circ1 && circ2)
- var/datum/gas_mixture/circ1_air1 = circ1.airs["a1"]
- var/datum/gas_mixture/circ1_air2 = circ1.airs["a2"]
- var/datum/gas_mixture/circ2_air1 = circ2.airs["a1"]
- var/datum/gas_mixture/circ2_air2 = circ2.airs["a2"]
+ var/datum/gas_mixture/circ1_air1 = circ1.AIR1
+ var/datum/gas_mixture/circ1_air2 = circ1.AIR2
+ var/datum/gas_mixture/circ2_air1 = circ2.AIR1
+ var/datum/gas_mixture/circ2_air2 = circ2.AIR2
t += "
"
diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm
index be09fdadd38..8eb7af7db8f 100644
--- a/code/modules/power/gravitygenerator.dm
+++ b/code/modules/power/gravitygenerator.dm
@@ -58,7 +58,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
set_broken()
if(main_part)
qdel(main_part)
- ..()
+ return ..()
//
// Part generator which is mostly there for looks
@@ -126,7 +126,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
for(var/obj/machinery/gravity_generator/part/O in parts)
O.main_part = null
qdel(O)
- ..()
+ return ..()
/obj/machinery/gravity_generator/main/proc/setup_parts()
var/turf/our_turf = get_turf(src)
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 145f2b2ba84..ab40d011b4b 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -11,61 +11,20 @@
-/obj/item/light_fixture_frame
+/obj/item/wallframe/light_fixture
name = "light fixture frame"
desc = "Used for building lights."
icon = 'icons/obj/lighting.dmi'
icon_state = "tube-construct-item"
- flags = CONDUCT
- var/fixture_type = "tube"
- var/obj/machinery/light/newlight = null
- var/sheets_refunded = 2
+ result_path = /obj/machinery/light_construct
+ inverse = 1
-/obj/item/light_fixture_frame/attackby(obj/item/weapon/W, mob/user, params)
- if (istype(W, /obj/item/weapon/wrench))
- new /obj/item/stack/sheet/metal( get_turf(src.loc), sheets_refunded )
- qdel(src)
- return
- ..()
-
-/obj/item/light_fixture_frame/proc/try_build(turf/on_wall)
- if (get_dist(on_wall,usr)>1)
- return
- var/ndir = get_dir(usr,on_wall)
- if (!(ndir in cardinal))
- return
- var/turf/loc = get_turf(usr)
- if (!istype(loc, /turf/simulated/floor))
- usr << "[src.name] cannot be placed on this spot!"
- return
- usr << "You begin attaching [src] to the wall..."
- playsound(src.loc, 'sound/machines/click.ogg', 75, 1)
- var/constrdir = usr.dir
- var/constrloc = usr.loc
- if (!do_after(usr, 30, target = src))
- return
- switch(fixture_type)
- if("bulb")
- newlight = new /obj/machinery/light_construct/small(constrloc)
- if("tube")
- newlight = new /obj/machinery/light_construct(constrloc)
- newlight.dir = constrdir
- newlight.fingerprints = src.fingerprints
- newlight.fingerprintshidden = src.fingerprintshidden
- newlight.fingerprintslast = src.fingerprintslast
-
- usr.visible_message("[usr.name] attaches [src] to the wall.", \
- "You attach [src] to the wall.")
- qdel(src)
-
-/obj/item/light_fixture_frame/small
+/obj/item/wallframe/light_fixture/small
name = "small light fixture frame"
- desc = "Used for building small lights."
- icon = 'icons/obj/lighting.dmi'
icon_state = "bulb-construct-item"
- flags = CONDUCT
- fixture_type = "bulb"
- sheets_refunded = 1
+ result_path = /obj/machinery/light_construct/small
+ materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT)
+
/obj/machinery/light_construct
name = "light fixture frame"
@@ -79,10 +38,10 @@
var/sheets_refunded = 2
var/obj/machinery/light/newlight = null
-/obj/machinery/light_construct/New()
+/obj/machinery/light_construct/New(loc, ndir, building)
..()
- if (fixture_type == "bulb")
- icon_state = "bulb-construct-stage1"
+ if(building)
+ dir = ndir
/obj/machinery/light_construct/examine(mob/user)
..()
@@ -172,12 +131,7 @@
/obj/machinery/light_construct/small
name = "small light fixture frame"
- desc = "A small light fixture under construction."
- icon = 'icons/obj/lighting.dmi'
icon_state = "bulb-construct-stage1"
- anchored = 1
- layer = 5
- stage = 1
fixture_type = "bulb"
sheets_refunded = 1
@@ -254,7 +208,7 @@
if(A)
on = 0
// A.update_lights()
- ..()
+ return ..()
/obj/machinery/light/update_icon()
@@ -379,7 +333,6 @@
"You hit the light, and it smashes!", \
"You hear a tinkle of breaking glass.")
if(on && (W.flags & CONDUCT))
- //if(!user.mutations & COLD_RESISTANCE)
if (prob(12))
electrocute_mob(user, get_area(src), src, 0.3)
broken()
@@ -415,7 +368,6 @@
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
- //if(!user.mutations & COLD_RESISTANCE)
if (prob(75))
electrocute_mob(user, get_area(src), src, rand(0.7,1.0))
diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm
index 37a75156cc8..8f295db3f3e 100644
--- a/code/modules/power/port_gen.dm
+++ b/code/modules/power/port_gen.dm
@@ -97,7 +97,7 @@ display round(lastgen) and plasmatank amount
var/board_path = "/obj/item/weapon/circuitboard/pacman"
var/sheet_left = 0 // How much is left of the sheet
var/time_per_sheet = 260
- var/heat = 0
+ var/current_heat = 0
/obj/machinery/power/port_gen/pacman/initialize()
..()
@@ -119,7 +119,7 @@ display round(lastgen) and plasmatank amount
/obj/machinery/power/port_gen/pacman/Destroy()
DropFuel()
- ..()
+ return ..()
/obj/machinery/power/port_gen/pacman/RefreshParts()
var/temp_rating = 0
@@ -171,24 +171,24 @@ display round(lastgen) and plasmatank amount
if (power_output > 4)
upper_limit = 400
bias = power_output - consumption * (4 - consumption)
- if (heat < lower_limit)
- heat += 4 - consumption
+ if (current_heat < lower_limit)
+ current_heat += 4 - consumption
else
- heat += rand(-7 + bias, 7 + bias)
- if (heat < lower_limit)
- heat = lower_limit
- if (heat > upper_limit)
- heat = upper_limit
+ current_heat += rand(-7 + bias, 7 + bias)
+ if (current_heat < lower_limit)
+ current_heat = lower_limit
+ if (current_heat > upper_limit)
+ current_heat = upper_limit
- if (heat > 300)
+ if (current_heat > 300)
overheat()
qdel(src)
return
/obj/machinery/power/port_gen/pacman/handleInactive()
- if (heat > 0)
- heat = max(heat - 2, 0)
+ if (current_heat > 0)
+ current_heat = max(current_heat - 2, 0)
src.updateDialog()
/obj/machinery/power/port_gen/pacman/proc/overheat()
@@ -271,7 +271,7 @@ display round(lastgen) and plasmatank amount
dat += text("Current stack: [stack_percent]% ")
dat += text("Power output: - [power_gen * power_output] + ")
dat += text("Power current: [(powernet == null ? "Unconnected" : "[avail()]")] ")
- dat += text("Heat: [heat] ")
+ dat += text("Heat: [current_heat] ")
dat += " Close"
user << browse("[dat]", "window=port_gen")
onclose(user, "port_gen")
diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm
index 1fbca84583c..213b288b724 100644
--- a/code/modules/power/power.dm
+++ b/code/modules/power/power.dm
@@ -9,7 +9,7 @@
/obj/machinery/power
name = null
icon = 'icons/obj/power.dmi'
- anchored = 1.0
+ anchored = 1
var/datum/powernet/powernet = null
use_power = 0
idle_power_usage = 0
@@ -17,7 +17,7 @@
/obj/machinery/power/Destroy()
disconnect_from_network()
- ..()
+ return ..()
///////////////////////////////
// General procedures
@@ -280,7 +280,7 @@
//power_source is a source of electricity, can be powercell, area, apc, cable, powernet or null
//source is an object caused electrocuting (airlock, grille, etc)
//No animations will be performed by this proc.
-/proc/electrocute_mob(mob/living/carbon/M, power_source, obj/source, siemens_coeff = 1.0)
+/proc/electrocute_mob(mob/living/carbon/M, power_source, obj/source, siemens_coeff = 1)
if(istype(M.loc,/obj/mecha)) return 0 //feckin mechs are dumb
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
diff --git a/code/modules/power/powernet.dm b/code/modules/power/powernet.dm
index 0ad877f987d..f8e8826294d 100644
--- a/code/modules/power/powernet.dm
+++ b/code/modules/power/powernet.dm
@@ -26,6 +26,7 @@
M.powernet = null
SSmachine.powernets -= src
+ return ..()
/datum/powernet/proc/is_empty()
return !cables.len && !nodes.len
diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm
index 3687d237bd2..aab80c9e97f 100644
--- a/code/modules/power/singularity/collector.dm
+++ b/code/modules/power/singularity/collector.dm
@@ -22,7 +22,7 @@ var/global/list/rad_collectors = list()
/obj/machinery/power/rad_collector/Destroy()
rad_collectors -= src
- ..()
+ return ..()
/obj/machinery/power/rad_collector/process()
if(P)
diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm
index 08278a00ea7..7fc737afb46 100644
--- a/code/modules/power/singularity/containment_field.dm
+++ b/code/modules/power/singularity/containment_field.dm
@@ -19,7 +19,7 @@
FG1.cleanup()
if(FG2 && !FG2.clean_up)
FG2.cleanup()
- ..()
+ return ..()
/obj/machinery/field/containment/attack_hand(mob/user)
if(get_dist(src, user) > 1)
diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm
index 23e6468096f..95cec63ff84 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/modules/power/singularity/emitter.dm
@@ -2,7 +2,7 @@
/obj/machinery/power/emitter
name = "Emitter"
- desc = "A heavy duty industrial laser"
+ desc = "A heavy duty industrial laser.\nAlt-click to rotate it clockwise."
icon = 'icons/obj/singularity.dmi'
icon_state = "emitter"
anchored = 0
@@ -57,9 +57,19 @@
if (src.anchored)
usr << "It is fastened to the floor!"
return 0
- src.dir = turn(src.dir, 90)
+ src.dir = turn(src.dir, 270)
return 1
+/obj/machinery/power/emitter/AltClick(mob/user)
+ ..()
+ if(!user.canUseTopic(user))
+ user << "You can't do that right now!"
+ return
+ if(!in_range(src, user))
+ return
+ else
+ rotate()
+
/obj/machinery/power/emitter/initialize()
..()
if(state == 2 && anchored)
@@ -70,7 +80,7 @@
message_admins("Emitter deleted at ([x],[y],[z] - JMP)",0,1)
log_game("Emitter deleted at ([x],[y],[z])")
investigate_log("deleted at ([x],[y],[z])","singulo")
- ..()
+ return ..()
/obj/machinery/power/emitter/update_icon()
if (active && powernet && avail(active_power_usage))
@@ -181,7 +191,8 @@
user << "Turn off \the [src] first!"
return
switch(state)
- if(0 && !isinspace())
+ if(0)
+ if(isinspace()) return
state = 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
user.visible_message("[user.name] secures [src.name] to the floor.", \
@@ -264,4 +275,5 @@
if(!emagged)
locked = 0
emagged = 1
- user.visible_message("[user.name] emags the [src.name].","You short out the lock.")
+ if(user)
+ user.visible_message("[user.name] emags the [src.name].","You short out the lock.")
diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm
index 550567bca53..857741045c9 100644
--- a/code/modules/power/singularity/field_generator.dm
+++ b/code/modules/power/singularity/field_generator.dm
@@ -100,7 +100,8 @@ field_generator power level display
return
else if(istype(W, /obj/item/weapon/wrench))
switch(state)
- if(0 && !isinspace())
+ if(0)
+ if(isinspace()) return
state = 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
user.visible_message("[user.name] secures [src.name] to the floor.", \
@@ -171,7 +172,7 @@ field_generator power level display
/obj/machinery/field/generator/Destroy()
src.cleanup()
- ..()
+ return ..()
diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm
index bbfa406ad58..f991cfc8478 100644
--- a/code/modules/power/singularity/narsie.dm
+++ b/code/modules/power/singularity/narsie.dm
@@ -25,7 +25,7 @@
/obj/singularity/narsie/large/New()
..()
world << "NAR-SIE HAS RISEN"
- world << pick(sound('sound/hallucinations/im_here1.ogg'), sound('sound/hallucinations/im_here2.ogg'))
+ world << 'sound/effects/narsie.ogg'
var/area/A = get_area(src)
if(A)
@@ -65,7 +65,7 @@
/obj/singularity/narsie/proc/godsmack(atom/A)
if(istype(A,/obj/))
var/obj/O = A
- O.ex_act(1.0)
+ O.ex_act(1)
if(O) qdel(O)
else if(isturf(A))
@@ -77,7 +77,7 @@
for(var/mob/living/carbon/M in oviewers(8, src))
if(M.stat == CONSCIOUS)
if(!iscultist(M))
- M << "You feel your sanity crumble away in an instant as you gaze upon [src.name]..."
+ M << "You feel conscious thought crumble away in an instant as you gaze upon [src.name]..."
M.apply_effect(3, STUN)
diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
index 18a04d16f32..30ee59ac72e 100644
--- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
+++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
@@ -71,11 +71,15 @@ So, hopefully this is helpful if any more icons are to be added/changed/wonderin
var/strength = null
var/desc_holder = null
+/obj/structure/particle_accelerator/examine(mob/user)
+ ..()
+ user << "Alt-click to rotate it clockwise."
+
/obj/structure/particle_accelerator/Destroy()
construction_state = 0
if(master)
master.part_scan()
- ..()
+ return ..()
/obj/structure/particle_accelerator/end_cap
name = "Alpha Particle Generation Array"
@@ -101,6 +105,16 @@ So, hopefully this is helpful if any more icons are to be added/changed/wonderin
src.dir = turn(src.dir, 270)
return 1
+/obj/structure/particle_accelerator/AltClick(mob/user)
+ ..()
+ if(!user.canUseTopic(user))
+ user << "You can't do that right now!"
+ return
+ if(!in_range(src, user))
+ return
+ else
+ rotate()
+
/obj/structure/particle_accelerator/verb/rotateccw()
set name = "Rotate Counter Clockwise"
set category = "Object"
diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm
index 61fd8dbe424..228dd2789d8 100644
--- a/code/modules/power/singularity/particle_accelerator/particle_control.dm
+++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm
@@ -29,7 +29,9 @@
/obj/machinery/particle_accelerator/control_box/Destroy()
if(active)
toggle_power()
- ..()
+ qdel(wires)
+ wires = null
+ return ..()
/obj/machinery/particle_accelerator/control_box/attack_hand(mob/user)
if(construction_state >= 3)
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index ce2e87d82da..b9578936e24 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -42,7 +42,7 @@
/obj/singularity/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/singularity/Move(atom/newloc, direct)
if(current_size >= STAGE_FIVE || check_turfs_in(direct))
@@ -65,16 +65,16 @@
/obj/singularity/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
if(current_size <= STAGE_TWO)
investigate_log("has been destroyed by a heavy explosion.","singulo")
qdel(src)
return
else
energy -= round(((energy+1)/2),1)
- if(2.0)
+ if(2)
energy -= round(((energy+1)/3),1)
- if(3.0)
+ if(3)
energy -= round(((energy+1)/4),1)
return
diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm
index 3bc6dbcfc36..fe60d38873c 100644
--- a/code/modules/power/smes.dm
+++ b/code/modules/power/smes.dm
@@ -159,6 +159,9 @@
//crowbarring it !
default_deconstruction_crowbar(I)
+ message_admins("[src] has been deconstructed by [key_name_admin(user)](?) (FLW) in ([x],[y],[z] - JMP)",0,1)
+ log_game("[src] has been deconstructed by [key_name(user)]")
+ investigate_log("SMES deconstructed by [key_name(user)]","singulo")
/obj/machinery/power/smes/Destroy()
if(ticker && ticker.current_state == GAME_STATE_PLAYING)
@@ -168,7 +171,7 @@
investigate_log("deleted at ([area.name])","singulo")
if(terminal)
disconnect_terminal()
- ..()
+ return ..()
// create a terminal object pointing towards the SMES
// wires will attach to this
@@ -331,7 +334,7 @@
/obj/machinery/power/smes/get_ui_data()
var/list/data = list(
- "capacityPercent" = round(100.0*charge/capacity, 0.1),
+ "capacityPercent" = round(100*charge/capacity, 0.1),
"capacity" = capacity,
"charge" = charge,
diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm
index ab650dfa411..cbc325ef706 100644
--- a/code/modules/power/solar.dm
+++ b/code/modules/power/solar.dm
@@ -27,7 +27,7 @@
/obj/machinery/power/solar/Destroy()
unset_control() //remove from control computer
- ..()
+ return ..()
//set the control of the panel to a given computer if closer than SOLAR_MAX_DIST
/obj/machinery/power/solar/proc/set_control(obj/machinery/power/solar_control/SC)
@@ -255,7 +255,7 @@
return 1
if(!tracker)
- if(istype(W, /obj/item/weapon/tracker_electronics))
+ if(istype(W, /obj/item/weapon/electronics/tracker))
if(!user.drop_item())
return
tracker = 1
@@ -264,7 +264,7 @@
return 1
else
if(istype(W, /obj/item/weapon/crowbar))
- new /obj/item/weapon/tracker_electronics(src.loc)
+ new /obj/item/weapon/electronics/tracker(src.loc)
tracker = 0
user.visible_message("[user] takes out the electronics from the solar assembly.", "You take out the electronics from the solar assembly.")
return 1
@@ -308,7 +308,7 @@
M.unset_control()
if(connected_tracker)
connected_tracker.unset_control()
- ..()
+ return ..()
/obj/machinery/power/solar_control/disconnect_from_network()
..()
diff --git a/code/modules/power/tracker.dm b/code/modules/power/tracker.dm
index b2771ae6d4f..874b2ca1733 100644
--- a/code/modules/power/tracker.dm
+++ b/code/modules/power/tracker.dm
@@ -23,7 +23,7 @@
/obj/machinery/power/tracker/Destroy()
unset_control() //remove from control computer
- ..()
+ return ..()
//set the control of the tracker to a given computer if closer than SOLAR_MAX_DIST
/obj/machinery/power/tracker/proc/set_control(obj/machinery/power/solar_control/SC)
@@ -76,9 +76,5 @@
// Tracker Electronic
-/obj/item/weapon/tracker_electronics
-
- name = "tracker electronics"
- icon = 'icons/obj/doors/door_assembly.dmi'
- icon_state = "door_electronics"
- w_class = 2.0
\ No newline at end of file
+/obj/item/weapon/electronics/tracker
+ name = "tracker electronics"
\ No newline at end of file
diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm
index c7bf249a611..d0fe04ce0a0 100644
--- a/code/modules/power/turbine.dm
+++ b/code/modules/power/turbine.dm
@@ -81,10 +81,12 @@
gas_contained = new
inturf = get_step(src, dir)
- spawn(5)
- locate_machinery()
- if(!turbine)
- stat |= BROKEN
+
+/obj/machinery/power/compressor/initialize()
+ ..()
+ locate_machinery()
+ if(!turbine)
+ stat |= BROKEN
#define COMPFRICTION 5e5
@@ -200,22 +202,12 @@
outturf = get_step(src, dir)
- spawn(5)
-// compressor is found in the opposite direction
-
- locate_machinery()
- if(!compressor)
- stat |= BROKEN
-
-
-// THIS MAKES IT WORK!!!!!
-
-// OLD FIX . Dunno how other engines handle this but this is how it should work: Turbine and compressor should be
-// treated as walls to avoid conductivity and gas spread. This was the problem of the original turbine which was just
-// a machinery - it didn't block the gas passage.
-// /obj/machinery/power/turbine/CanPass(atom/movable/mover, turf/target, height=0)
-// return !density
+/obj/machinery/power/turbine/initialize()
+ ..()
+ locate_machinery()
+ if(!compressor)
+ stat |= BROKEN
/obj/machinery/power/turbine/RefreshParts()
var/P = 0
@@ -350,13 +342,13 @@
-/obj/machinery/computer/turbine_computer/New()
+/obj/machinery/computer/turbine_computer/initialize()
..()
- spawn(5)
+ spawn(10)
locate_machinery()
/obj/machinery/computer/turbine_computer/locate_machinery()
- compressor = locate(/obj/machinery/power/compressor) in range(5)
+ compressor = locate(/obj/machinery/power/compressor) in range(5, src)
/obj/machinery/computer/turbine_computer/attack_hand(var/mob/user as mob)
if(..())
diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm
index 27a1309f57b..64e1e18cd1c 100644
--- a/code/modules/projectiles/ammunition.dm
+++ b/code/modules/projectiles/ammunition.dm
@@ -6,7 +6,7 @@
flags = CONDUCT
slot_flags = SLOT_BELT
throwforce = 0
- w_class = 1.0
+ w_class = 1
var/fire_sound = null //What sound should play when this ammo is fired
var/caliber = null //Which kind of guns it can be loaded into
var/projectile_type = null //The bullet type to create when New() is called
@@ -19,8 +19,8 @@
..()
if(projectile_type)
BB = new projectile_type(src)
- pixel_x = rand(-10.0, 10)
- pixel_y = rand(-10.0, 10)
+ pixel_x = rand(-10, 10)
+ pixel_y = rand(-10, 10)
dir = pick(alldirs)
update_icon()
@@ -64,7 +64,7 @@
item_state = "syringe_kit"
materials = list(MAT_METAL=30000)
throwforce = 2
- w_class = 1.0
+ w_class = 1
throw_speed = 3
throw_range = 7
var/list/stored_ammo = list()
diff --git a/code/modules/projectiles/ammunition/ammo_casings.dm b/code/modules/projectiles/ammunition/ammo_casings.dm
index 26b4bc77e99..641bae74ffe 100644
--- a/code/modules/projectiles/ammunition/ammo_casings.dm
+++ b/code/modules/projectiles/ammunition/ammo_casings.dm
@@ -13,18 +13,30 @@
caliber = "38"
projectile_type = /obj/item/projectile/bullet/weakbullet2
-
/obj/item/ammo_casing/c10mm
desc = "A 10mm bullet casing."
caliber = "10mm"
projectile_type = /obj/item/projectile/bullet/midbullet3
-
/obj/item/ammo_casing/c9mm
desc = "A 9mm bullet casing."
caliber = "9mm"
projectile_type = /obj/item/projectile/bullet/weakbullet3
+/obj/item/ammo_casing/c9mmap
+ desc = "A 9mm bullet casing."
+ caliber = "9mm"
+ projectile_type =/obj/item/projectile/bullet/armourpiercing
+
+/obj/item/ammo_casing/c9mmtox
+ desc = "A 9mm bullet casing."
+ caliber = "9mm"
+ projectile_type = /obj/item/projectile/bullet/toxinbullet
+
+/obj/item/ammo_casing/c9mminc
+ desc = "A 9mm bullet casing."
+ caliber = "9mm"
+ projectile_type = /obj/item/projectile/bullet/incendiary/firebullet
/obj/item/ammo_casing/c45
desc = "A .45 bullet casing."
@@ -84,7 +96,7 @@
projectile_type = /obj/item/projectile/bullet/pellet/random
materials = list(MAT_METAL=250)
pellets = 5
- variance = 1.0
+ variance = 1
/obj/item/ammo_casing/shotgun/improvised/overload/New()
..()
diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm
index c776a60e0a4..020539c1c4d 100644
--- a/code/modules/projectiles/ammunition/magazines.dm
+++ b/code/modules/projectiles/ammunition/magazines.dm
@@ -1,101 +1,139 @@
////////////////INTERNAL MAGAZINES//////////////////////
+/obj/item/ammo_box/magazine/internal
+ desc = "Oh god, this shouldn't be here"
+
//internals magazines are accessible, so replace spent ammo if full when trying to put a live one in
/obj/item/ammo_box/magazine/internal/give_round(obj/item/ammo_casing/R)
return ..(R,1)
+
+
+// Revolver internal mags
/obj/item/ammo_box/magazine/internal/cylinder
name = "revolver cylinder"
- desc = "Oh god, this shouldn't be here"
ammo_type = /obj/item/ammo_casing/a357
caliber = "357"
max_ammo = 7
/obj/item/ammo_box/magazine/internal/cylinder/ammo_count(countempties = 1)
- if (!countempties)
- var/boolets = 0
- for (var/i = 1, i <= stored_ammo.len, i++)
- var/obj/item/ammo_casing/bullet = stored_ammo[i]
- if (bullet.BB)
- boolets++
- return boolets
- else
- return ..()
+ var/boolets = 0
+ for(var/obj/item/ammo_casing/bullet in stored_ammo)
+ if(bullet && (bullet.BB || countempties))
+ boolets++
-/obj/item/ammo_box/magazine/internal/cylinder/rus357
- name = "russian revolver cylinder"
- desc = "Oh god, this shouldn't be here"
- ammo_type = /obj/item/ammo_casing/a357
- caliber = "357"
- max_ammo = 6
- multiload = 0
+ return boolets
-/obj/item/ammo_box/magazine/internal/cylinder/rus357/New()
- stored_ammo += new ammo_type(src)
+/obj/item/ammo_box/magazine/internal/cylinder/get_round(keep = 0)
+ rotate()
+
+ var/b = stored_ammo[1]
+ if(!keep)
+ stored_ammo[1] = null
+
+ return b
+
+/obj/item/ammo_box/magazine/internal/cylinder/proc/rotate()
+ var/b = stored_ammo[1]
+ stored_ammo.Cut(1,2)
+ stored_ammo.Insert(0, b)
+
+/obj/item/ammo_box/magazine/internal/cylinder/proc/spin()
+ for(var/i in 1 to rand(0, max_ammo*2))
+ rotate()
+
+
+/obj/item/ammo_box/magazine/internal/cylinder/give_round(obj/item/ammo_casing/R, replace_spent = 0)
+ if(!R || (caliber && R.caliber != caliber) || (!caliber && R.type != ammo_type))
+ return 0
+
+ for(var/i in 1 to stored_ammo.len)
+ var/obj/item/ammo_casing/bullet = stored_ammo[i]
+ if(!bullet || !bullet.BB) // found a spent ammo
+ stored_ammo[i] = R
+ R.loc = src
+
+ if(bullet)
+ bullet.loc = get_turf(src.loc)
+ return 1
+
+ return 0
/obj/item/ammo_box/magazine/internal/cylinder/rev38
name = "d-tiv revolver cylinder"
- desc = "Oh god, this shouldn't be here"
ammo_type = /obj/item/ammo_casing/c38
caliber = "38"
max_ammo = 6
+/obj/item/ammo_box/magazine/internal/cylinder/grenademulti
+ name = "grenade launcher internal magazine"
+ ammo_type = /obj/item/ammo_casing/a40mm
+ caliber = "40mm"
+ max_ammo = 6
+
+
+// Shotgun internal mags
/obj/item/ammo_box/magazine/internal/shot
name = "shotgun internal magazine"
- desc = "Oh god, this shouldn't be here"
ammo_type = /obj/item/ammo_casing/shotgun/beanbag
caliber = "shotgun"
max_ammo = 4
multiload = 0
-/obj/item/ammo_box/magazine/internal/shotcom
+/obj/item/ammo_box/magazine/internal/shot/ammo_count(countempties = 1)
+ if (!countempties)
+ var/boolets = 0
+ for(var/obj/item/ammo_casing/bullet in stored_ammo)
+ if(bullet.BB)
+ boolets++
+ return boolets
+ else
+ return ..()
+
+/obj/item/ammo_box/magazine/internal/shot/com
name = "combat shotgun internal magazine"
- desc = "Oh god, this shouldn't be here"
ammo_type = /obj/item/ammo_casing/shotgun/buckshot
- caliber = "shotgun"
max_ammo = 6
- multiload = 0
-/obj/item/ammo_box/magazine/internal/cylinder/dualshot
+/obj/item/ammo_box/magazine/internal/shot/dual
name = "double-barrel shotgun internal magazine"
- desc = "This doesn't even exist"
- ammo_type = /obj/item/ammo_casing/shotgun/beanbag
- caliber = "shotgun"
max_ammo = 2
- multiload = 0
-/obj/item/ammo_box/magazine/internal/cylinder/improvised
+/obj/item/ammo_box/magazine/internal/shot/improvised
name = "improvised shotgun internal magazine"
- desc = "This doesn't even exist"
ammo_type = /obj/item/ammo_casing/shotgun/improvised
- caliber = "shotgun"
max_ammo = 1
- multiload = 0
-/obj/item/ammo_box/magazine/internal/shotriot
+/obj/item/ammo_box/magazine/internal/shot/riot
name = "riot shotgun internal magazine"
- desc = "Oh god, this shouldn't be here"
ammo_type = /obj/item/ammo_casing/shotgun/rubbershot
- caliber = "shotgun"
max_ammo = 6
- multiload = 0
-/obj/item/ammo_box/magazine/internal/cylinder/grenadelauncher
+
+
+
+/obj/item/ammo_box/magazine/internal/grenadelauncher
name = "grenade launcher internal magazine"
ammo_type = /obj/item/ammo_casing/a40mm
caliber = "40mm"
max_ammo = 1
-/obj/item/ammo_box/magazine/internal/cylinder/grenadelauncher/multi
- ammo_type = /obj/item/ammo_casing/a40mm
- max_ammo = 6
-
-/obj/item/ammo_box/magazine/internal/cylinder/speargun
+/obj/item/ammo_box/magazine/internal/speargun
name = "speargun internal magazine"
ammo_type = /obj/item/ammo_casing/caseless/magspear
caliber = "speargun"
max_ammo = 1
+/obj/item/ammo_box/magazine/internal/rus357
+ name = "russian revolver cylinder"
+ ammo_type = /obj/item/ammo_casing/a357
+ caliber = "357"
+ max_ammo = 6
+ multiload = 0
+
+/obj/item/ammo_box/magazine/internal/rus357/New()
+ stored_ammo += new ammo_type(src)
+
/obj/item/ammo_box/magazine/internal/boltaction
name = "bolt action rifle internal magazine"
desc = "Oh god, this shouldn't be here"
@@ -134,6 +172,29 @@
..()
icon_state = "45-[ammo_count() ? "8" : "0"]"
+/obj/item/ammo_box/magazine/wt550m9
+ name = "wt550 magazine (9mm)"
+ icon_state = "9mmt-20"
+ ammo_type = /obj/item/ammo_casing/c9mm
+ caliber = "9mm"
+ max_ammo = 20
+
+/obj/item/ammo_box/magazine/wt550m9/update_icon()
+ ..()
+ icon_state = "9mmt-[round(ammo_count(),4)]"
+
+/obj/item/ammo_box/magazine/wt550m9/wtap
+ name = "wt550 magazine (Armour Piercing 9mm)"
+ ammo_type = /obj/item/ammo_casing/c9mmap
+
+/obj/item/ammo_box/magazine/wt550m9/wttx
+ name = "wt550 magazine (Toxin Tipped 9mm)"
+ ammo_type = /obj/item/ammo_casing/c9mmtox
+
+/obj/item/ammo_box/magazine/wt550m9/wtic
+ name = "wt550 magazine (Incindiary 9mm)"
+ ammo_type = /obj/item/ammo_casing/c9mminc
+
/obj/item/ammo_box/magazine/uzim9mm
name = "uzi magazine (9mm)"
icon_state = "uzi9mm-32"
@@ -147,14 +208,22 @@
/obj/item/ammo_box/magazine/smgm9mm
name = "SMG magazine (9mm)"
- icon_state = "smg9mm-20"
+ icon_state = "smg9mm-42"
ammo_type = /obj/item/ammo_casing/c9mm
caliber = "9mm"
- max_ammo = 20
+ max_ammo = 42
-/obj/item/ammo_box/magazine/smgm9mm/update_icon()
- ..()
- icon_state = "smg9mm-[round(ammo_count(),5)]"
+/obj/item/ammo_box/magazine/smgm9mm/ap
+ name = "SMG magazine (Armour Piercing 9mm)"
+ ammo_type = /obj/item/ammo_casing/c9mmap
+
+/obj/item/ammo_box/magazine/smgm9mm/toxin
+ name = "SMG magazine (Toxin Tipped 9mm)"
+ ammo_type = /obj/item/ammo_casing/c9mmtox
+
+/obj/item/ammo_box/magazine/smgm9mm/fire
+ name = "SMG Magazine (Incindiary 9mm)"
+ ammo_type = /obj/item/ammo_casing/c9mminc
/obj/item/ammo_box/magazine/smgm45
name = "SMG magazine (.45)"
diff --git a/code/modules/projectiles/firing.dm b/code/modules/projectiles/firing.dm
index 2833f2de7f5..80afb0f065c 100644
--- a/code/modules/projectiles/firing.dm
+++ b/code/modules/projectiles/firing.dm
@@ -1,9 +1,9 @@
-/obj/item/ammo_casing/proc/fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, params, distro, quiet)
+/obj/item/ammo_casing/proc/fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, params, distro, quiet, zone_override = "")
distro += variance
for (var/i = max(1, pellets), i > 0, i--)
var/curloc = user.loc
var/targloc = get_turf(target)
- ready_proj(target, user, quiet)
+ ready_proj(target, user, quiet, zone_override)
if(distro)
targloc = spread(targloc, curloc, distro)
if(!throw_proj(targloc, user, params))
@@ -15,12 +15,15 @@
update_icon()
return 1
-/obj/item/ammo_casing/proc/ready_proj(atom/target as mob|obj|turf, mob/living/user, quiet)
+/obj/item/ammo_casing/proc/ready_proj(atom/target as mob|obj|turf, mob/living/user, quiet, zone_override = "")
if (!BB)
return
BB.original = target
BB.firer = user
- BB.def_zone = user.zone_sel.selecting
+ if (zone_override)
+ BB.def_zone = zone_override
+ else
+ BB.def_zone = user.zone_sel.selecting
BB.suppressed = quiet
if(reagents && BB.reagents)
@@ -33,8 +36,8 @@
return 0
if(targloc == curloc)
if(BB.original == user) //if we target ourselves we go straight to bullet_act()
- user.bullet_act(BB)
- del(BB)
+ user.bullet_act(BB, BB.def_zone)
+ qdel(BB)
return 1
BB.loc = get_turf(user)
BB.starting = get_turf(user)
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index cc5bd988992..9252eb3eccf 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -11,11 +11,11 @@
flags = CONDUCT
slot_flags = SLOT_BELT
materials = list(MAT_METAL=2000)
- w_class = 3.0
+ w_class = 3
throwforce = 5
throw_speed = 3
throw_range = 5
- force = 5.0
+ force = 5
origin_tech = "combat=1"
needs_permit = 1
attack_verb = list("struck", "hit", "bashed")
@@ -23,6 +23,7 @@
var/fire_sound = "gunshot"
var/suppressed = 0 //whether or not a message is displayed when fired
var/can_suppress = 0
+ var/can_unsuppress = 1
var/recoil = 0 //boom boom shake the room
var/clumsy_check = 1
var/obj/item/ammo_casing/chambered = null
@@ -121,8 +122,12 @@
/obj/item/weapon/gun/afterattack(atom/target as mob|obj|turf, mob/living/carbon/human/user as mob|obj, flag, params)//TODO: go over this
if(flag) //It's adjacent, is the user, or is on the user's person
- if(istype(target, /mob/) && target != user && !(target in user.contents)) //We make sure that it is a mob, it's not us or part of us.
- if(user.a_intent == "harm") //Flogging action
+ if(istype(target, /mob/) && !(target in user.contents) && target != user && user.a_intent == "harm")
+ //We make sure that it is a mob, it's not us or part of us.
+ return //Flogging action
+ else if(ishuman(target) && ishuman(user))
+ if(user.zone_sel.selecting == "mouth")
+ handle_suicide(user, target, params)
return
else
return
@@ -155,7 +160,7 @@
return 0
if(trigger_guard)
- if(istype(user) && user.dna)
+ if(user.has_dna())
if(user.dna.check_mutation(HULK))
user << "Your meaty finger is much too large for the trigger guard!"
return 0
@@ -232,7 +237,7 @@
user.update_inv_l_hand()
else
user.update_inv_r_hand()
- feedback_add_details("gun_fired","[src.name]")
+ feedback_add_details("gun_fired","[src.type]")
/obj/item/weapon/gun/attack(mob/M as mob, mob/user)
if(user.a_intent == "harm") //Flogging
@@ -359,4 +364,41 @@
if(src && input && !M.stat && in_range(M,src) && !M.restrained() && M.canmove)
name = input
M << "You name the gun [input]. Say hello to your new friend."
- return
\ No newline at end of file
+ return
+
+
+/obj/item/weapon/gun/proc/handle_suicide(mob/living/carbon/human/user, mob/living/carbon/human/target, params)
+ if(!ishuman(user) || !ishuman(target))
+ return
+
+ if(semicd)
+ return
+
+ if(user == target)
+ target.visible_message("[user] sticks [src] in their mouth, ready to pull the trigger...", \
+ "You stick [src] in your mouth, ready to pull the trigger...")
+ else
+ target.visible_message("[user] points [src] at [target]'s head, ready to pull the trigger...", \
+ "[user] points [src] at your head, ready to pull the trigger...")
+
+ semicd = 1
+
+ if(!do_mob(user, target, 120) || user.zone_sel.selecting != "mouth")
+ if(user == target && user)
+ user.visible_message("[user] decided life was worth living.")
+ else if(user && target && target.Adjacent(user))
+ target.visible_message("[user] has decided to spare [target]'s life.", "[user] has decided to spare your life!")
+ semicd = 0
+ return
+
+ semicd = 0
+
+ if(!can_trigger_gun(user))
+ return
+
+ target.visible_message("[user] pulls the trigger!", "[user] pulls the trigger!")
+
+ if(chambered && chambered.BB)
+ chambered.BB.damage *= 5
+
+ process_fire(target, user, 1, params)
diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm
index f6b625d1169..2e86e52f5fd 100644
--- a/code/modules/projectiles/guns/energy/laser.dm
+++ b/code/modules/projectiles/guns/energy/laser.dm
@@ -3,7 +3,7 @@
desc = "A basic energy-based laser gun that fires concentrated beams of light which pass through glass and thin metal."
icon_state = "laser"
item_state = "laser"
- w_class = 3.0
+ w_class = 3
materials = list(MAT_METAL=2000)
origin_tech = "combat=3;magnets=2"
ammo_type = list(/obj/item/ammo_casing/energy/lasergun)
@@ -18,13 +18,14 @@
needs_permit = 0
/obj/item/weapon/gun/energy/laser/retro
- name ="retro laser"
+ name ="retro laser gun"
icon_state = "retro"
desc = "An older model of the basic lasergun, no longer used by Nanotrasen's private security or military forces. Nevertheless, it is still quite deadly and easy to maintain, making it a favorite amongst pirates and other outlaws."
ammo_x_offset = 3
/obj/item/weapon/gun/energy/laser/captain
+ name = "\improper QSJ 01 Premium laser pistol"
icon_state = "caplaser"
item_state = "caplaser"
desc = "This is an antique laser gun. All craftsmanship is of the highest quality. It is decorated with assistant leather and chrome. The object menaces with spikes of energy. On the item is an image of Space Station 13. The station is exploding."
@@ -40,7 +41,7 @@
/obj/item/weapon/gun/energy/laser/captain/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/gun/energy/laser/captain/process()
@@ -83,7 +84,7 @@
desc = "With the L.A.S.E.R. cannon, the lasing medium is enclosed in a tube lined with uranium-235 and subjected to high neutron flux in a nuclear reactor core. This incredible technology may help YOU achieve high excitation rates with small laser volumes!"
icon_state = "lasercannon"
item_state = "laser"
- w_class = 4.0
+ w_class = 4
force = 10
flags = CONDUCT
slot_flags = SLOT_BACK
@@ -122,7 +123,7 @@
/obj/item/weapon/gun/energy/laser/bluetag/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/gun/energy/laser/bluetag/process()
charge_tick++
@@ -154,7 +155,7 @@
/obj/item/weapon/gun/energy/laser/redtag/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/gun/energy/laser/redtag/process()
charge_tick++
diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm
index 89c73331581..a5752e23273 100644
--- a/code/modules/projectiles/guns/energy/nuclear.dm
+++ b/code/modules/projectiles/guns/energy/nuclear.dm
@@ -16,6 +16,7 @@
update_icon()
/obj/item/weapon/gun/energy/gun/hos
+ name = "\improper X-01 MultiPhase Energy Gun"
desc = "This is a expensive, modern recreation of a antique laser gun. This gun has several unique firemodes, but lacks the ability to recharge over time."
icon_state = "hoslaser"
force = 10
@@ -23,7 +24,7 @@
ammo_x_offset = 4
/obj/item/weapon/gun/energy/gun/dragnet
- name = "DRAGnet"
+ name = "\improper DRAGnet"
desc = "The \"Dynamic Rapid-Apprehension of the Guilty\" net is a revolution in law enforcement technology."
icon_state = "dragnet"
origin_tech = "combat=3;magnets=3;materials=4; bluespace=4"
@@ -50,61 +51,66 @@
icon_state = "nucgun"
item_state = "nucgun"
origin_tech = "combat=3;materials=5;powerstorage=3"
- var/fail_state = 0
+ var/fail_tick = 0
var/charge_tick = 0
- can_flashlight = 0
+ var/charge_delay = 5
pin = null
can_charge = 0
ammo_x_offset = 1
+ ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/laser, /obj/item/ammo_casing/energy/disabler)
/obj/item/weapon/gun/energy/gun/nuclear/New()
..()
SSobj.processing |= src
-
/obj/item/weapon/gun/energy/gun/nuclear/Destroy()
SSobj.processing.Remove(src)
- ..()
-
+ return ..()
/obj/item/weapon/gun/energy/gun/nuclear/process()
+ if(fail_tick > 0)
+ fail_tick--
charge_tick++
- if(charge_tick < 4) return 0
+ if(charge_tick < charge_delay)
+ return
charge_tick = 0
- if(!power_supply) return 0
- if((power_supply.charge / power_supply.maxcharge) != 1)
- if(!failcheck()) return 0
- power_supply.give(100)
- update_icon()
- return 1
+ if(!power_supply)
+ return
+ power_supply.give(100)
+ update_icon()
+/obj/item/weapon/gun/energy/gun/nuclear/shoot_live_shot()
+ failcheck()
+ update_icon()
+ ..()
/obj/item/weapon/gun/energy/gun/nuclear/proc/failcheck()
- fail_state = 0
- if (prob(src.reliability)) return 1 //No failure
- if (prob(src.reliability))
- for (var/mob/living/M in range(0,src)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it
- if (src in M.contents)
- M << "Your gun feels pleasantly warm for a moment."
- else
- M << "You feel a warm sensation."
- M.irradiate(rand(3,120))
- fail_state = 1
- else
- for (var/mob/living/M in range(rand(1,4),src)) //Big failure, TIME FOR RADIATION BITCHES
- if (src in M.contents)
- M << "Your gun's reactor overloads!"
- M << "You feel a wave of heat wash over you."
- M.irradiate(300)
- fail_state = 2 //break the gun so it stops recharging
- SSobj.processing.Remove(src)
- update_icon()
- return 0
+ if(!prob(reliability) && istype(loc, /mob/living))
+ var/mob/living/M = loc
+ switch(fail_tick)
+ if(0 to 200)
+ fail_tick += (2*(100-reliability))
+ M.irradiate(40)
+ M << "Your [name] feels warmer."
+ if(201 to INFINITY)
+ SSobj.processing.Remove(src)
+ M.irradiate(80)
+ crit_fail = 1
+ M << "Your [name]'s reactor overloads!"
/obj/item/weapon/gun/energy/gun/nuclear/emp_act(severity)
..()
- reliability -= round(15/severity)
+ reliability = max(reliability - round(15/severity), 0) //Do not allow it to go negative!
/obj/item/weapon/gun/energy/gun/nuclear/update_icon()
..()
- overlays += "[icon_state]_fail_[fail_state]"
+ if(crit_fail)
+ overlays += "[icon_state]_fail_3"
+ else
+ switch(fail_tick)
+ if(0)
+ overlays += "[icon_state]_fail_0"
+ if(1 to 150)
+ overlays += "[icon_state]_fail_1"
+ if(151 to INFINITY)
+ overlays += "[icon_state]_fail_2"
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index 1401c31937a..9ad6ea678c0 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -61,7 +61,7 @@
/obj/item/weapon/gun/energy/floragun/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/gun/energy/floragun/process()
@@ -97,7 +97,7 @@
/obj/item/weapon/gun/energy/meteorgun/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/gun/energy/meteorgun/process()
charge_tick++
@@ -122,7 +122,7 @@
/obj/item/weapon/gun/energy/mindflayer
- name = "mind flayer"
+ name = "\improper Mind Flayer"
desc = "A prototype weapon recovered from the ruins of Research-Station Epsilon."
icon_state = "xray"
ammo_type = list(/obj/item/ammo_casing/energy/mindflayer)
@@ -140,6 +140,7 @@
var/overheat_time = 16
var/recent_reload = 1
unique_rename = 1
+ origin_tech = "combat=2;powerstorage=1"
/obj/item/weapon/gun/energy/kinetic_accelerator/shoot_live_shot()
overheat = 1
@@ -205,6 +206,7 @@
flags = CONDUCT | OPENCONTAINER
attack_verb = list("attacked", "slashed", "cut", "sliced")
can_charge = 0
+ heat = 3800
/obj/item/weapon/gun/energy/plasmacutter/examine(mob/user)
..()
@@ -301,7 +303,7 @@
/obj/item/weapon/gun/energy/printer/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/gun/energy/printer/process()
charge_tick++
diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm
index 6659fe329cd..acd06b2eda3 100644
--- a/code/modules/projectiles/guns/energy/stun.dm
+++ b/code/modules/projectiles/guns/energy/stun.dm
@@ -38,7 +38,7 @@
/obj/item/weapon/gun/energy/gun/advtaser/cyborg/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/gun/energy/gun/advtaser/cyborg/process() //Every [recharge_time] ticks, recharge a shot for the cyborg
charge_tick++
@@ -78,7 +78,7 @@
/obj/item/weapon/gun/energy/disabler/cyborg/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/gun/energy/disabler/cyborg/process() //Every [recharge_time] ticks, recharge a shot for the cyborg
charge_tick++
diff --git a/code/modules/projectiles/guns/grenade_launcher.dm b/code/modules/projectiles/guns/grenade_launcher.dm
index 39a23d5c07d..2c38f1b8c85 100644
--- a/code/modules/projectiles/guns/grenade_launcher.dm
+++ b/code/modules/projectiles/guns/grenade_launcher.dm
@@ -4,10 +4,10 @@
icon = 'icons/obj/guns/projectile.dmi'
icon_state = "riotgun"
item_state = "riotgun"
- w_class = 4.0
+ w_class = 4
throw_speed = 2
throw_range = 7
- force = 5.0
+ force = 5
var/list/grenades = new/list()
var/max_grenades = 3
materials = list(MAT_METAL=2000)
diff --git a/code/modules/projectiles/guns/magic.dm b/code/modules/projectiles/guns/magic.dm
index 645d078002e..af800ecefb7 100644
--- a/code/modules/projectiles/guns/magic.dm
+++ b/code/modules/projectiles/guns/magic.dm
@@ -56,7 +56,7 @@
/obj/item/weapon/gun/magic/Destroy()
if(can_charge) SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/gun/magic/process()
@@ -74,6 +74,6 @@
return
/obj/item/weapon/gun/magic/suicide_act(mob/user)
- user.visible_message("[user] is casting a spell on themself with the [src.name]! It looks like \he's trying to commit suicide.")
+ user.visible_message("[user] is twisting the [src.name] above \his head, releasing a magical blast! It looks like \he's trying to commit suicide.")
playsound(loc, fire_sound, 50, 1, -1)
return (FIRELOSS)
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm
index 03c38726f09..f3f93102e14 100644
--- a/code/modules/projectiles/guns/projectile.dm
+++ b/code/modules/projectiles/guns/projectile.dm
@@ -3,7 +3,7 @@
name = "projectile gun"
icon_state = "pistol"
origin_tech = "combat=2;materials=2"
- w_class = 3.0
+ w_class = 3
materials = list(MAT_METAL=1000)
var/mag_type = /obj/item/ammo_box/magazine/m10mm //Removes the need for max_ammo and caliber info
@@ -89,7 +89,7 @@
/obj/item/weapon/gun/projectile/attack_hand(mob/user)
if(loc == user)
- if(suppressed)
+ if(suppressed && can_unsuppress)
var/obj/item/weapon/suppressor/S = suppressed
if(user.l_hand != src && user.r_hand != src)
..()
@@ -139,7 +139,7 @@
user.visible_message("[user] is putting the barrel of the [src.name] in \his mouth. It looks like \he's trying to commit suicide.")
sleep(25)
if(user.l_hand == src || user.r_hand == src)
- process_fire(user, user, 0)
+ process_fire(user, user, 0, zone_override = "head")
user.visible_message("[user] blows \his brains out with the [src.name]!")
return(BRUTELOSS)
else
@@ -157,4 +157,4 @@
icon_state = "suppressor"
w_class = 2
var/oldsound = null
- var/initial_w_class = null
\ No newline at end of file
+ var/initial_w_class = null
diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm
index 45660958359..9dc38fe5ba6 100644
--- a/code/modules/projectiles/guns/projectile/automatic.dm
+++ b/code/modules/projectiles/guns/projectile/automatic.dm
@@ -9,7 +9,7 @@
action_button_name = "Toggle Firemode"
/obj/item/weapon/gun/projectile/automatic/proto
- name = "prototype SMG"
+ name = "\improper NanoTrasen Saber SMG"
desc = "A prototype three-round burst 9mm submachine gun, designated 'SABR'. Has a threaded barrel for suppressors."
icon_state = "saber"
mag_type = /obj/item/ammo_box/magazine/smgm9mm
@@ -80,7 +80,7 @@
return
/obj/item/weapon/gun/projectile/automatic/c20r
- name = "syndicate SMG"
+ name = "\improper C-20r SMG"
desc = "A bullpup two-round burst .45 SMG, designated 'C-20r'. Has a 'Scarborough Arms - Per falcis, per pravitas' buttstamp."
icon_state = "c20r"
item_state = "c20r"
@@ -109,8 +109,26 @@
icon_state = "c20r[magazine ? "-[Ceiling(get_ammo(0)/4)*4]" : ""][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
return
+/obj/item/weapon/gun/projectile/automatic/wt550
+ name = "security auto rifle"
+ desc = "A outdated personal defence weapon. Uses 9mm rounds and is designated the WT-550 Automatic Rifle."
+ icon_state = "wt550"
+ item_state = "arg"
+ mag_type = /obj/item/ammo_box/magazine/wt550m9
+ fire_delay = 2
+ can_suppress = 0
+ burst_size = 0
+
+/obj/item/weapon/gun/projectile/automatic/wt550/ui_action_click()
+ return
+
+/obj/item/weapon/gun/projectile/automatic/wt550/update_icon()
+ ..()
+ icon_state = "wt550[magazine ? "-[Ceiling(get_ammo(0)/4)*4]" : ""]"
+ return
+
/obj/item/weapon/gun/projectile/automatic/mini_uzi
- name = "uzi"
+ name = "\improper 'Type U3' Uzi"
desc = "A lightweight, burst-fire submachine gun, for when you really want someone dead. Uses 9mm rounds."
icon_state = "mini-uzi"
origin_tech = "combat=5;materials=2;syndicate=8"
@@ -118,7 +136,7 @@
burst_size = 2
/obj/item/weapon/gun/projectile/automatic/l6_saw
- name = "syndicate LMG"
+ name = "\improper L6 SAW LMG"
desc = "A heavily modified 7.62 light machine gun, designated 'L6 SAW'. Has 'Aussec Armoury - 2531' engraved on the receiver below the designation."
icon_state = "l6closed100"
item_state = "l6closedmag"
@@ -178,7 +196,7 @@
..()
/obj/item/weapon/gun/projectile/automatic/m90
- name = "syndicate carbine"
+ name = "\improper M-90gl Carbine"
desc = "A three-round burst 5.56 toploading carbine, designated 'M-90gl'. Has an attached underbarrel grenade launcher which can be toggled on and off."
icon_state = "m90"
item_state = "m90"
@@ -190,13 +208,22 @@
burst_size = 3
fire_delay = 2
pin = /obj/item/device/firing_pin/implant/pindicate
-/obj/item/weapon/gun/projectile/automatic/m90/unrestricted
- pin = /obj/item/device/firing_pin
+
/obj/item/weapon/gun/projectile/automatic/m90/New()
..()
underbarrel = new /obj/item/weapon/gun/projectile/revolver/grenadelauncher(src)
update_icon()
return
+
+/obj/item/weapon/gun/projectile/automatic/m90/unrestricted
+ pin = /obj/item/device/firing_pin
+
+/obj/item/weapon/gun/projectile/automatic/m90/unrestricted/New()
+ ..()
+ underbarrel = new /obj/item/weapon/gun/projectile/revolver/grenadelauncher/unrestricted(src)
+ update_icon()
+ return
+
/obj/item/weapon/gun/projectile/automatic/m90/afterattack(atom/target, mob/living/user, flag, params)
if(select == 2)
underbarrel.afterattack(target, user, flag, params)
@@ -243,7 +270,7 @@
return
/obj/item/weapon/gun/projectile/automatic/tommygun
- name = "thompson SMG"
+ name = "\improper Thompson SMG"
desc = "Based on the classic 'Chicago Typewriter'."
icon_state = "tommygun"
item_state = "shotgun"
@@ -257,7 +284,7 @@
fire_delay = 1
/obj/item/weapon/gun/projectile/automatic/ar
- name = "ARG"
+ name = "\improper NT-ARG 'Boarder'"
desc = "A robust assault rile used by Nanotrasen fighting forces."
icon_state = "arg"
item_state = "arg"
diff --git a/code/modules/projectiles/guns/projectile/launchers.dm b/code/modules/projectiles/guns/projectile/launchers.dm
index 4bddd2d3ce4..0d9220733f1 100644
--- a/code/modules/projectiles/guns/projectile/launchers.dm
+++ b/code/modules/projectiles/guns/projectile/launchers.dm
@@ -6,9 +6,13 @@
name = "grenade launcher"
icon_state = "dshotgun-sawn"
item_state = "gun"
- mag_type = /obj/item/ammo_box/magazine/internal/cylinder/grenadelauncher
+ mag_type = /obj/item/ammo_box/magazine/internal/grenadelauncher
fire_sound = 'sound/weapons/grenadelaunch.ogg'
w_class = 3
+ pin = /obj/item/device/firing_pin/implant/pindicate
+
+/obj/item/weapon/gun/projectile/revolver/grenadelauncher/unrestricted
+ pin = /obj/item/device/firing_pin
/obj/item/weapon/gun/projectile/revolver/grenadelauncher/attackby(obj/item/A, mob/user, params)
..()
@@ -20,13 +24,13 @@
name = "multi grenade launcher"
icon = 'icons/mecha/mecha_equipment.dmi'
icon_state = "mecha_grenadelnchr"
- mag_type = /obj/item/ammo_box/magazine/internal/cylinder/grenadelauncher/multi
+ mag_type = /obj/item/ammo_box/magazine/internal/cylinder/grenademulti
/obj/item/weapon/gun/projectile/revolver/grenadelauncher/cyborg/attack_self()
return
/obj/item/weapon/gun/projectile/automatic/gyropistol
- name = "gyrojet pistol"
+ name = "\improper Gyrojet rocket pistol"
desc = "A prototype pistol designed to fire self propelled rockets."
icon_state = "gyropistol"
fire_sound = 'sound/weapons/grenadelaunch.ogg'
@@ -52,7 +56,7 @@
w_class = 4
force = 10
can_suppress = 0
- mag_type = /obj/item/ammo_box/magazine/internal/cylinder/speargun
+ mag_type = /obj/item/ammo_box/magazine/internal/speargun
fire_sound = 'sound/weapons/grenadelaunch.ogg'
burst_size = 1
fire_delay = 0
diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm
index 7e3635defc1..97fbda944f3 100644
--- a/code/modules/projectiles/guns/projectile/pistol.dm
+++ b/code/modules/projectiles/guns/projectile/pistol.dm
@@ -1,5 +1,5 @@
/obj/item/weapon/gun/projectile/automatic/pistol
- name = "syndicate pistol"
+ name = "\improper FK-69 pistol"
desc = "A small, easily concealable 10mm handgun. Has a threaded barrel for suppressors."
icon_state = "pistol"
w_class = 2
@@ -16,7 +16,7 @@
return
/obj/item/weapon/gun/projectile/automatic/pistol/m1911
- name = "M1911 pistol"
+ name = "\improper M1911 pistol"
desc = "A classic .45 handgun with a small magazine capacity."
icon_state = "m1911"
w_class = 3
@@ -24,7 +24,7 @@
can_suppress = 0
/obj/item/weapon/gun/projectile/automatic/pistol/deagle
- name = "desert eagle"
+ name = "\improper Desert Eagle pistol"
desc = "A robust .50 AE handgun."
icon_state = "deagle"
force = 14
diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm
index 1a9c2fdd071..7cc46f27a26 100644
--- a/code/modules/projectiles/guns/projectile/revolver.dm
+++ b/code/modules/projectiles/guns/projectile/revolver.dm
@@ -1,16 +1,25 @@
/obj/item/weapon/gun/projectile/revolver
- name = "revolver"
+ name = "\improper .357 revolver"
desc = "A suspicious revolver. Uses .357 ammo." //usually used by syndicates
icon_state = "revolver"
mag_type = /obj/item/ammo_box/magazine/internal/cylinder
-/obj/item/weapon/gun/projectile/revolver/chamber_round()
- if ((chambered && chambered.BB)|| !magazine) //if there's a live ammo in the chamber or no magazine
- return
- else if (magazine.ammo_count())
+/obj/item/weapon/gun/projectile/revolver/New()
+ ..()
+ if(!istype(magazine, /obj/item/ammo_box/magazine/internal/cylinder))
+ verbs -= /obj/item/weapon/gun/projectile/revolver/verb/spin
+
+/obj/item/weapon/gun/projectile/revolver/chamber_round(var/spin = 1)
+ if(spin)
chambered = magazine.get_round(1)
+ else
+ chambered = magazine.stored_ammo[1]
return
+/obj/item/weapon/gun/projectile/revolver/shoot_with_empty_chamber(mob/living/user as mob|obj)
+ ..()
+ chamber_round(1)
+
/obj/item/weapon/gun/projectile/revolver/process_chamber()
return ..(0, 1)
@@ -20,7 +29,7 @@
user << "You load [num_loaded] shell\s into \the [src]."
A.update_icon()
update_icon()
- chamber_round()
+ chamber_round(0)
if(unique_rename)
if(istype(A, /obj/item/weapon/pen))
@@ -28,19 +37,39 @@
/obj/item/weapon/gun/projectile/revolver/attack_self(mob/living/user)
var/num_unloaded = 0
+ chambered = null
while (get_ammo() > 0)
var/obj/item/ammo_casing/CB
CB = magazine.get_round(0)
- chambered = null
- CB.loc = get_turf(src.loc)
- CB.SpinAnimation(10, 1)
- CB.update_icon()
- num_unloaded++
+ if(CB)
+ CB.loc = get_turf(src.loc)
+ CB.SpinAnimation(10, 1)
+ CB.update_icon()
+ num_unloaded++
if (num_unloaded)
user << "You unload [num_unloaded] shell\s from [src]."
else
user << "[src] is empty!"
+/obj/item/weapon/gun/projectile/revolver/verb/spin()
+ set name = "Spin Chamber"
+ set category = "Object"
+ set desc = "Click to spin your revolver's chamber."
+
+ var/mob/M = usr
+
+ if(M.stat || !in_range(M,src))
+ return
+
+ if(istype(magazine, /obj/item/ammo_box/magazine/internal/cylinder))
+ var/obj/item/ammo_box/magazine/internal/cylinder/C = magazine
+ C.spin()
+ chamber_round(0)
+ usr.visible_message("[usr] spins [src]'s chamber.", "You spin [src]'s chamber.")
+ else
+ verbs -= /obj/item/weapon/gun/projectile/revolver/verb/spin
+
+
/obj/item/weapon/gun/projectile/revolver/can_shoot()
return get_ammo(0,0)
@@ -57,6 +86,7 @@
user << "[get_ammo(0,0)] of those are live rounds."
/obj/item/weapon/gun/projectile/revolver/detective
+ name = "\improper .38 Mars Special"
desc = "A cheap Martian knock-off of a classic law enforcement firearm. Uses .38-special rounds."
icon_state = "detective"
origin_tech = "combat=2;materials=2"
@@ -73,7 +103,7 @@
options["The Peacemaker"] = "detective_peacemaker"
options["Cancel"] = null
-/obj/item/weapon/gun/projectile/revolver/detective/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params)
+/obj/item/weapon/gun/projectile/revolver/detective/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override = "")
if(magazine.caliber != initial(magazine.caliber))
if(prob(70 - (magazine.ammo_count() * 10))) //minimum probability of 10, maximum of 60
playsound(user, fire_sound, 50, 1)
@@ -115,8 +145,8 @@
/obj/item/weapon/gun/projectile/revolver/mateba
- name = "autorevolver"
- desc = "A retro high-powered mateba autorevolver typically used by officers of the New Russia military. Uses .357 ammo."
+ name = "\improper Unica 6 auto-revolver"
+ desc = "A retro high-powered autorevolver typically used by officers of the New Russia military. Uses .357 ammo."
icon_state = "mateba"
origin_tech = "combat=2;materials=2"
@@ -125,10 +155,10 @@
// You can spin the chamber to randomize the position of the bullet.
/obj/item/weapon/gun/projectile/revolver/russian
- name = "russian revolver"
+ name = "\improper russian revolver"
desc = "A Russian-made revolver for drinking games. Uses .357 ammo, and has a mechanism requiring you to spin the chamber before each trigger pull."
origin_tech = "combat=2;materials=2"
- mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rus357
+ mag_type = /obj/item/ammo_box/magazine/internal/rus357
var/spun = 0
/obj/item/weapon/gun/projectile/revolver/russian/New()
diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm
index cc253a9e66e..1b4d3ec2ac7 100644
--- a/code/modules/projectiles/guns/projectile/shotgun.dm
+++ b/code/modules/projectiles/guns/projectile/shotgun.dm
@@ -3,7 +3,7 @@
desc = "A traditional shotgun with wood furniture and a four-shell capacity underneath."
icon_state = "shotgun"
item_state = "shotgun"
- w_class = 4.0
+ w_class = 4
force = 10
flags = CONDUCT
slot_flags = SLOT_BACK
@@ -68,7 +68,7 @@
name = "riot shotgun"
desc = "A sturdy shotgun with a longer magazine and a fixed tactical stock designed for non-lethal riot control."
icon_state = "riotshotgun"
- mag_type = /obj/item/ammo_box/magazine/internal/shotriot
+ mag_type = /obj/item/ammo_box/magazine/internal/shot/riot
sawn_desc = "Come with me if you want to live."
/obj/item/weapon/gun/projectile/shotgun/riot/attackby(obj/item/A, mob/user, params)
@@ -85,8 +85,8 @@
///////////////////////
/obj/item/weapon/gun/projectile/shotgun/boltaction
- name = "bolt action rifle"
- desc = "This piece of junk looks like something that could have been used 700 years ago."
+ name = "\improper Mosin Nagant rifle"
+ desc = "This piece of junk looks like something that could have been used 700 years ago. It feels slightly moist."
icon_state = "moistnugget"
item_state = "moistnugget"
slot_flags = 0 //no SLOT_BACK sprite, alas
@@ -122,12 +122,12 @@
desc = "A true classic."
icon_state = "dshotgun"
item_state = "shotgun"
- w_class = 4.0
+ w_class = 4
force = 10
flags = CONDUCT
slot_flags = SLOT_BACK
origin_tech = "combat=3;materials=1"
- mag_type = /obj/item/ammo_box/magazine/internal/cylinder/dualshot
+ mag_type = /obj/item/ammo_box/magazine/internal/shot/dual
sawn_desc = "Omar's coming!"
unique_rename = 1
unique_reskin = 1
@@ -175,11 +175,11 @@
desc = "Essentially a tube that aims shotgun shells."
icon_state = "ishotgun"
item_state = "shotgun"
- w_class = 4.0
+ w_class = 4
force = 10
slot_flags = null
origin_tech = "combat=2;materials=2"
- mag_type = /obj/item/ammo_box/magazine/internal/cylinder/improvised
+ mag_type = /obj/item/ammo_box/magazine/internal/shot/improvised
sawn_desc = "I'm just here for the gasoline."
unique_rename = 0
unique_reskin = 0
@@ -234,7 +234,7 @@
name = "sawn-off [src.name]"
desc = sawn_desc
icon_state = "[icon_state]-sawn"
- w_class = 3.0
+ w_class = 3
item_state = "gun"
slot_flags &= ~SLOT_BACK //you can't sling it on your back
slot_flags |= SLOT_BELT //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally)
@@ -248,11 +248,11 @@
// Bulldog shotgun //
/obj/item/weapon/gun/projectile/automatic/shotgun/bulldog
- name = "syndicate shotgun"
+ name = "\improper MLG-12 'Bulldog' Shotgun"
desc = "A semi-auto, mag-fed shotgun for combat in narrow corridors, nicknamed 'Bulldog' by boarding parties. Compatible only with specialized 8-round drum magazines."
icon_state = "bulldog"
item_state = "bulldog"
- w_class = 3.0
+ w_class = 3
origin_tech = "combat=5;materials=4;syndicate=6"
mag_type = /obj/item/ammo_box/magazine/m12g
fire_sound = 'sound/weapons/Gunshot.ogg'
@@ -298,5 +298,5 @@
desc = "A semi automatic shotgun with tactical furniture and a six-shell capacity underneath."
icon_state = "cshotgun"
origin_tech = "combat=5;materials=2"
- mag_type = /obj/item/ammo_box/magazine/internal/shotcom
+ mag_type = /obj/item/ammo_box/magazine/internal/shot/com
w_class = 5
diff --git a/code/modules/projectiles/guns/syringe_gun.dm b/code/modules/projectiles/guns/syringe_gun.dm
index e44ae121576..8f22c228f21 100644
--- a/code/modules/projectiles/guns/syringe_gun.dm
+++ b/code/modules/projectiles/guns/syringe_gun.dm
@@ -78,3 +78,14 @@
desc = "A modification of the syringe gun design, using a rotating cylinder to store up to six syringes."
icon_state = "rapidsyringegun"
max_syringes = 6
+
+/obj/item/weapon/gun/syringe/syndicate
+ name = "dart pistol"
+ desc = "A small spring-loaded sidearm that functions identically to a syringe gun."
+ icon_state = "syringe_pistol"
+ item_state = "gun" //Smaller inhand
+ w_class = 2
+ origin_tech = "combat=2;syndicate=2"
+ force = 2 //Also very weak because it's smaller
+ suppressed = 1 //Softer fire sound
+ can_unsuppress = 0 //Permanently silenced
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index 83d693f3479..fda0ec76a94 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -11,7 +11,6 @@
damage = 5
stamina = 80
-
/obj/item/projectile/bullet/weakbullet2 //detective revolver instastuns, but multiple shots are better for keeping punks down
damage = 15
weaken = 3
@@ -20,6 +19,17 @@
/obj/item/projectile/bullet/weakbullet3
damage = 20
+/obj/item/projectile/bullet/toxinbullet
+ damage = 15
+ damage_type = TOX
+
+/obj/item/projectile/bullet/incendiary/firebullet
+ damage = 10
+
+/obj/item/projectile/bullet/armourpiercing
+ damage = 17
+ armour_penetration = 10
+
/obj/item/projectile/bullet/pellet
name = "pellet"
damage = 15
diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm
index bbe10e02af3..3238db399ec 100644
--- a/code/modules/projectiles/projectile/magic.dm
+++ b/code/modules/projectiles/projectile/magic.dm
@@ -202,7 +202,7 @@
if("parrot") new_mob = new /mob/living/simple_animal/parrot(M.loc)
if("corgi") new_mob = new /mob/living/simple_animal/pet/dog/corgi(M.loc)
if("crab") new_mob = new /mob/living/simple_animal/crab(M.loc)
- if("pug") new_mob = new /mob/living/simple_animal/pet/pug(M.loc)
+ if("pug") new_mob = new /mob/living/simple_animal/pet/dog/pug(M.loc)
if("cat") new_mob = new /mob/living/simple_animal/pet/cat(M.loc)
if("mouse") new_mob = new /mob/living/simple_animal/mouse(M.loc)
if("chicken") new_mob = new /mob/living/simple_animal/chicken(M.loc)
@@ -216,19 +216,21 @@
new_mob = new /mob/living/carbon/human(M.loc)
var/datum/preferences/A = new() //Randomize appearance for the human
- A.copy_to(new_mob)
+ A.copy_to(new_mob, icon_updates=0)
var/mob/living/carbon/human/H = new_mob
- ready_dna(H)
- if(H.dna && prob(50))
+ if(prob(50))
var/list/all_species = list()
for(var/speciestype in typesof(/datum/species) - /datum/species)
var/datum/species/S = new speciestype()
if(!S.dangerous_existence)
all_species += speciestype
- hardset_dna(H, null, null, null, null, pick(all_species))
+ H.set_species(pick(all_species), icon_update=0)
H.real_name = H.dna.species.random_name(H.gender,1)
- H.update_icons()
+ H.update_body()
+ H.update_hair()
+ H.update_mutcolor()
+ H.dna.update_dna_identity()
else
return
@@ -243,7 +245,7 @@
new_mob << "Your form morphs into that of a [randomize]."
- del(M)
+ qdel(M)
return new_mob
/obj/item/projectile/magic/animate
diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm
index e83acf03014..bda9b056d14 100644
--- a/code/modules/reagents/Chemistry-Holder.dm
+++ b/code/modules/reagents/Chemistry-Holder.dm
@@ -1,7 +1,9 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
-var/const/TOUCH = 1
-var/const/INGEST = 2
+var/const/TOUCH = 1 //splashing
+var/const/INGEST = 2 //injection, ingestion
+var/const/VAPOR = 3 //smoke, foam, spray, blob attack
+var/const/PATCH = 4 //patches
///////////////////////////////////////////////////////////////////////////////////
@@ -52,7 +54,7 @@ var/const/INGEST = 2
break // Don't bother adding ourselves to other reagent ids, it is redundant.
/datum/reagents/Destroy()
- ..()
+ . = ..()
SSobj.processing.Remove(src)
for(var/datum/reagent/R in reagent_list)
qdel(R)
@@ -211,7 +213,7 @@ var/const/INGEST = 2
return total_transfered
*/
-/datum/reagents/proc/metabolize(mob/M)
+/datum/reagents/proc/metabolize(mob/M, can_overdose = 0)
if(M)
chem_temp = M.bodytemperature
handle_reactions()
@@ -224,45 +226,47 @@ var/const/INGEST = 2
M = R.holder.my_atom
if(M && R)
if(M.reagent_check(R) != 1)
- if(R.overdose_threshold)
- if(R.volume >= R.overdose_threshold && !R.overdosed)
- R.overdosed = 1
- R.overdose_start(M)
- if(R.addiction_threshold)
- if(R.volume >= R.addiction_threshold && !is_type_in_list(R, addiction_list))
- var/datum/reagent/new_reagent = new R.type()
- addiction_list.Add(new_reagent)
- if(R.overdosed)
- R.overdose_process(M)
- if(is_type_in_list(R,addiction_list))
- for(var/datum/reagent/addicted_reagent in addiction_list)
- if(istype(R, addicted_reagent))
- addicted_reagent.addiction_stage = -15 // you're satisfied for a good while.
+ if(can_overdose)
+ if(R.overdose_threshold)
+ if(R.volume >= R.overdose_threshold && !R.overdosed)
+ R.overdosed = 1
+ R.overdose_start(M)
+ if(R.addiction_threshold)
+ if(R.volume >= R.addiction_threshold && !is_type_in_list(R, addiction_list))
+ var/datum/reagent/new_reagent = new R.type()
+ addiction_list.Add(new_reagent)
+ if(R.overdosed)
+ R.overdose_process(M)
+ if(is_type_in_list(R,addiction_list))
+ for(var/datum/reagent/addicted_reagent in addiction_list)
+ if(istype(R, addicted_reagent))
+ addicted_reagent.addiction_stage = -15 // you're satisfied for a good while.
R.on_mob_life(M)
- if(addiction_tick == 6)
- addiction_tick = 1
- for(var/A in addiction_list)
- var/datum/reagent/R = A
- if(M && R)
- if(R.addiction_stage <= 0)
- R.addiction_stage++
- if(R.addiction_stage > 0 && R.addiction_stage <= 10)
- R.addiction_act_stage1(M)
- R.addiction_stage++
- if(R.addiction_stage > 10 && R.addiction_stage <= 20)
- R.addiction_act_stage2(M)
- R.addiction_stage++
- if(R.addiction_stage > 20 && R.addiction_stage <= 30)
- R.addiction_act_stage3(M)
- R.addiction_stage++
- if(R.addiction_stage > 30 && R.addiction_stage <= 40)
- R.addiction_act_stage4(M)
- R.addiction_stage++
- if(R.addiction_stage > 40)
- M << "You feel like you've gotten over your need for [R.name]."
- addiction_list.Remove(R)
- addiction_tick++
+ if(can_overdose)
+ if(addiction_tick == 6)
+ addiction_tick = 1
+ for(var/A in addiction_list)
+ var/datum/reagent/R = A
+ if(M && R)
+ if(R.addiction_stage <= 0)
+ R.addiction_stage++
+ if(R.addiction_stage > 0 && R.addiction_stage <= 10)
+ R.addiction_act_stage1(M)
+ R.addiction_stage++
+ if(R.addiction_stage > 10 && R.addiction_stage <= 20)
+ R.addiction_act_stage2(M)
+ R.addiction_stage++
+ if(R.addiction_stage > 20 && R.addiction_stage <= 30)
+ R.addiction_act_stage3(M)
+ R.addiction_stage++
+ if(R.addiction_stage > 30 && R.addiction_stage <= 40)
+ R.addiction_act_stage4(M)
+ R.addiction_stage++
+ if(R.addiction_stage > 40)
+ M << "You feel like you've gotten over your need for [R.name]."
+ addiction_list.Remove(R)
+ addiction_tick++
update_total()
/datum/reagents/process()
@@ -398,7 +402,7 @@ var/const/INGEST = 2
/datum/reagents/proc/check_gofast(mob/M)
if(istype(M, /mob))
- if(M.reagents.has_reagent("unholywater")||M.reagents.has_reagent("nuka_cola"))
+ if(M.reagents.has_reagent("unholywater")||M.reagents.has_reagent("nuka_cola")||M.reagents.has_reagent("stimulants"))
return 1
else
M.status_flags &= ~GOTTAGOFAST
@@ -429,7 +433,7 @@ var/const/INGEST = 2
if(isliving(A))
var/mob/living/L = A
var/touch_protection = 0
- if(method == TOUCH)
+ if(method == VAPOR)
touch_protection = L.get_permeability_protection()
for(var/datum/reagent/R in reagent_list)
R.reaction_mob(L, method, R.volume*volume_modifier, show_message, touch_protection)
diff --git a/code/modules/reagents/Chemistry-Readme.dm b/code/modules/reagents/Chemistry-Readme.dm
index 74e9fe0b093..bd28dcb79f1 100644
--- a/code/modules/reagents/Chemistry-Readme.dm
+++ b/code/modules/reagents/Chemistry-Readme.dm
@@ -69,7 +69,7 @@ About the Holder:
This proc calls the appropriate reaction procs of the reagents.
I.e. if A is an object, it will call the reagents reaction_obj
proc. The method var is used for reaction on mobs. It simply tells
- us if the mob TOUCHed the reagent or if it INGESTed the reagent.
+ us if the mob TOUCHed the reagent, if it INGESTed the reagent, if the reagent was VAPORIZEd on them, or transfered via a PATCH to them..
Since the volume can be checked in a reagents proc, you might want to
use the volume_modifier var to modifiy the passed value without actually
changing the volume of the reagents.
diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm
index c89a5d434eb..3f258374874 100644
--- a/code/modules/reagents/Chemistry-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents.dm
@@ -4,10 +4,6 @@
#define REM REAGENTS_EFFECT_MULTIPLIER
-//The reaction procs must ALWAYS set src = null, this detaches the proc from the object (the reagent)
-//so that it can continue working when the reagent is deleted while the proc is still active.
-
-
//Various reagents
//Toxin & acid reagents
//Hydroponics stuff
@@ -28,38 +24,31 @@
var/overdose_threshold = 0
var/addiction_threshold = 0
var/addiction_stage = 0
- var/overdosed = 0 // You fucked up and this is now triggering it's overdose effects, purge that shit quick.
+ var/overdosed = 0 // You fucked up and this is now triggering its overdose effects, purge that shit quick.
/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references
- ..()
+ . = ..()
holder = null
-/datum/reagent/proc/reaction_mob(mob/living/M, method=TOUCH, volume, show_message = 1, touch_protection = 0)
+/datum/reagent/proc/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1, touch_protection = 0)
if(!istype(M))
return 0
- var/datum/reagent/self = src
- src = null
-
- if(method == TOUCH)
+ if(method == VAPOR) //smoke, foam, spray
if(M.reagents)
- var/modifier = Clamp((1 - touch_protection) + rand(-5,5)/100, 0, 1)
- var/amount = round(volume*modifier, 0.1)
+ var/modifier = Clamp((1 - touch_protection), 0, 1)
+ var/amount = round(reac_volume*modifier, 0.1)
if(amount >= 1)
- M.reagents.add_reagent(self.id, amount)
+ M.reagents.add_reagent(id, amount)
return 1
/datum/reagent/proc/reaction_obj(obj/O, volume)
- src = null
return
/datum/reagent/proc/reaction_turf(turf/T, volume)
- src = null
return
/datum/reagent/proc/on_mob_life(mob/living/M)
current_cycle++
- if(!istype(M, /mob/living))
- return //Noticed runtime errors from facid trying to damage ghosts, this should fix. --NEO
holder.remove_reagent(src.id, metabolization_rate * M.metabolism_efficiency) //By default it slowly disappears.
return
@@ -117,3 +106,10 @@
M << "You're not feeling good at all! You really need some [name]."
return
+/proc/pretty_string_from_reagent_list(var/list/reagent_list)
+ //Convert reagent list to a printable string for logging etc
+ var/result = "| "
+ for (var/datum/reagent/R in reagent_list)
+ result += "[R.name], [R.volume] | "
+
+ return result
diff --git a/code/modules/reagents/Chemistry-Reagents/Blob-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Blob-Reagents.dm
index 5470a6f5db1..a6bb05181a7 100644
--- a/code/modules/reagents/Chemistry-Reagents/Blob-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Blob-Reagents.dm
@@ -1,179 +1,114 @@
// These can only be applied by blobs. They are what blobs are made out of.
// The 4 damage
/datum/reagent/blob
+ description = ""
var/message = "The blob strikes you" //message sent to any mob hit by the blob
var/message_living = null //extension to first mob sent to only living mobs i.e. silicons have no skin to be burnt
-/datum/reagent/blob/boiling_oil
- name = "Boiling Oil"
- id = "boiling_oil"
- description = ""
- color = "#B68D00"
- message = "The blob splashes you with burning oil"
+/datum/reagent/blob/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection)
+ return round(reac_volume * min(1.5 - touch_protection, 1), 0.1) //full touch protection means 50% volume, any prot below 0.5 means 100% volume.
-/datum/reagent/blob/boiling_oil/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH)
- var/ratio = volume/25
- M.apply_damage(15*ratio, BURN)
- M.adjust_fire_stacks(2*ratio)
- M.IgniteMob()
- if(isliving(M))
- M.emote("scream")
-
-/datum/reagent/blob/toxic_goop
- name = "Toxic Goop"
- id = "toxic_goop"
- description = ""
- color = "#008000"
- message_living = ", and you feel sick and nauseated"
-
-/datum/reagent/blob/toxic_goop/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH)
- var/ratio = volume/25
- M.apply_damage(20*ratio, TOX)
-
-/datum/reagent/blob/skin_ripper
- name = "Skin Ripper"
- id = "skin_ripper"
- description = ""
- color = "#FF4C4C"
+/datum/reagent/blob/ripping_tendrils //does brute and a little stamina damage
+ name = "Ripping Tendrils"
+ id = "ripping_tendrils"
+ color = "#7F0000"
message_living = ", and you feel your skin ripping and tearing off"
-/datum/reagent/blob/skin_ripper/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH)
- var/ratio = volume/25
- M.apply_damage(20*ratio, BRUTE)
- if(iscarbon(M))
- M.emote("scream")
+/datum/reagent/blob/ripping_tendrils/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ reac_volume = ..()
+ M.apply_damage(0.6*reac_volume, BRUTE)
+ M.adjustStaminaLoss(0.4*reac_volume)
+ if(iscarbon(M))
+ M.emote("scream")
-// Combo Reagents
-
-/datum/reagent/blob/skin_melter
- name = "Skin Melter"
- id = "skin_melter"
- description = ""
- color = "#7F0000"
+/datum/reagent/blob/boiling_oil //sets you on fire, does burn damage
+ name = "Boiling Oil"
+ id = "boiling_oil"
+ color = "#B68D00"
+ message = "The blob splashes you with burning oil"
message_living = ", and you feel your skin char and melt"
-/datum/reagent/blob/skin_melter/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH)
- var/ratio = volume/25
- M.apply_damage(10*ratio, BRUTE)
- M.apply_damage(10*ratio, BURN)
- M.adjust_fire_stacks(2*ratio)
- M.IgniteMob()
- if(iscarbon(M))
- M.emote("scream")
+/datum/reagent/blob/boiling_oil/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ M.adjust_fire_stacks(round(reac_volume/12))
+ reac_volume = ..()
+ M.apply_damage(0.6*reac_volume, BURN)
+ M.IgniteMob()
+ if(iscarbon(M))
+ M.emote("scream")
-/datum/reagent/blob/lung_destroying_toxin
- name = "Lung Destroying Toxin"
- id = "lung_destroying_toxin"
- description = ""
+/datum/reagent/blob/envenomed_filaments //toxin, hallucination, and some bonus spore toxin
+ name = "Envenomed Filaments"
+ id = "envenomed_filaments"
+ color = "#9ACD32"
+ message_living = ", and you feel sick and nauseated"
+
+/datum/reagent/blob/envenomed_filaments/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ reac_volume = ..()
+ M.apply_damage(0.6*reac_volume, TOX)
+ M.hallucination += 0.6*reac_volume
+ M.reagents.add_reagent("spore", 0.4*reac_volume)
+
+/datum/reagent/blob/lexorin_jelly //does tons of oxygen damage and a little brute
+ name = "Lexorin Jelly"
+ id = "lexorin_jelly"
color = "#00FFC5"
message_living = ", and your lungs feel heavy and weak"
-/datum/reagent/blob/lung_destroying_toxin/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH)
- var/ratio = volume/25
- M.apply_damage(20* ratio, OXY)
- M.losebreath += 15*ratio
- M.apply_damage(20*ratio, TOX)
+/datum/reagent/blob/lexorin_jelly/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ reac_volume = ..()
+ M.apply_damage(0.4*reac_volume, BRUTE)
+ M.apply_damage(1*reac_volume, OXY)
+ M.losebreath += round(0.3*reac_volume)
-// Special Reagents
+/datum/reagent/blob/kinetic //does semi-random brute damage
+ name = "Kinetic Gelatin"
+ id = "kinetic"
+ color = "#FFA500"
+ message = "The blob pummels you"
-/datum/reagent/blob/radioactive_liquid
- name = "Radioactive Liquid"
- id = "radioactive_liquid"
- description = ""
- color = "#00EE00"
- message_living = ", and your skin feels papery and everything hurts"
+/datum/reagent/blob/kinetic/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ reac_volume = ..()
+ var/damage = rand(5, 35)/25
+ M.apply_damage(damage*reac_volume, BRUTE)
-/datum/reagent/blob/radioactive_liquid/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH)
- var/ratio = volume/25
- M.apply_damage(10*ratio, BRUTE)
- if(istype(M, /mob/living/carbon/human))
- M.irradiate(40*ratio)
- if(prob(33*ratio))
- randmuti(M)
- if(prob(98))
- randmutb(M)
- domutcheck(M, null)
- updateappearance(M)
+/datum/reagent/blob/cryogenic_liquid //does low burn damage and stamina damage and cools targets down
+ name = "Cryogenic Liquid"
+ id = "cryogenic_liquid"
+ color = "#8BA6E9"
+ message = "The blob splashes you with an icy liquid"
+ message_living = ", and you feel cold and tired"
-/datum/reagent/blob/dark_matter
+/datum/reagent/blob/cryogenic_liquid/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ reac_volume = ..()
+ M.apply_damage(0.4*reac_volume, BURN)
+ M.adjustStaminaLoss(0.4*reac_volume)
+ M.reagents.add_reagent("frostoil", 0.4*reac_volume)
+
+/datum/reagent/blob/dark_matter //does brute damage and throws or pulls nearby objects at the target
name = "Dark Matter"
id = "dark_matter"
- description = ""
color = "#61407E"
message = "You feel a thrum as the blob strikes you, and everything flies at you"
-/datum/reagent/blob/dark_matter/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH)
- var/ratio = volume/25
- M.apply_damage(15*ratio, BRUTE)
- reagent_vortex(M, 0)
+/datum/reagent/blob/dark_matter/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ reagent_vortex(M, 0, reac_volume)
+ reac_volume = ..()
+ M.apply_damage(0.6*reac_volume, BRUTE)
-
-/datum/reagent/blob/b_sorium
+/datum/reagent/blob/b_sorium //does brute damage and throws or pushes nearby objects away from the target
name = "Sorium"
id = "b_sorium"
- description = ""
color = "#808000"
message = "The blob slams into you, and sends you flying"
-/datum/reagent/blob/b_sorium/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH)
- var/ratio = volume/25
- M.apply_damage(15*ratio, BRUTE)
- reagent_vortex(M, 1)
+/datum/reagent/blob/b_sorium/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ reagent_vortex(M, 1, reac_volume)
+ reac_volume = ..()
+ M.apply_damage(0.6*reac_volume, BRUTE)
-
-/datum/reagent/blob/explosive // I'm gonna burn in hell for this one
- name = "Explosive Gelatin"
- id = "explosive"
- description = ""
- color = "#FFA500"
- message = "The blob strikes you, and its tendrils explode"
-
-/datum/reagent/blob/explosive/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH)
- var/ratio = volume/25
- if(prob(75*ratio))
- explosion(M.loc, 0, 0, 1, 0, 0)
-
-/datum/reagent/blob/omnizine
- name = "Omnizine"
- id = "b_omnizine"
- description = ""
- color = "#C8A5DC"
- message = "The blob squirts something at you"
- message_living = ", and you feel great"
-
-/datum/reagent/blob/omnizine/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH)
- var/ratio = volume/25
- M.reagents.add_reagent("omnizine", 11*ratio)
-
-/datum/reagent/blob/spacedrugs
- name = "Space drugs"
- id = "b_space_drugs"
- description = ""
- color = "#60A584"
- message = "The blob squirts something at you"
- message_living = ", and you feel funny"
-
-/datum/reagent/blob/spacedrugs/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH)
- var/ratio = volume/25
- M.hallucination += 20*ratio
- M.reagents.add_reagent("space_drugs", 15*ratio)
- M.apply_damage(10*ratio, TOX)
-
-
-/datum/reagent/blob/proc/reagent_vortex(mob/living/M, setting_type)
+/datum/reagent/blob/proc/reagent_vortex(mob/living/M, setting_type, reac_volume)
var/turf/pull = get_turf(M)
- var/range_power = Clamp(round(volume/5, 1), 1, 5)
+ var/range_power = Clamp(round(reac_volume/5, 1), 1, 5)
for(var/atom/movable/X in range(range_power,pull))
if(istype(X, /obj/effect))
continue
diff --git a/code/modules/reagents/Chemistry-Reagents/Consumable-Reagents/Drink-Reagents/Alcohols.dm b/code/modules/reagents/Chemistry-Reagents/Consumable-Reagents/Drink-Reagents/Alcohols.dm
index df637f4eab8..3732ef105f0 100644
--- a/code/modules/reagents/Chemistry-Reagents/Consumable-Reagents/Drink-Reagents/Alcohols.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Consumable-Reagents/Drink-Reagents/Alcohols.dm
@@ -29,18 +29,18 @@
M.Dizzy(5)
if(current_cycle >= boozepwr*2.5 && prob(33))
if (!M.confused) M.confused = 1
- M.confused += 3
+ M.confused += 2
if(current_cycle >= boozepwr*10 && prob(33))
M.adjustToxLoss(2)
..()
return
-/datum/reagent/consumable/ethanol/reaction_obj(obj/O, volume)
+/datum/reagent/consumable/ethanol/reaction_obj(obj/O, reac_volume)
if(istype(O,/obj/item/weapon/paper))
var/obj/item/weapon/paper/paperaffected = O
paperaffected.clearpaper()
usr << "The solution melts away the ink on the paper."
if(istype(O,/obj/item/weapon/book))
- if(volume >= 5)
+ if(reac_volume >= 5)
var/obj/item/weapon/book/affectedbook = O
affectedbook.dat = null
usr << "The solution melts away the ink on the book."
@@ -48,12 +48,12 @@
usr << "It wasn't enough..."
return
-/datum/reagent/consumable/ethanol/reaction_mob(mob/living/M, method=TOUCH, volume)//Splashing people with ethanol isn't quite as good as fuel.
+/datum/reagent/consumable/ethanol/reaction_mob(mob/living/M, method=TOUCH, reac_volume)//Splashing people with ethanol isn't quite as good as fuel.
if(!istype(M, /mob/living))
return
- if(method == TOUCH)
- M.adjust_fire_stacks(volume / 15)
- return
+ if(method == TOUCH || method == VAPOR)
+ M.adjust_fire_stacks(reac_volume / 15)
+ ..()
/datum/reagent/consumable/ethanol/beer
name = "Beer"
diff --git a/code/modules/reagents/Chemistry-Reagents/Consumable-Reagents/Food-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Consumable-Reagents/Food-Reagents.dm
index 6ca5afcf052..e8df9af6064 100644
--- a/code/modules/reagents/Chemistry-Reagents/Consumable-Reagents/Food-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Consumable-Reagents/Food-Reagents.dm
@@ -121,7 +121,7 @@
name = "Frost Oil"
id = "frostoil"
description = "A special oil that noticably chills the body. Extraced from Icepeppers."
- color = "#B31008" // rgb: 139, 166, 233
+ color = "#8BA6E9" // rgb: 139, 166, 233
/datum/reagent/consumable/frostoil/on_mob_life(mob/living/M)
switch(current_cycle)
@@ -150,8 +150,8 @@
..()
return
-/datum/reagent/consumable/frostoil/reaction_turf(turf/simulated/T, volume)
- if(volume >= 5)
+/datum/reagent/consumable/frostoil/reaction_turf(turf/simulated/T, reac_volume)
+ if(reac_volume >= 5)
for(var/mob/living/simple_animal/slime/M in T)
M.adjustToxLoss(rand(15,30))
//if(istype(T))
@@ -163,12 +163,12 @@
description = "A chemical agent used for self-defense and in police work."
color = "#B31008" // rgb: 179, 16, 8
-/datum/reagent/consumable/condensedcapsaicin/reaction_mob(mob/living/M, method=TOUCH, volume)
+/datum/reagent/consumable/condensedcapsaicin/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(!istype(M, /mob/living/carbon/human) && !istype(M, /mob/living/carbon/monkey))
return
var/mob/living/carbon/victim = M
- if(method == TOUCH)
+ if(method == TOUCH || method == VAPOR)
//check for protection
var/mouth_covered = 0
var/eyes_covered = 0
@@ -321,11 +321,10 @@
nutriment_factor = 20 * REAGENTS_METABOLISM
color = "#302000" // rgb: 48, 32, 0
-/datum/reagent/consumable/cornoil/reaction_turf(turf/simulated/T, volume)
+/datum/reagent/consumable/cornoil/reaction_turf(turf/simulated/T, reac_volume)
if (!istype(T))
return
- src = null
- if(volume >= 3)
+ if(reac_volume >= 3)
T.MakeSlippery()
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T)
if(hotspot)
@@ -380,11 +379,10 @@
reagent_state = SOLID
color = "#FFFFFF" // rgb: 0, 0, 0
-/datum/reagent/consumable/flour/reaction_turf(turf/T, volume)
- src = null
+/datum/reagent/consumable/flour/reaction_turf(turf/T, reac_volume)
if(!istype(T, /turf/space))
var/obj/effect/decal/cleanable/reagentdecal = new/obj/effect/decal/cleanable/flour(T)
- reagentdecal.reagents.add_reagent("flour", volume)
+ reagentdecal.reagents.add_reagent("flour", reac_volume)
/datum/reagent/consumable/cherryjelly
name = "Cherry Jelly"
diff --git a/code/modules/reagents/Chemistry-Reagents/Drug-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Drug-Reagents.dm
index a4854c28153..df33fc5c594 100644
--- a/code/modules/reagents/Chemistry-Reagents/Drug-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Drug-Reagents.dm
@@ -132,10 +132,10 @@
return
/datum/reagent/drug/krokodil/addiction_act_stage4(mob/living/carbon/human/M)
- if(!istype(M.dna.species, /datum/species/cosmetic_zombie))
+ if(M.has_dna() && M.dna.species.id != "zombie")
M << "Your skin falls off easily!"
M.adjustBruteLoss(50*REM) // holy shit your skin just FELL THE FUCK OFF
- hardset_dna(M, null, null, null, null, /datum/species/cosmetic_zombie)
+ M.set_species(/datum/species/cosmetic_zombie)
else
M.adjustBruteLoss(5*REM)
..()
diff --git a/code/modules/reagents/Chemistry-Reagents/Medicine-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Medicine-Reagents.dm
index 3f08110b756..43c4effc01f 100644
--- a/code/modules/reagents/Chemistry-Reagents/Medicine-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Medicine-Reagents.dm
@@ -163,23 +163,44 @@
reagent_state = LIQUID
color = "#C8A5DC"
-/datum/reagent/medicine/silver_sulfadiazine/reaction_mob(mob/living/M, method=TOUCH, volume, show_message = 1)
- if(iscarbon(M))
- if(method == TOUCH)
- M.adjustFireLoss(-volume)
+/datum/reagent/medicine/silver_sulfadiazine/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
+ if(iscarbon(M) && M.stat != DEAD)
+ if(method == PATCH)
+ M.adjustFireLoss(-reac_volume)
if(show_message)
M << "You feel your burns healing!"
M.emote("scream")
if(method == INGEST)
- M.adjustToxLoss(0.5*volume)
+ M.adjustToxLoss(0.5*reac_volume)
if(show_message)
- M << "You probably shouldn't have eaten that. Maybe you should of splashed it on, or applied a patch?"
+ M << "You probably shouldn't have eaten that. Maybe you should have splashed it on, or applied a patch?"
..()
- return
/datum/reagent/medicine/silver_sulfadiazine/on_mob_life(mob/living/M)
M.adjustFireLoss(-2*REM)
..()
+
+/datum/reagent/medicine/oxandrolone
+ name = "Oxandrolone"
+ id = "oxandrolone"
+ description = "Stimulates healing of severe burns. If you have more than 50 burn damage, it heals 2 units; otherwise, 0.5. If overdosed it will exacerbate existing burns, causing burn and brute damage."
+ reagent_state = LIQUID
+ color = "#f7ffa5"
+ metabolization_rate = 0.5 * REAGENTS_METABOLISM
+ overdose_threshold = 25
+
+/datum/reagent/medicine/oxandrolone/on_mob_life(mob/living/M)
+ if(M.getFireLoss() > 50)
+ M.adjustFireLoss(-2*REM)
+ else
+ M.adjustFireLoss(-0.5*REM)
+ ..()
+ return
+
+/datum/reagent/medicine/oxandrolone/overdose_process(mob/living/M)
+ M.adjustFireLoss(2.5*REM) // it's going to be healing either 2 or 0.5
+ M.adjustBruteLoss(0.5*REM)
+ ..()
return
/datum/reagent/medicine/styptic_powder
@@ -189,25 +210,23 @@
reagent_state = LIQUID
color = "#C8A5DC"
-/datum/reagent/medicine/styptic_powder/reaction_mob(mob/living/M, method=TOUCH, volume, show_message = 1)
- if(iscarbon(M))
- if(method == TOUCH)
- M.adjustBruteLoss(-volume)
+/datum/reagent/medicine/styptic_powder/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
+ if(iscarbon(M) && M.stat != DEAD)
+ if(method == PATCH)
+ M.adjustBruteLoss(-reac_volume)
if(show_message)
M << "You feel your wounds knitting back together!"
- if(M.stat)
- M.emote("scream")
+ M.emote("scream")
if(method == INGEST)
- M.adjustToxLoss(0.5*volume)
+ M.adjustToxLoss(0.5*reac_volume)
if(show_message)
M << "You feel kind of ill. Maybe you ate a medicine you shouldn't have?"
..()
- return
+
/datum/reagent/medicine/styptic_powder/on_mob_life(mob/living/M)
M.adjustBruteLoss(-2*REM)
..()
- return
/datum/reagent/medicine/salglu_solution
name = "Saline-Glucose Solution"
@@ -222,7 +241,6 @@
M.adjustBruteLoss(-0.5*REM)
M.adjustFireLoss(-0.5*REM)
..()
- return
/datum/reagent/medicine/mine_salve
name = "Miner's Salve"
@@ -239,20 +257,19 @@
M.adjustBruteLoss(-0.25*REM)
M.adjustFireLoss(-0.25*REM)
..()
- return
-/datum/reagent/medicine/mine_salve/reaction_mob(mob/living/M, method=TOUCH, volume, show_message = 1)
+/datum/reagent/medicine/mine_salve/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
if(iscarbon(M))
if(method == TOUCH)
if(show_message)
M << "You feel your wounds knitting back together!"
+ method = VAPOR //so it's correctly absorbed in reagent/reaction_mob()
if(method == INGEST)
if(show_message)
M << "That tasted horrible."
M.AdjustStunned(2)
M.AdjustWeakened(2)
..()
- return
/datum/reagent/medicine/mine_salve/on_mob_delete(mob/living/M)
if(iscarbon(M))
@@ -267,15 +284,15 @@
reagent_state = LIQUID
color = "#C8A5DC"
-/datum/reagent/medicine/synthflesh/reaction_mob(mob/living/M, method=TOUCH, volume,show_message = 1)
- if(iscarbon(M))
- if(method == TOUCH)
- M.adjustBruteLoss(-1.5*volume)
- M.adjustFireLoss(-1.5*volume)
+/datum/reagent/medicine/synthflesh/reaction_mob(mob/living/M, method=TOUCH, reac_volume,show_message = 1)
+ if(iscarbon(M) && M.stat != DEAD)
+ if(method == PATCH)
+ M.adjustBruteLoss(-1.5*reac_volume)
+ M.adjustFireLoss(-1.5*reac_volume)
if(show_message)
M << "You feel your burns healing and your flesh knitting together!"
..()
- return
+
/datum/reagent/medicine/charcoal
name = "Charcoal"
@@ -570,15 +587,23 @@
metabolization_rate = 0.25 * REAGENTS_METABOLISM
/datum/reagent/medicine/oculine/on_mob_life(mob/living/M)
- if(M.eye_blind > 0 && current_cycle > 20)
- if(prob(30))
+ if(current_cycle > 15)
+ if(M.disabilities & BLIND)
+ if(prob(20))
+ M.disabilities &= ~BLIND
+ M.disabilities &= NEARSIGHT
+ M.eye_blurry = 35
+
+ else if(M.disabilities & NEARSIGHT)
+ M.disabilities &= ~NEARSIGHT
+ M.eye_blurry = 10
+
+ else if(M.eye_blind || M.eye_blurry)
M.eye_blind = 0
- else if(prob(80))
- M.eye_blind = 0
- M.eye_blurry = 1
- if(M.eye_blurry > 0)
- if(prob(80))
- M.eye_blurry = 0
+ M.eye_blurry = 0
+ else if(M.eye_stat > 0)
+ M.eye_stat -= 1
+
..()
return
@@ -659,13 +684,13 @@
color = "#C8A5DC"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
-/datum/reagent/medicine/strange_reagent/reaction_mob(mob/living/carbon/human/M, method=TOUCH, volume)
+/datum/reagent/medicine/strange_reagent/reaction_mob(mob/living/carbon/human/M, method=TOUCH, reac_volume)
if(M.stat == DEAD)
if(M.getBruteLoss() >= 100 || M.getFireLoss() >= 100)
M.visible_message("[M]'s body convulses a bit, and then falls still once more.")
return
M.visible_message("[M]'s body convulses a bit.")
- if(!M.suiciding && !(NOCLONE in M.mutations))
+ if(!M.suiciding && !(M.disabilities & NOCLONE))
if(!M)
return
if(M.notify_ghost_cloning())
@@ -707,7 +732,7 @@
/datum/reagent/medicine/mutadone/on_mob_life(mob/living/carbon/human/M)
M.jitteriness = 0
- if(istype(M) && M.dna)
+ if(M.has_dna())
M.dna.remove_all_mutations()
..()
return
@@ -885,3 +910,20 @@ datum/reagent/medicine/tricordrazine/overdose_process(mob/living/M)
M.adjustFireLoss(2*REM)
..()
return
+
+datum/reagent/medicine/syndicate_nanites //Used exclusively by Syndicate medical cyborgs
+ name = "Restorative Nanites"
+ id = "syndicate_nanites"
+ description = "Miniature medical robots that swiftly restore bodily damage."
+ reagent_state = SOLID
+ color = "#555555"
+
+datum/reagent/medicine/syndicate_nanites/on_mob_life(mob/living/M)
+ M.adjustBruteLoss(-2*REM)
+ M.adjustFireLoss(-2*REM)
+ M.adjustOxyLoss(-2*REM)
+ M.adjustToxLoss(-2*REM)
+ M.adjustBrainLoss(-5*REM)
+ M.adjustCloneLoss(-1*REM)
+ ..()
+ return
diff --git a/code/modules/reagents/Chemistry-Reagents/Other-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Other-Reagents.dm
index a5975560f1c..4e0b0fbeb02 100644
--- a/code/modules/reagents/Chemistry-Reagents/Other-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Other-Reagents.dm
@@ -5,31 +5,29 @@
id = "blood"
color = "#C80000" // rgb: 200, 0, 0
-/datum/reagent/blood/reaction_mob(mob/M, method=TOUCH, volume)
- var/datum/reagent/blood/self = src
- src = null
- if(self.data && self.data["viruses"])
- for(var/datum/disease/D in self.data["viruses"])
+/datum/reagent/blood/reaction_mob(mob/M, method=TOUCH, reac_volume)
+ if(data && data["viruses"])
+ for(var/datum/disease/D in data["viruses"])
if(D.spread_flags & SPECIAL || D.spread_flags & NON_CONTAGIOUS)
continue
- if(method == TOUCH)
+ if(method == TOUCH || method == VAPOR)
M.ContractDisease(D)
- else //injected
+ else //ingest or patch
M.ForceContractDisease(D)
/datum/reagent/blood/on_new(list/data)
if(istype(data))
SetViruses(src, data)
-/datum/reagent/blood/on_merge(list/data)
- if(src.data && data)
- src.data["cloneable"] = 0 //On mix, consider the genetic sampling unviable for pod cloning, or else we won't know who's even getting cloned, etc
- if(src.data["viruses"] || data["viruses"])
+/datum/reagent/blood/on_merge(list/mix_data)
+ if(data && mix_data)
+ data["cloneable"] = 0 //On mix, consider the genetic sampling unviable for pod cloning, or else we won't know who's even getting cloned, etc
+ if(data["viruses"] || mix_data["viruses"])
- var/list/mix1 = src.data["viruses"]
- var/list/mix2 = data["viruses"]
+ var/list/mix1 = data["viruses"]
+ var/list/mix2 = mix_data["viruses"]
// Stop issues with the list changing during mixing.
var/list/to_mix = list()
@@ -42,46 +40,45 @@
var/datum/disease/advance/AD = Advance_Mix(to_mix)
if(AD)
var/list/preserve = list(AD)
- for(var/D in src.data["viruses"])
+ for(var/D in data["viruses"])
if(!istype(D, /datum/disease/advance))
preserve += D
- src.data["viruses"] = preserve
+ data["viruses"] = preserve
return 1
-/datum/reagent/blood/reaction_turf(turf/simulated/T, volume)//splash the blood all over the place
- if(!istype(T)) return
- var/datum/reagent/blood/self = src
- src = null
- if(!(volume >= 3)) return
- //var/datum/disease/D = self.data["virus"]
- if(!self.data["donor"] || istype(self.data["donor"], /mob/living/carbon/human))
+/datum/reagent/blood/reaction_turf(turf/simulated/T, reac_volume)//splash the blood all over the place
+ if(!istype(T))
+ return
+ if(reac_volume < 3)
+ return
+ if(!data["donor"] || istype(data["donor"], /mob/living/carbon/human))
var/obj/effect/decal/cleanable/blood/blood_prop = locate() in T //find some blood here
if(!blood_prop) //first blood!
blood_prop = new(T)
- blood_prop.blood_DNA[self.data["blood_DNA"]] = self.data["blood_type"]
+ blood_prop.blood_DNA[data["blood_DNA"]] = data["blood_type"]
- for(var/datum/disease/D in self.data["viruses"])
+ for(var/datum/disease/D in data["viruses"])
var/datum/disease/newVirus = D.Copy(1)
blood_prop.viruses += newVirus
newVirus.holder = blood_prop
- else if(istype(self.data["donor"], /mob/living/carbon/monkey))
+ else if(istype(data["donor"], /mob/living/carbon/monkey))
var/obj/effect/decal/cleanable/blood/blood_prop = locate() in T
if(!blood_prop)
blood_prop = new(T)
blood_prop.blood_DNA["Non-Human DNA"] = "A+"
- for(var/datum/disease/D in self.data["viruses"])
+ for(var/datum/disease/D in data["viruses"])
var/datum/disease/newVirus = D.Copy(1)
blood_prop.viruses += newVirus
newVirus.holder = blood_prop
- else if(istype(self.data["donor"], /mob/living/carbon/alien))
+ else if(istype(data["donor"], /mob/living/carbon/alien))
var/obj/effect/decal/cleanable/xenoblood/blood_prop = locate() in T
if(!blood_prop)
blood_prop = new(T)
blood_prop.blood_DNA["UNKNOWN DNA STRUCTURE"] = "X*"
- for(var/datum/disease/D in self.data["viruses"])
+ for(var/datum/disease/D in data["viruses"])
var/datum/disease/newVirus = D.Copy(1)
blood_prop.viruses += newVirus
newVirus.holder = blood_prop
@@ -93,21 +90,17 @@
id = "vaccine"
color = "#C81040" // rgb: 200, 16, 64
-/datum/reagent/vaccine/reaction_mob(mob/M, method=TOUCH, volume)
- var/datum/reagent/vaccine/self = src
- src = null
- if(islist(self.data) && method == INGEST)
+/datum/reagent/vaccine/reaction_mob(mob/M, method=TOUCH, reac_volume)
+ if(islist(data) && method == INGEST)
for(var/datum/disease/D in M.viruses)
- if(D.GetDiseaseID() in self.data)
+ if(D.GetDiseaseID() in data)
D.cure()
- M.resistances |= self.data
- return
+ M.resistances |= data
/datum/reagent/vaccine/on_merge(list/data)
if(istype(data))
src.data |= data.Copy()
-
/datum/reagent/water
name = "Water"
id = "water"
@@ -119,11 +112,10 @@
* Water reaction to turf
*/
-/datum/reagent/water/reaction_turf(turf/simulated/T, volume)
+/datum/reagent/water/reaction_turf(turf/simulated/T, reac_volume)
if (!istype(T)) return
var/CT = cooling_temperature
- src = null
- if(volume >= 10)
+ if(reac_volume >= 10)
T.MakeSlippery()
for(var/mob/living/simple_animal/slime/M in T)
@@ -142,9 +134,7 @@
* Water reaction to an object
*/
-/datum/reagent/water/reaction_obj(obj/O, volume)
- src = null
-
+/datum/reagent/water/reaction_obj(obj/O, reac_volume)
if(istype(O,/obj/item))
var/obj/item/Item = O
Item.extinguish()
@@ -166,11 +156,12 @@
* Water reaction to a mob
*/
-/datum/reagent/water/reaction_mob(mob/living/M, method=TOUCH, volume)//Splashing people with water can help put them out!
+/datum/reagent/water/reaction_mob(mob/living/M, method=TOUCH, reac_volume)//Splashing people with water can help put them out!
if(!istype(M, /mob/living))
return
if(method == TOUCH)
- M.adjust_fire_stacks(-(volume / 10))
+ M.adjust_fire_stacks(-(reac_volume / 10))
+ ..()
/datum/reagent/water/holywater
name = "Holy Water"
@@ -200,10 +191,10 @@
holder.remove_reagent(src.id, 0.4) //fixed consumption to prevent balancing going out of whack
return
-/datum/reagent/water/holywater/reaction_turf(turf/simulated/T, volume)
+/datum/reagent/water/holywater/reaction_turf(turf/simulated/T, reac_volume)
..()
if(!istype(T)) return
- if(volume>=10)
+ if(reac_volume>=10)
for(var/obj/effect/rune/R in T)
qdel(R)
T.Bless()
@@ -247,10 +238,9 @@
description = "Lubricant is a substance introduced between two moving surfaces to reduce the friction and wear between them. giggity."
color = "#009CA8" // rgb: 0, 156, 168
-/datum/reagent/lube/reaction_turf(turf/simulated/T, volume)
+/datum/reagent/lube/reaction_turf(turf/simulated/T, reac_volume)
if (!istype(T)) return
- src = null
- if(volume >= 1)
+ if(reac_volume >= 1)
T.MakeSlippery(2)
/datum/reagent/spraytan
@@ -261,9 +251,9 @@
metabolization_rate = 10 * REAGENTS_METABOLISM // very fast, so it can be applied rapidly. But this changes on an overdose
overdose_threshold = 11 //Slightly more than one un-nozzled spraybottle.
-/datum/reagent/spraytan/reaction_mob(mob/living/M, method=TOUCH, volume, show_message = 1)
+/datum/reagent/spraytan/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
if(istype(M, /mob/living/carbon/human))
- if(method == TOUCH)
+ if(method == PATCH || method == VAPOR)
var/mob/living/carbon/human/N = M
if(N.dna.species.id == "human")
switch(N.skin_tone)
@@ -366,8 +356,7 @@
var/datum/species/mutation = pick(possible_morphs)
if(prob(90) && mutation && H.dna.species != /datum/species/golem && H.dna.species != /datum/species/golem/adamantine)
H << "The pain subsides. You feel... different."
- hardset_dna(H, null, null, null, null, mutation)
- H.regenerate_icons()
+ H.set_species(mutation)
if(mutation == /datum/species/slime)
H.faction |= "slime"
else
@@ -382,9 +371,9 @@
description = "An advanced corruptive toxin produced by slimes."
color = "#13BC5E" // rgb: 19, 188, 94
-/datum/reagent/aslimetoxin/reaction_mob(mob/M, volume)
- src = null
- M.ForceContractDisease(new /datum/disease/transformation/slime(0))
+/datum/reagent/aslimetoxin/reaction_mob(mob/M, method=TOUCH, reac_volume)
+ if(method != TOUCH)
+ M.ForceContractDisease(new /datum/disease/transformation/slime(0))
/datum/reagent/serotrotium
name = "Serotrotium"
@@ -463,8 +452,7 @@
reagent_state = SOLID
color = "#1C1300" // rgb: 30, 20, 0
-/datum/reagent/carbon/reaction_turf(turf/T, volume)
- src = null
+/datum/reagent/carbon/reaction_turf(turf/T, reac_volume)
if(!istype(T, /turf/space))
new /obj/effect/decal/cleanable/dirt(T)
@@ -539,12 +527,11 @@
..()
return
-/datum/reagent/radium/reaction_turf(turf/T, volume)
- src = null
- if(volume >= 3)
+/datum/reagent/radium/reaction_turf(turf/T, reac_volume)
+ if(reac_volume >= 3)
if(!istype(T, /turf/space))
var/obj/effect/decal/cleanable/reagentdecal = new/obj/effect/decal/cleanable/greenglow(T)
- reagentdecal.reagents.add_reagent("radium", volume)
+ reagentdecal.reagents.add_reagent("radium", reac_volume)
/datum/reagent/sterilizine
name = "Sterilizine"
@@ -583,15 +570,12 @@
/datum/reagent/uranium/on_mob_life(mob/living/M)
M.apply_effect(1/M.metabolism_efficiency,IRRADIATE,0)
..()
- return
-
-/datum/reagent/uranium/reaction_turf(turf/T, volume)
- src = null
- if(volume >= 3)
+/datum/reagent/uranium/reaction_turf(turf/T, reac_volume)
+ if(reac_volume >= 3)
if(!istype(T, /turf/space))
var/obj/effect/decal/cleanable/reagentdecal = new/obj/effect/decal/cleanable/greenglow(T)
- reagentdecal.reagents.add_reagent("uranium", volume)
+ reagentdecal.reagents.add_reagent("uranium", reac_volume)
/datum/reagent/aluminium
name = "Aluminium"
@@ -613,17 +597,17 @@
description = "Required for welders. Flamable."
color = "#660000" // rgb: 102, 0, 0
-/datum/reagent/fuel/reaction_mob(mob/living/M, method=TOUCH, volume)//Splashing people with welding fuel to make them easy to ignite!
+/datum/reagent/fuel/reaction_mob(mob/living/M, method=TOUCH, reac_volume)//Splashing people with welding fuel to make them easy to ignite!
if(!istype(M, /mob/living))
return
- if(method == TOUCH)
- M.adjust_fire_stacks(volume / 10)
+ if(method == TOUCH || method == VAPOR)
+ M.adjust_fire_stacks(reac_volume / 10)
return
+ ..()
/datum/reagent/fuel/on_mob_life(mob/living/M)
M.adjustToxLoss(1)
..()
- return
/datum/reagent/space_cleaner
name = "Space cleaner"
@@ -631,56 +615,53 @@
description = "A compound used to clean things. Now with 50% more sodium hypochlorite!"
color = "#A5F0EE" // rgb: 165, 240, 238
-/datum/reagent/space_cleaner/reaction_obj(obj/O, volume)
+/datum/reagent/space_cleaner/reaction_obj(obj/O, reac_volume)
if(istype(O,/obj/effect/decal/cleanable))
qdel(O)
else
if(O)
O.clean_blood()
-/datum/reagent/space_cleaner/reaction_turf(turf/T, volume)
- if(volume >= 1)
+/datum/reagent/space_cleaner/reaction_turf(turf/T, reac_volume)
+ if(reac_volume >= 1)
T.clean_blood()
for(var/obj/effect/decal/cleanable/C in T)
qdel(C)
for(var/mob/living/simple_animal/slime/M in T)
M.adjustToxLoss(rand(5,10))
- if(istype(T, /turf/simulated/floor))
- var/turf/simulated/floor/F = T
- if(volume >= 1)
- F.dirt = 0
-/datum/reagent/space_cleaner/reaction_mob(mob/M, method=TOUCH, volume)
- if(iscarbon(M))
- var/mob/living/carbon/C = M
- if(istype(M,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- if(H.lip_style)
- H.lip_style = null
- H.update_body()
- if(C.r_hand)
- C.r_hand.clean_blood()
- if(C.l_hand)
- C.l_hand.clean_blood()
- if(C.wear_mask)
- if(C.wear_mask.clean_blood())
- C.update_inv_wear_mask()
- if(ishuman(M))
- var/mob/living/carbon/human/H = C
- if(H.head)
- if(H.head.clean_blood())
- H.update_inv_head()
- if(H.wear_suit)
- if(H.wear_suit.clean_blood())
- H.update_inv_wear_suit()
- else if(H.w_uniform)
- if(H.w_uniform.clean_blood())
- H.update_inv_w_uniform()
- if(H.shoes)
- if(H.shoes.clean_blood())
- H.update_inv_shoes()
- M.clean_blood()
+/datum/reagent/space_cleaner/reaction_mob(mob/M, method=TOUCH, reac_volume)
+ if(method == TOUCH || VAPOR)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(istype(M,/mob/living/carbon/human))
+ var/mob/living/carbon/human/H = M
+ if(H.lip_style)
+ H.lip_style = null
+ H.update_body()
+ if(C.r_hand)
+ C.r_hand.clean_blood()
+ if(C.l_hand)
+ C.l_hand.clean_blood()
+ if(C.wear_mask)
+ if(C.wear_mask.clean_blood())
+ C.update_inv_wear_mask()
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = C
+ if(H.head)
+ if(H.head.clean_blood())
+ H.update_inv_head()
+ if(H.wear_suit)
+ if(H.wear_suit.clean_blood())
+ H.update_inv_wear_suit()
+ else if(H.w_uniform)
+ if(H.w_uniform.clean_blood())
+ H.update_inv_w_uniform()
+ if(H.shoes)
+ if(H.shoes.clean_blood())
+ H.update_inv_shoes()
+ M.clean_blood()
/datum/reagent/cryptobiolin
name = "Cryptobiolin"
@@ -717,9 +698,8 @@
description = "Microscopic construction robots."
color = "#535E66" // rgb: 83, 94, 102
-/datum/reagent/nanites/reaction_mob(mob/M, method=TOUCH, volume)
- src = null
- if( (prob(min(10, volume)) && method==TOUCH) || method==INGEST)
+/datum/reagent/nanites/reaction_mob(mob/M, method=TOUCH, reac_volume, show_message = 1, touch_protection = 0)
+ if(method==PATCH || method==INGEST || (method == VAPOR && prob(min(reac_volume,100)*(1 - touch_protection))))
M.ForceContractDisease(new /datum/disease/transformation/robot(0))
/datum/reagent/xenomicrobes
@@ -728,9 +708,8 @@
description = "Microbes with an entirely alien cellular structure."
color = "#535E66" // rgb: 83, 94, 102
-/datum/reagent/xenomicrobes/reaction_mob(mob/M, method=TOUCH, volume)
- src = null
- if( (prob(min(10, volume)) && method==TOUCH) || method==INGEST)
+/datum/reagent/xenomicrobes/reaction_mob(mob/M, method=TOUCH, reac_volume, show_message = 1, touch_protection = 0)
+ if(method==PATCH || method==INGEST || (method == VAPOR && prob(min(reac_volume,100)*(1 - touch_protection))))
M.ContractDisease(new /datum/disease/transformation/xeno(0))
/datum/reagent/fluorosurfactant//foam precursor
@@ -909,7 +888,7 @@
reagent_state = LIQUID
color = "#C8A5DC"
-/datum/reagent/carpet/reaction_turf(turf/simulated/T, volume)
+/datum/reagent/carpet/reaction_turf(turf/simulated/T, reac_volume)
if(istype(T, /turf/simulated/floor/plating) || istype(T, /turf/simulated/floor/plasteel))
var/turf/simulated/floor/F = T
F.ChangeTurf(/turf/simulated/floor/carpet)
@@ -959,21 +938,20 @@
..()
return
-/datum/reagent/colorful_reagent/reaction_mob(mob/living/M, volume)
+/datum/reagent/colorful_reagent/reaction_mob(mob/living/M, reac_volume)
if(M && isliving(M))
M.color = pick(random_color_list)
..()
- return
-/datum/reagent/colorful_reagent/reaction_obj(obj/O, volume)
+
+/datum/reagent/colorful_reagent/reaction_obj(obj/O, reac_volume)
if(O)
O.color = pick(random_color_list)
..()
- return
-/datum/reagent/colorful_reagent/reaction_turf(turf/T, volume)
+
+/datum/reagent/colorful_reagent/reaction_turf(turf/T, reac_volume)
if(T)
T.color = pick(random_color_list)
..()
- return
/datum/reagent/hair_dye
name = "Quantum Hair Dye"
@@ -983,14 +961,13 @@
color = "#C8A5DC"
var/list/potential_colors = list("0ad","a0f","f73","d14","d14","0b5","0ad","f73","fc2","084","05e","d22","fa0") // fucking hair code
-/datum/reagent/hair_dye/reaction_mob(mob/living/M, volume)
- if(M && ishuman(M))
- var/mob/living/carbon/human/H = M
- H.hair_color = pick(potential_colors)
- H.facial_hair_color = pick(potential_colors)
- H.update_hair()
- ..()
- return
+/datum/reagent/hair_dye/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ if(method == TOUCH || method == VAPOR)
+ if(M && ishuman(M))
+ var/mob/living/carbon/human/H = M
+ H.hair_color = pick(potential_colors)
+ H.facial_hair_color = pick(potential_colors)
+ H.update_hair()
/datum/reagent/barbers_aid
name = "Barber's Aid"
@@ -999,16 +976,15 @@
reagent_state = LIQUID
color = "#C8A5DC"
-/datum/reagent/barbers_aid/reaction_mob(mob/living/M, volume)
- if(M && ishuman(M))
- var/mob/living/carbon/human/H = M
- var/datum/sprite_accessory/hair/picked_hair = pick(hair_styles_list)
- var/datum/sprite_accessory/facial_hair/picked_beard = pick(facial_hair_styles_list)
- H.hair_style = picked_hair
- H.facial_hair_style = picked_beard
- H.update_hair()
- ..()
- return
+/datum/reagent/barbers_aid/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ if(method == TOUCH || method == VAPOR)
+ if(M && ishuman(M))
+ var/mob/living/carbon/human/H = M
+ var/datum/sprite_accessory/hair/picked_hair = pick(hair_styles_list)
+ var/datum/sprite_accessory/facial_hair/picked_beard = pick(facial_hair_styles_list)
+ H.hair_style = picked_hair
+ H.facial_hair_style = picked_beard
+ H.update_hair()
/datum/reagent/concentrated_barbers_aid
name = "Concentrated Barber's Aid"
@@ -1017,14 +993,13 @@
reagent_state = LIQUID
color = "#C8A5DC"
-/datum/reagent/concentrated_barbers_aid/reaction_mob(mob/living/M, volume)
- if(M && ishuman(M))
- var/mob/living/carbon/human/H = M
- H.hair_style = "Very Long Hair"
- H.facial_hair_style = "Very Long Beard"
- H.update_hair()
- ..()
- return
+/datum/reagent/concentrated_barbers_aid/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ if(method == TOUCH || method == VAPOR)
+ if(M && ishuman(M))
+ var/mob/living/carbon/human/H = M
+ H.hair_style = "Very Long Hair"
+ H.facial_hair_style = "Very Long Beard"
+ H.update_hair()
/datum/reagent/saltpetre
name = "Saltpetre"
@@ -1033,3 +1008,19 @@
reagent_state = LIQUID
color = "#60A584" // rgb: 96, 165, 132
+/datum/reagent/drying_agent
+ name = "Drying agent"
+ id = "drying_agent"
+ description = "Can be used to dry things."
+ reagent_state = LIQUID
+ color = "#A70FFF"
+
+/datum/reagent/drying_agent/reaction_turf(turf/simulated/T, reac_volume)
+ if(istype(T) && T.wet)
+ T.MakeDry(TURF_WET_WATER)
+
+/datum/reagent/drying_agent/reaction_obj(obj/O, reac_volume)
+ if(O.type == /obj/item/clothing/shoes/galoshes)
+ var/t_loc = get_turf(O)
+ qdel(O)
+ new /obj/item/clothing/shoes/galoshes/dry(t_loc)
\ No newline at end of file
diff --git a/code/modules/reagents/Chemistry-Reagents/Pyrotechnic-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Pyrotechnic-Reagents.dm
index 51b06d2774e..32a253ae5de 100644
--- a/code/modules/reagents/Chemistry-Reagents/Pyrotechnic-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Pyrotechnic-Reagents.dm
@@ -6,14 +6,13 @@
reagent_state = SOLID
color = "#673910" // rgb: 103, 57, 16
-/datum/reagent/thermite/reaction_turf(turf/T, volume)
- src = null
- if(volume >= 1 && istype(T, /turf/simulated/wall))
+/datum/reagent/thermite/reaction_turf(turf/T, reac_volume)
+ if(reac_volume >= 1 && istype(T, /turf/simulated/wall))
var/turf/simulated/wall/Wall = T
if(istype(Wall, /turf/simulated/wall/r_wall))
- Wall.thermite = Wall.thermite+(volume*2.5)
+ Wall.thermite = Wall.thermite+(reac_volume*2.5)
else
- Wall.thermite = Wall.thermite+(volume*10)
+ Wall.thermite = Wall.thermite+(reac_volume*10)
Wall.overlays = list()
Wall.overlays += image('icons/effects/effects.dmi',"thermite")
@@ -40,7 +39,7 @@
description = "Makes a temporary 3x3 fireball when it comes into existence, so be careful when mixing. ClF3 applied to a surface burns things that wouldn't otherwise burn, sometimes through the very floors of the station and exposing it to the vacuum of space."
reagent_state = LIQUID
color = "#FF0000"
- metabolization_rate = 0.5 * REAGENTS_METABOLISM
+ metabolization_rate = 4
/datum/reagent/clf3/on_mob_life(mob/living/M)
M.adjust_fire_stacks(2)
@@ -48,29 +47,30 @@
M.adjustFireLoss(burndmg)
..()
-/datum/reagent/clf3/reaction_turf(turf/simulated/T, volume)
+/datum/reagent/clf3/reaction_turf(turf/simulated/T, reac_volume)
if(istype(T, /turf/simulated/floor/plating))
var/turf/simulated/floor/plating/F = T
if(prob(1 + F.burnt + 5*F.broken)) //broken or burnt plating is more susceptible to being destroyed
F.ChangeTurf(F.baseturf)
if(istype(T, /turf/simulated/floor/))
var/turf/simulated/floor/F = T
- if(prob(volume/10))
+ if(prob(reac_volume/10))
F.make_plating()
- else if(prob(volume))
+ else if(prob(reac_volume))
F.burn_tile()
if(istype(F, /turf/simulated/floor/))
PoolOrNew(/obj/effect/hotspot, F)
if(istype(T, /turf/simulated/wall/))
var/turf/simulated/wall/W = T
- if(prob(volume/10))
+ if(prob(reac_volume/10))
W.ChangeTurf(/turf/simulated/floor/plating)
-/datum/reagent/clf3/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH && isliving(M))
- M.adjust_fire_stacks(min(volume/5, 10))
- M.IgniteMob()
- PoolOrNew(/obj/effect/hotspot, M.loc)
+/datum/reagent/clf3/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ if(istype(M))
+ if(method != INGEST)
+ M.adjust_fire_stacks(min(reac_volume/5, 10))
+ M.IgniteMob()
+ PoolOrNew(/obj/effect/hotspot, M.loc)
/datum/reagent/sorium
name = "Sorium"
@@ -128,8 +128,8 @@
description = "Catches you on fire and makes you ignite."
reagent_state = LIQUID
color = "#FF9999"
-
-/datum/reagent/phlogiston/reaction_mob(mob/living/M, method=TOUCH, volume)
+
+/datum/reagent/phlogiston/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
M.IgniteMob()
..()
@@ -150,9 +150,10 @@
M.adjust_fire_stacks(1)
..()
-/datum/reagent/napalm/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH && isliving(M))
- M.adjust_fire_stacks(min(volume/4, 20))
+/datum/reagent/napalm/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ if(istype(M))
+ if(method != INGEST)
+ M.adjust_fire_stacks(min(reac_volume/4, 20))
/datum/reagent/cryostylane
name = "Cryostylane"
@@ -175,8 +176,8 @@
holder.handle_reactions()
..()
-/datum/reagent/cryostylane/reaction_turf(turf/simulated/T, volume)
- if(volume >= 5)
+/datum/reagent/cryostylane/reaction_turf(turf/simulated/T, reac_volume)
+ if(reac_volume >= 5)
for(var/mob/living/simple_animal/slime/M in T)
M.adjustToxLoss(rand(15,30))
diff --git a/code/modules/reagents/Chemistry-Reagents/Toxin-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Toxin-Reagents.dm
index 2672d7e678a..aaaaf09c20e 100644
--- a/code/modules/reagents/Chemistry-Reagents/Toxin-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Toxin-Reagents.dm
@@ -28,27 +28,25 @@
color = "#13BC5E" // rgb: 19, 188, 94
toxpwr = 0
-/datum/reagent/toxin/mutagen/reaction_mob(mob/living/carbon/M, method=TOUCH, volume)
+/datum/reagent/toxin/mutagen/reaction_mob(mob/living/carbon/M, method=TOUCH, reac_volume)
if(!..())
return
- if(!istype(M) || !M.dna)
+ if(!M.has_dna())
return //No robots, AIs, aliens, Ians or other mobs should be affected by this.
- src = null
- if((method==TOUCH && prob(min(33, volume))) || method==INGEST)
+ if((method==VAPOR && prob(min(33, reac_volume))) || method==INGEST || method == PATCH)
randmuti(M)
if(prob(98))
randmutb(M)
else
randmutg(M)
- domutcheck(M, null)
- updateappearance(M)
- return
+ M.updateappearance()
+ M.domutcheck()
+ ..()
/datum/reagent/toxin/mutagen/on_mob_life(mob/living/carbon/M)
if(istype(M))
M.apply_effect(5,IRRADIATE,0)
..()
- return
/datum/reagent/toxin/plasma
name = "Plasma"
@@ -66,27 +64,23 @@
..()
return
-/datum/reagent/toxin/plasma/reaction_obj(obj/O, volume)
- src = null
- /*if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/egg/slime))
- var/obj/item/weapon/reagent_containers/food/snacks/egg/slime/egg = O
- if (egg.grown)
- egg.Hatch()*/
- if((!O) || (!volume)) return 0
- O.atmos_spawn_air(SPAWN_TOXINS|SPAWN_20C, volume)
+/datum/reagent/toxin/plasma/reaction_obj(obj/O, reac_volume)
+ if((!O) || (!reac_volume))
+ return 0
+ O.atmos_spawn_air(SPAWN_TOXINS|SPAWN_20C, reac_volume)
-/datum/reagent/toxin/plasma/reaction_turf(turf/simulated/T, volume)
- src = null
+/datum/reagent/toxin/plasma/reaction_turf(turf/simulated/T, reac_volume)
if(istype(T))
- T.atmos_spawn_air(SPAWN_TOXINS|SPAWN_20C, volume)
+ T.atmos_spawn_air(SPAWN_TOXINS|SPAWN_20C, reac_volume)
return
-/datum/reagent/toxin/plasma/reaction_mob(mob/living/M, method=TOUCH, volume)//Splashing people with plasma is stronger than fuel!
+/datum/reagent/toxin/plasma/reaction_mob(mob/living/M, method=TOUCH, reac_volume)//Splashing people with plasma is stronger than fuel!
if(!istype(M, /mob/living))
return
- if(method == TOUCH)
- M.adjust_fire_stacks(volume / 5)
+ if(method == TOUCH || method == VAPOR)
+ M.adjust_fire_stacks(reac_volume / 5)
return
+ ..()
/datum/reagent/toxin/lexorin
name = "Lexorin"
@@ -129,7 +123,7 @@
toxpwr = 0
/datum/reagent/toxin/minttoxin/on_mob_life(mob/living/M)
- if (FAT in M.mutations)
+ if (M.disabilities & FAT)
M.gib()
..()
return
@@ -181,7 +175,7 @@
color = "#49002E" // rgb: 73, 0, 46
toxpwr = 1
-/datum/reagent/toxin/plantbgone/reaction_obj(obj/O, volume)
+/datum/reagent/toxin/plantbgone/reaction_obj(obj/O, reac_volume)
if(istype(O,/obj/structure/alien/weeds/))
var/obj/structure/alien/weeds/alien_weeds = O
alien_weeds.health -= rand(15,35) // Kills alien weeds pretty fast
@@ -192,13 +186,14 @@
var/obj/effect/spacevine/SV = O
SV.on_chem_effect(src)
-/datum/reagent/toxin/plantbgone/reaction_mob(mob/living/M, method=TOUCH, volume)
- src = null
- if(iscarbon(M))
- var/mob/living/carbon/C = M
- if(!C.wear_mask) // If not wearing a mask
- var/damage = min(round(0.4*volume, 0.1),10)
- C.adjustToxLoss(damage)
+/datum/reagent/toxin/plantbgone/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ if(method == VAPOR)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(!C.wear_mask) // If not wearing a mask
+ var/damage = min(round(0.4*reac_volume, 0.1),10)
+ C.adjustToxLoss(damage)
+
/datum/reagent/toxin/plantbgone/weedkiller
name = "Weed Killer"
id = "weedkiller"
@@ -213,20 +208,20 @@
color = "#4B004B" // rgb: 75, 0, 75
toxpwr = 1
-/datum/reagent/toxin/pestkiller/reaction_mob(mob/living/M, method=TOUCH, volume)
- src = null
- if(iscarbon(M))
- var/mob/living/carbon/C = M
- if(!C.wear_mask) // If not wearing a mask
- var/damage = min(round(0.4*volume, 0.1),10)
- C.adjustToxLoss(damage)
+/datum/reagent/toxin/pestkiller/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ if(method == VAPOR)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(!C.wear_mask) // If not wearing a mask
+ var/damage = min(round(0.4*reac_volume, 0.1),10)
+ C.adjustToxLoss(damage)
/datum/reagent/toxin/spore
name = "Spore Toxin"
id = "spore"
description = "A toxic spore cloud which blocks vision when ingested."
color = "#9ACD32"
- toxpwr = 0.5
+ toxpwr = 1
/datum/reagent/toxin/spore/on_mob_life(mob/living/M)
M.damageoverlaytemp = 60
@@ -456,10 +451,9 @@
metabolization_rate = 0.4 * REAGENTS_METABOLISM
toxpwr = 0
-/datum/reagent/toxin/itching_powder/reaction_mob(mob/living/M, method=TOUCH, volume)
- if(method == TOUCH)
- M.reagents.add_reagent("itching_powder", volume)
- return
+/datum/reagent/toxin/itching_powder/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
+ if(method != INGEST)
+ M.reagents.add_reagent("itching_powder", reac_volume)
/datum/reagent/toxin/itching_powder/on_mob_life(mob/living/M)
if(prob(15))
@@ -623,21 +617,27 @@
toxpwr = 1
var/acidpwr = 10 //the amount of protection removed from the armour
-/datum/reagent/toxin/acid/reaction_mob(mob/living/carbon/C, method=TOUCH, volume)
+/datum/reagent/toxin/acid/reaction_mob(mob/living/carbon/C, method=TOUCH, reac_volume)
if(!istype(C))
return
- volume = round(volume,0.1)
- if(method != TOUCH)
- C.take_organ_damage(min(6*toxpwr, volume * toxpwr))
+ reac_volume = round(reac_volume,0.1)
+ if(method == INGEST)
+ C.take_organ_damage(min(6*toxpwr, reac_volume * toxpwr))
return
+ C.acid_act(acidpwr, toxpwr, reac_volume)
- C.acid_act(acidpwr, toxpwr, volume)
-
-/datum/reagent/toxin/acid/reaction_obj(obj/O, volume)
+/datum/reagent/toxin/acid/reaction_obj(obj/O, reac_volume)
if(istype(O.loc, /mob)) //handled in human acid_act()
return
- volume = round(volume,0.1)
- O.acid_act(acidpwr, toxpwr, volume)
+ reac_volume = round(reac_volume,0.1)
+ O.acid_act(acidpwr, reac_volume)
+
+/datum/reagent/toxin/acid/reaction_turf(turf/T, reac_volume)
+ if (!istype(T))
+ return
+ reac_volume = round(reac_volume,0.1)
+ for(var/obj/O in T)
+ O.acid_act(acidpwr, reac_volume)
/datum/reagent/toxin/acid/fluacid
name = "Fluorosulfuric acid"
diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm
index e7f7014e135..84822634782 100644
--- a/code/modules/reagents/Chemistry-Recipes.dm
+++ b/code/modules/reagents/Chemistry-Recipes.dm
@@ -21,43 +21,18 @@
return
//I recommend you set the result amount to the total volume of all components.
-
+var/list/chemical_mob_spawn_meancritters = list() // list of possible hostile mobs
+var/list/chemical_mob_spawn_nicecritters = list() // and possible friendly mobs
/datum/chemical_reaction/proc/chemical_mob_spawn(datum/reagents/holder, amount_to_spawn, reaction_name, mob_faction = "chemicalsummon")
if(holder && holder.my_atom)
- var/blocked = list(/mob/living/simple_animal/hostile,
- /mob/living/simple_animal/hostile/pirate,
- /mob/living/simple_animal/hostile/pirate/ranged,
- /mob/living/simple_animal/hostile/russian,
- /mob/living/simple_animal/hostile/russian/ranged,
- /mob/living/simple_animal/hostile/syndicate,
- /mob/living/simple_animal/hostile/syndicate/melee,
- /mob/living/simple_animal/hostile/syndicate/melee/space,
- /mob/living/simple_animal/hostile/syndicate/ranged,
- /mob/living/simple_animal/hostile/syndicate/ranged/space,
- /mob/living/simple_animal/hostile/alien/queen/large,
- /mob/living/simple_animal/hostile/mushroom,
- /mob/living/simple_animal/hostile/asteroid,
- /mob/living/simple_animal/hostile/retaliate,
- /mob/living/simple_animal/hostile/asteroid/basilisk,
- /mob/living/simple_animal/hostile/asteroid/goldgrub,
- /mob/living/simple_animal/hostile/asteroid/goliath,
- /mob/living/simple_animal/hostile/asteroid/hivelord,
- /mob/living/simple_animal/hostile/asteroid/hivelordbrood,
- /mob/living/simple_animal/hostile/carp/holocarp,
- /mob/living/simple_animal/hostile/mining_drone,
- /mob/living/simple_animal/hostile/poison,
- /mob/living/simple_animal/hostile/blob,
- /mob/living/simple_animal/ascendant_shadowling
- )//exclusion list for things you don't want the reaction to create.
- var/list/meancritters = typesof(/mob/living/simple_animal/hostile) - blocked // list of possible hostile mobs
- var/list/nicecritters = list(/mob/living/simple_animal/crab,
- /mob/living/simple_animal/mouse,
- /mob/living/simple_animal/lizard,
- /mob/living/simple_animal/parrot,
- /mob/living/simple_animal/butterfly,
- /mob/living/simple_animal/cow,
- /mob/living/simple_animal/chicken) // and possible friendly mobs
- nicecritters += typesof(/mob/living/simple_animal/pet) - /mob/living/simple_animal/pet
+ if (chemical_mob_spawn_meancritters.len <= 0 || chemical_mob_spawn_nicecritters.len <= 0)
+ for (var/T in typesof(/mob/living/simple_animal))
+ var/mob/living/simple_animal/SA = T
+ switch(initial(SA.gold_core_spawnable))
+ if(1)
+ chemical_mob_spawn_meancritters += T
+ if(2)
+ chemical_mob_spawn_nicecritters += T
var/atom/A = holder.my_atom
var/turf/T = get_turf(A)
var/area/my_area = get_area(T)
@@ -77,22 +52,17 @@
for(var/mob/living/carbon/C in viewers(get_turf(holder.my_atom), null))
C.flash_eyes()
for(var/i = 1, i <= amount_to_spawn, i++)
+ var/chosen
if (reaction_name == "Friendly Gold Slime")
- var/chosen = pick(nicecritters)
- var/mob/living/simple_animal/C = new chosen
- C.faction |= mob_faction
- C.loc = get_turf(holder.my_atom)
- if(prob(50))
- for(var/j = 1, j <= rand(1, 3), j++)
- step(C, pick(NORTH,SOUTH,EAST,WEST))
+ chosen = pick(chemical_mob_spawn_nicecritters)
else
- var/chosen = pick(meancritters)
- var/mob/living/simple_animal/hostile/C = new chosen
- C.faction |= mob_faction
- C.loc = get_turf(holder.my_atom)
- if(prob(50))
- for(var/j = 1, j <= rand(1, 3), j++)
- step(C, pick(NORTH,SOUTH,EAST,WEST))
+ chosen = pick(chemical_mob_spawn_meancritters)
+ var/mob/living/simple_animal/C = new chosen
+ C.faction |= mob_faction
+ C.loc = get_turf(holder.my_atom)
+ if(prob(50))
+ for(var/j = 1, j <= rand(1, 3), j++)
+ step(C, pick(NORTH,SOUTH,EAST,WEST))
/datum/chemical_reaction/proc/goonchem_vortex(turf/simulated/T, setting_type, range)
for(var/atom/movable/X in orange(range, T))
@@ -118,4 +88,4 @@
for(var/i = 0, i < moving_power, i++)
sleep(2)
if(!step_towards(X, T))
- break
\ No newline at end of file
+ break
diff --git a/code/modules/reagents/Chemistry-Recipes/Medicine.dm b/code/modules/reagents/Chemistry-Recipes/Medicine.dm
index 60e80923400..3ccc5753cc2 100644
--- a/code/modules/reagents/Chemistry-Recipes/Medicine.dm
+++ b/code/modules/reagents/Chemistry-Recipes/Medicine.dm
@@ -116,6 +116,12 @@
required_reagents = list("sodium" = 1, "phenol" = 1, "carbon" = 1, "oxygen" = 1, "sacid" = 1)
result_amount = 5
+/datum/chemical_reaction/oxandrolone
+ name = "Oxandrolone"
+ id = "oxandrolone"
+ result = "oxandrolone"
+ required_reagents = list("carbon" = 3, "phenol" = 1, "hydrogen" = 1, "oxygen" = 1)
+ result_amount = 6
/datum/chemical_reaction/salbutamol
name = "Salbutamol"
diff --git a/code/modules/reagents/Chemistry-Recipes/Others.dm b/code/modules/reagents/Chemistry-Recipes/Others.dm
index aa015604409..c3614639f7b 100644
--- a/code/modules/reagents/Chemistry-Recipes/Others.dm
+++ b/code/modules/reagents/Chemistry-Recipes/Others.dm
@@ -12,14 +12,14 @@
result = "lube"
required_reagents = list("water" = 1, "silicon" = 1, "oxygen" = 1)
result_amount = 4
-
+
/datum/chemical_reaction/spraytan
name = "Spray Tan"
id = "spraytan"
result = "spraytan"
required_reagents = list("orangejuice" = 1, "oil" = 1)
result_amount = 2
-
+
/datum/chemical_reaction/spraytan2
name = "Spray Tan"
id = "spraytan"
@@ -254,6 +254,12 @@
required_reagents = list("toxin" = 1, "ethanol" = 4)
result_amount = 5
+/datum/chemical_reaction/drying_agent
+ name = "Drying agent"
+ id = "drying_agent"
+ result = "drying_agent"
+ required_reagents = list("stable_plasma" = 2, "ethanol" = 1, "sodium" = 1)
+ result_amount = 3
//////////////////////////////////// Other goon stuff ///////////////////////////////////////////
diff --git a/code/modules/reagents/Chemistry-Recipes/Slime_extracts.dm b/code/modules/reagents/Chemistry-Recipes/Slime_extracts.dm
index a0b76e0bad4..bf01060db8f 100644
--- a/code/modules/reagents/Chemistry-Recipes/Slime_extracts.dm
+++ b/code/modules/reagents/Chemistry-Recipes/Slime_extracts.dm
@@ -10,7 +10,7 @@
required_other = 1
/datum/chemical_reaction/slimespawn/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/mob/living/simple_animal/slime/S = new /mob/living/simple_animal/slime
S.loc = get_turf(holder.my_atom)
S.visible_message("Infused with plasma, the core begins to quiver and grow, and soon a new baby slime emerges from it!")
@@ -25,7 +25,7 @@
required_container = /obj/item/slime_extract/grey
/datum/chemical_reaction/slimeinaprov/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
/datum/chemical_reaction/slimemonkey
name = "Slime Monkey"
@@ -37,7 +37,7 @@
required_other = 1
/datum/chemical_reaction/slimemonkey/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
for(var/i = 1, i <= 3, i++)
var /obj/item/weapon/reagent_containers/food/snacks/monkeycube/M = new /obj/item/weapon/reagent_containers/food/snacks/monkeycube
M.loc = get_turf(holder.my_atom)
@@ -53,7 +53,7 @@
required_container = /obj/item/slime_extract/green
/datum/chemical_reaction/slimemutate/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
//Mutated Green
/datum/chemical_reaction/slimemutate_unstable
@@ -67,7 +67,7 @@
mix_message = "The mixture rapidly expands and contracts, its appearance shifting into a sickening green."
/datum/chemical_reaction/slimemutate_unstable/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
//Metal
/datum/chemical_reaction/slimemetal
@@ -80,7 +80,7 @@
required_other = 1
/datum/chemical_reaction/slimemetal/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/obj/item/stack/sheet/metal/M = new /obj/item/stack/sheet/metal
M.amount = 15
M.loc = get_turf(holder.my_atom)
@@ -99,7 +99,7 @@
required_other = 1
/datum/chemical_reaction/slimecrit/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
for(var/mob/O in viewers(get_turf(holder.my_atom), null))
O.show_message(text("The slime extract begins to vibrate violently !"), 1)
spawn(50)
@@ -116,7 +116,7 @@
required_other = 1
/datum/chemical_reaction/slimecritlesser/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
for(var/mob/O in viewers(get_turf(holder.my_atom), null))
O.show_message(text("The slime extract begins to vibrate violently !"), 1)
spawn(50)
@@ -133,7 +133,7 @@
required_other = 1
/datum/chemical_reaction/slimecritfriendly/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
for(var/mob/O in viewers(get_turf(holder.my_atom), null))
O.show_message(text("The slime extract begins to vibrate adorably !"), 1)
spawn(50)
@@ -152,7 +152,7 @@
/datum/chemical_reaction/slimebork/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/list/blocked = list(/obj/item/weapon/reagent_containers/food/snacks,
/obj/item/weapon/reagent_containers/food/snacks/store/bread,
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
@@ -200,7 +200,7 @@
/datum/chemical_reaction/slimebork2/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/list/blocked = list(/obj/item/weapon/reagent_containers/food/drinks)
var/list/borks = typesof(/obj/item/weapon/reagent_containers/food/drinks) - blocked
@@ -232,7 +232,7 @@
required_other = 1
/datum/chemical_reaction/slimefrost/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
/datum/chemical_reaction/slimestabilizer
@@ -245,8 +245,8 @@
required_other = 1
/datum/chemical_reaction/slimestabilizer/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
- var/obj/item/weapon/slimestabilizer/P = new /obj/item/weapon/slimestabilizer
+ feedback_add_details("slime_cores_used","[type]")
+ var/obj/item/slimepotion/stabilizer/P = new /obj/item/slimepotion/stabilizer
P.loc = get_turf(holder.my_atom)
@@ -262,7 +262,7 @@
required_other = 1
/datum/chemical_reaction/slimefreeze/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
for(var/mob/O in viewers(get_turf(holder.my_atom), null))
O.show_message(text("The slime extract begins to vibrate violently !"), 1)
spawn(50)
@@ -283,7 +283,7 @@
required_other = 1
/datum/chemical_reaction/slimecasp/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
/datum/chemical_reaction/slimefire
name = "Slime fire"
@@ -295,7 +295,7 @@
required_other = 1
/datum/chemical_reaction/slimefire/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
for(var/mob/O in viewers(get_turf(holder.my_atom), null))
O.show_message(text("The slime extract begins to vibrate violently !"), 1)
spawn(50)
@@ -316,7 +316,7 @@
required_other = 1
/datum/chemical_reaction/slimeoverload/on_reaction(datum/reagents/holder, created_volume)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
empulse(get_turf(holder.my_atom), 3, 7)
@@ -330,7 +330,7 @@
required_other = 1
/datum/chemical_reaction/slimecell/on_reaction(datum/reagents/holder, created_volume)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/obj/item/weapon/stock_parts/cell/high/slime/P = new /obj/item/weapon/stock_parts/cell/high/slime
P.loc = get_turf(holder.my_atom)
@@ -344,7 +344,7 @@
required_other = 1
/datum/chemical_reaction/slimeglow/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
for(var/mob/O in viewers(get_turf(holder.my_atom), null))
O.show_message(text("The slime begins to emit a soft light. Squeezing it will cause it to grow brightly."), 1)
var/obj/item/device/flashlight/slime/F = new /obj/item/device/flashlight/slime
@@ -362,8 +362,8 @@
required_other = 1
/datum/chemical_reaction/slimepsteroid/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
- var/obj/item/weapon/slimesteroid/P = new /obj/item/weapon/slimesteroid
+ feedback_add_details("slime_cores_used","[type]")
+ var/obj/item/slimepotion/steroid/P = new /obj/item/slimepotion/steroid
P.loc = get_turf(holder.my_atom)
/datum/chemical_reaction/slimejam
@@ -376,7 +376,7 @@
required_other = 1
/datum/chemical_reaction/slimejam/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
//Dark Purple
@@ -390,25 +390,11 @@
required_other = 1
/datum/chemical_reaction/slimeplasma/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/obj/item/stack/sheet/mineral/plasma/P = new /obj/item/stack/sheet/mineral/plasma
P.amount = 10
P.loc = get_turf(holder.my_atom)
-//Red
-/*/datum/chemical_reaction/slimeglycerol
- name = "Slime Glycerol"
- id = "m_glycerol"
- result = "glycerol"
- required_reagents = list("plasma" = 1)
- result_amount = 8
- required_container = /obj/item/slime_extract/red
- required_other = 1
-
-/datum/chemical_reaction/slimeglycerol/on_reaction(var/datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
-*/
-
/datum/chemical_reaction/slimemutator
name = "Slime Mutator"
id = "m_slimemutator"
@@ -419,8 +405,8 @@
required_other = 1
/datum/chemical_reaction/slimemutator/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
- var/obj/item/weapon/slimemutator/P = new /obj/item/weapon/slimemutator
+ feedback_add_details("slime_cores_used","[type]")
+ var/obj/item/slimepotion/mutator/P = new /obj/item/slimepotion/mutator
P.loc = get_turf(holder.my_atom)
/datum/chemical_reaction/slimebloodlust
@@ -433,15 +419,15 @@
required_other = 1
/datum/chemical_reaction/slimebloodlust/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
for(var/mob/living/simple_animal/slime/slime in viewers(get_turf(holder.my_atom), null))
slime.rabid = 1
for(var/mob/O in viewers(get_turf(holder.my_atom), null))
O.show_message(text("The [slime] is driven into a frenzy!"), 1)
//Pink
-/datum/chemical_reaction/slimeppotion
- name = "Slime Potion"
+/datum/chemical_reaction/docility
+ name = "Docility Potion"
id = "m_potion"
result = null
required_reagents = list("plasma" = 1)
@@ -449,9 +435,9 @@
required_container = /obj/item/slime_extract/pink
required_other = 1
-/datum/chemical_reaction/slimeppotion/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
- var/obj/item/slimepotion/P = new /obj/item/slimepotion
+/datum/chemical_reaction/docility/on_reaction(datum/reagents/holder)
+ feedback_add_details("slime_cores_used","[type]")
+ var/obj/item/slimepotion/docility/P = new /obj/item/slimepotion/docility
P.loc = get_turf(holder.my_atom)
@@ -466,7 +452,7 @@
required_container = /obj/item/slime_extract/black
/datum/chemical_reaction/slimemutate2/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
//Oil
/datum/chemical_reaction/slimeexplosion
@@ -479,7 +465,7 @@
required_other = 1
/datum/chemical_reaction/slimeexplosion/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
for(var/mob/O in viewers(get_turf(holder.my_atom), null))
O.show_message(text("The slime extract begins to vibrate violently !"), 1)
spawn(50)
@@ -497,8 +483,8 @@
required_other = 1
/datum/chemical_reaction/slimepotion2/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
- var/obj/item/slimepotion2/P = new /obj/item/slimepotion2
+ feedback_add_details("slime_cores_used","[type]")
+ var/obj/item/slimepotion/sentience/P = new /obj/item/slimepotion/sentience
P.loc = get_turf(holder.my_atom)
//Adamantine
@@ -512,7 +498,7 @@
required_other = 1
/datum/chemical_reaction/slimegolem/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/obj/effect/golemrune/Z = new /obj/effect/golemrune
Z.loc = get_turf(holder.my_atom)
notify_ghosts("Golem rune created in [get_area(Z)].", 'sound/effects/ghost2.ogg')
@@ -528,7 +514,7 @@
required_other = 1
/datum/chemical_reaction/slimefloor2/on_reaction(datum/reagents/holder, created_volume)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/obj/item/stack/tile/bluespace/P = new /obj/item/stack/tile/bluespace
P.amount = 25
P.loc = get_turf(holder.my_atom)
@@ -544,7 +530,7 @@
required_other = 1
/datum/chemical_reaction/slimecrystal/on_reaction(datum/reagents/holder, created_volume)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
if(holder.my_atom)
var/obj/item/bluespace_crystal/BC = new(get_turf(holder.my_atom))
BC.visible_message("The [BC.name] appears out of thin air!")
@@ -560,8 +546,8 @@
required_other = 1
/datum/chemical_reaction/slimepsteroid2/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
- var/obj/item/weapon/slimesteroid2/P = new /obj/item/weapon/slimesteroid2
+ feedback_add_details("slime_cores_used","[type]")
+ var/obj/item/slimepotion/enhancer/P = new /obj/item/slimepotion/enhancer
P.loc = get_turf(holder.my_atom)
//Sepia
@@ -575,11 +561,11 @@
required_other = 1
/datum/chemical_reaction/slimestop/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/mob/mob = get_mob_by_key(holder.my_atom.fingerprintslast)
var/obj/effect/timestop/T = new /obj/effect/timestop
T.loc = get_turf(holder.my_atom)
- T.immune = mob
+ T.immune += mob
T.timestop()
@@ -593,7 +579,7 @@
required_other = 1
/datum/chemical_reaction/slimecamera/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/obj/item/device/camera/P = new /obj/item/device/camera
P.loc = get_turf(holder.my_atom)
var/obj/item/device/camera_film/Z = new /obj/item/device/camera_film
@@ -609,7 +595,7 @@
required_other = 1
/datum/chemical_reaction/slimefloor/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/obj/item/stack/tile/sepia/P = new /obj/item/stack/tile/sepia
P.amount = 25
P.loc = get_turf(holder.my_atom)
@@ -628,7 +614,7 @@
required_other = 1
/datum/chemical_reaction/slimepaint/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/list/paints = typesof(/obj/item/weapon/paint) - /obj/item/weapon/paint
var/chosen = pick(paints)
var/obj/P = new chosen
@@ -646,7 +632,7 @@
required_container = /obj/item/slime_extract/rainbow
/datum/chemical_reaction/slimeRNG/on_reaction(datum/reagents/holder)
- feedback_add_details("slime_cores_used","[replacetext(name," ","_")]")
+ feedback_add_details("slime_cores_used","[type]")
var/mob/living/simple_animal/slime/S = new /mob/living/simple_animal/slime
S.colour = pick("grey","orange", "metal", "blue", "purple", "dark purple", "dark blue", "green", "silver", "yellow", "gold", "yellow", "red", "silver", "pink", "cerulean", "sepia", "bluespace", "pyrite", "light pink", "oil", "adamantine", "black")
S.loc = get_turf(holder.my_atom)
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index 99f7e10089c..dd63e9c86d9 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -106,5 +106,7 @@
else
visible_message("[src] spills its contents all over [target].")
reagents.reaction(target, TOUCH)
+ if(qdeleted(src))
+ return
reagents.clear_reagents()
diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm
index ab68ee49f79..51e5e9e8756 100644
--- a/code/modules/reagents/reagent_containers/borghydro.dm
+++ b/code/modules/reagents/reagent_containers/borghydro.dm
@@ -43,7 +43,7 @@ Borg Hypospray
/obj/item/weapon/reagent_containers/borghypo/Destroy()
SSobj.processing.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/reagent_containers/borghypo/process() //Every [recharge_time] seconds, recharge some reagents for the cyborg
@@ -125,6 +125,15 @@ Borg Hypospray
if(empty)
usr << "It is currently empty! Allow some time for the internal syntheszier to produce more."
+
+/obj/item/weapon/reagent_containers/borghypo/syndicate
+ name = "syndicate cyborg hypospray"
+ desc = "A modified hypospray that generates reagents more quickly and consumes less power."
+ icon_state = "borghypo_s"
+ charge_cost = 20
+ recharge_time = 2
+ reagent_ids = list("syndicate_nanites", "potass_iodide", "morphine")
+
/*
Borg Shaker
*/
diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm
index 0da770be3ec..756aeb33d24 100644
--- a/code/modules/reagents/reagent_containers/glass.dm
+++ b/code/modules/reagents/reagent_containers/glass.dm
@@ -122,7 +122,7 @@
/obj/item/weapon/reagent_containers/glass/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/clothing/mask/cigarette)) //ciggies are weird
return
- var/hotness = is_hot(I)
+ var/hotness = I.is_hot()
if(hotness)
var/added_heat = (hotness / 100) //ishot returns a temperature
if(reagents)
@@ -253,7 +253,7 @@
icon_state = "bucket"
item_state = "bucket"
materials = list(MAT_METAL=200)
- w_class = 3.0
+ w_class = 3
amount_per_transfer_from_this = 20
possible_transfer_amounts = list(10,20,30,50,70)
volume = 70
diff --git a/code/modules/reagents/reagent_containers/patch.dm b/code/modules/reagents/reagent_containers/patch.dm
index f87d3682a7c..1b475da801e 100644
--- a/code/modules/reagents/reagent_containers/patch.dm
+++ b/code/modules/reagents/reagent_containers/patch.dm
@@ -6,7 +6,7 @@
item_state = "bandaid"
possible_transfer_amounts = null
volume = 50
- apply_type = TOUCH
+ apply_type = PATCH
apply_method = "apply"
/obj/item/weapon/reagent_containers/pill/patch/New()
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index 2a99e768c75..94ece6ee2c0 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -133,6 +133,12 @@
icon_state = "pill5"
list_reagents = list("sal_acid" = 24)
roundstart = 1
+/obj/item/weapon/reagent_containers/pill/oxandrolone
+ name = "oxandrolone pill"
+ desc = "Used to stimulate burn healing."
+ icon_state = "pill5"
+ list_reagents = list("oxandrolone" = 24)
+ roundstart = 1
/obj/item/weapon/reagent_containers/pill/insulin
name = "insulin pill"
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index 73923de0f62..b35b9330ab7 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -7,7 +7,7 @@
flags = OPENCONTAINER | NOBLUDGEON
slot_flags = SLOT_BELT
throwforce = 0
- w_class = 2.0
+ w_class = 2
throw_speed = 3
throw_range = 7
var/spray_maxrange = 3 //what the sprayer will set spray_currentrange to in the attack_self.
@@ -79,12 +79,12 @@
continue
if(puff_reagent_left <= 0)
break
- D.reagents.reaction(T)
+ D.reagents.reaction(T, VAPOR)
if(ismob(T)) //mobs are obstacles that consume part of the puff, shortening its range.
puff_reagent_left -= 1
if(puff_reagent_left > 0)
- D.reagents.reaction(get_turf(D))
+ D.reagents.reaction(get_turf(D), VAPOR)
puff_reagent_left -= 1
if(puff_reagent_left <= 0) // we used all the puff so we delete it.
@@ -152,7 +152,7 @@
icon_state = "chemsprayer"
item_state = "chemsprayer"
throwforce = 0
- w_class = 3.0
+ w_class = 3
spray_maxrange = 7
spray_currentrange = 7
amount_per_transfer_from_this = 10
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 46b77827093..019ec3c4c83 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -66,20 +66,16 @@
if(ismob(target)) //Blood!
if(ishuman(target))
var/mob/living/carbon/human/H = target
- if(H.dna)
- if(NOBLOOD in H.dna.species.specflags && !H.dna.species.exotic_blood)
- user << "You are unable to locate any blood!"
- return
+ if(NOBLOOD in H.dna.species.specflags && !H.dna.species.exotic_blood)
+ user << "You are unable to locate any blood!"
+ return
if(reagents.has_reagent("blood"))
user << "There is already a blood sample in this syringe!"
return
if(istype(target, /mob/living/carbon)) //maybe just add a blood reagent to all mobs. Then you can suck them dry...With hundreds of syringes. Jolly good idea.
var/amount = src.reagents.maximum_volume - src.reagents.total_volume
var/mob/living/carbon/T = target
- if(!check_dna_integrity(T))
- user << "You are unable to locate any blood!"
- return
- if(NOCLONE in T.mutations) //target done been eat, no more blood in him
+ if(!T.has_dna() || (T.disabilities & NOCLONE)) //target done been eat, no more blood in him
user << "You are unable to locate any blood!"
return
if(target != user)
@@ -95,7 +91,7 @@
if(!B && ishuman(target))
var/mob/living/carbon/human/H = target
- if(H.dna && H.dna.species.exotic_blood && H.reagents.total_volume)
+ if(H.dna.species.exotic_blood && H.reagents.total_volume)
target.reagents.trans_to(src, amount)
else
user << "You are unable to locate any blood!"
@@ -127,8 +123,6 @@
if(!reagents.total_volume)
user << "[src] is empty."
return
- if(istype(target, /obj/item/weapon/implantcase/chem))
- return
if(!target.is_open_container() && !ismob(target) && !istype(target, /obj/item/weapon/reagent_containers/food) && !istype(target, /obj/item/slime_extract) && !istype(target, /obj/item/clothing/mask/cigarette) && !istype(target, /obj/item/weapon/storage/fancy/cigarettes))
user << "You cannot directly fill [target]!"
@@ -180,7 +174,7 @@
C.inject_blood(src,5)
else
src.reagents.trans_to(target, amount_per_transfer_from_this)
- user << "You inject 5 units of the solution. The syringe now contains [src.reagents.total_volume] units."
+ user << "You inject [amount_per_transfer_from_this] units of the solution. The syringe now contains [src.reagents.total_volume] units."
if (reagents.total_volume <= 0 && mode==SYRINGE_INJECT)
mode = SYRINGE_DRAW
update_icon()
@@ -221,6 +215,11 @@
desc = "Contains antiviral agents."
list_reagents = list("spaceacillin" = 15)
+/obj/item/weapon/reagent_containers/syringe/bioterror
+ name = "bioterror syringe"
+ desc = "Contains several paralyzing reagents."
+ list_reagents = list("neurotoxin" = 5, "mutetoxin" = 5, "sodium_thiopental" = 5)
+
/obj/item/weapon/reagent_containers/syringe/stimulants
name = "Stimpack"
desc = "Contains stimulants."
diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm
index fc503fac901..165d4b0a31b 100644
--- a/code/modules/reagents/reagent_dispenser.dm
+++ b/code/modules/reagents/reagent_dispenser.dm
@@ -12,14 +12,14 @@
/obj/structure/reagent_dispensers/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
qdel(src)
return
- if(2.0)
+ if(2)
if (prob(50))
qdel(src)
return
- if(3.0)
+ if(3)
if (prob(5))
qdel(src)
return
@@ -67,15 +67,15 @@
/obj/structure/reagent_dispensers/watertank/ex_act(severity, target)
switch(severity)
- if(1.0)
+ if(1)
qdel(src)
return
- if(2.0)
+ if(2)
if (prob(50))
PoolOrNew(/obj/effect/effect/water, src.loc)
qdel(src)
return
- if(3.0)
+ if(3)
if (prob(5))
PoolOrNew(/obj/effect/effect/water, src.loc)
qdel(src)
@@ -197,4 +197,4 @@
/obj/structure/reagent_dispensers/virusfood/New()
..()
- reagents.add_reagent("virusfood", 1000)
+ reagents.add_reagent("virusfood", 1000)
diff --git a/code/modules/recycling/disposal-construction.dm b/code/modules/recycling/disposal-construction.dm
index d636f818374..20cb7d40710 100644
--- a/code/modules/recycling/disposal-construction.dm
+++ b/code/modules/recycling/disposal-construction.dm
@@ -16,6 +16,10 @@
var/dpdir = 0 // directions as disposalpipe
var/base_state = "pipe-s"
+/obj/structure/disposalconstruct/examine(mob/user)
+ ..()
+ user << "Alt-click to rotate it clockwise."
+
/obj/structure/disposalconstruct/New(var/loc, var/pipe_type, var/direction = 1)
..(loc)
if(pipe_type)
@@ -104,6 +108,16 @@
dir = turn(dir, -90)
update()
+/obj/structure/disposalconstruct/AltClick(mob/user)
+ ..()
+ if(!user.canUseTopic(user))
+ user << "You can't do that right now!"
+ return
+ if(!in_range(src, user))
+ return
+ else
+ rotate()
+
/obj/structure/disposalconstruct/verb/flip()
set name = "Flip Pipe"
set category = "Object"
diff --git a/code/modules/recycling/disposal-structures.dm b/code/modules/recycling/disposal-structures.dm
index ca1364644be..0589e10be6d 100644
--- a/code/modules/recycling/disposal-structures.dm
+++ b/code/modules/recycling/disposal-structures.dm
@@ -17,7 +17,7 @@
/obj/structure/disposalholder/Destroy()
qdel(gas)
active = 0
- ..()
+ return ..()
// initialize a holder from the contents of a disposal unit
/obj/structure/disposalholder/proc/init(obj/machinery/disposal/D)
@@ -59,7 +59,6 @@
if(!D.trunk)
D.expel(src) // no trunk connected, so expel immediately
return
-
loc = D.trunk
active = 1
dir = DOWN
@@ -122,11 +121,9 @@
playsound(src.loc, 'sound/effects/clang.ogg', 50, 0, 0)
// called to vent all gas in holder to a location
-/obj/structure/disposalholder/proc/vent_gas(atom/location)
- if(location)
- location.assume_air(gas) // vent all gas to turf
- air_update_turf()
- return
+/obj/structure/disposalholder/proc/vent_gas(turf/T)
+ T.assume_air(gas)
+ T.air_update_turf()
/obj/structure/disposalholder/allow_drop()
return 1
@@ -197,13 +194,12 @@
AM.loc = T
AM.pipe_eject(0)
qdel(H)
- ..()
- return
+ return ..()
// otherwise, do normal expel from turf
if(H)
expel(H, T, 0)
- ..()
+ return ..()
// returns the direction of the next pipe object, given the entrance dir
// by default, returns the bitmask of remaining directions
@@ -346,14 +342,14 @@
H.contents_explosion(severity, target)
switch(severity)
- if(1.0)
+ if(1)
broken(0)
return
- if(2.0)
+ if(2)
health -= rand(5,15)
healthcheck()
return
- if(3.0)
+ if(3)
health -= rand(0,15)
healthcheck()
return
@@ -637,6 +633,16 @@
update()
return
+/obj/structure/disposalpipe/trunk/Destroy()
+ if(linked)
+ if(istype(linked, /obj/structure/disposaloutlet))
+ var/obj/structure/disposaloutlet/D = linked
+ D.trunk = null
+ else if(istype(linked, /obj/machinery/disposal))
+ var/obj/machinery/disposal/D = linked
+ D.trunk = null
+ return ..()
+
/obj/structure/disposalpipe/trunk/proc/getlinked()
linked = null
var/obj/machinery/disposal/D = locate() in src.loc
@@ -776,7 +782,7 @@
/obj/structure/disposaloutlet/Destroy()
if(trunk)
trunk.linked = null
- ..()
+ return ..()
// expel the contents of the holder object, then delete it
// called when the holder exits the outlet
diff --git a/code/modules/recycling/disposal-unit.dm b/code/modules/recycling/disposal-unit.dm
index a348aa86165..b76334d1680 100644
--- a/code/modules/recycling/disposal-unit.dm
+++ b/code/modules/recycling/disposal-unit.dm
@@ -49,7 +49,7 @@
eject()
if(trunk)
trunk.linked = null
- ..()
+ return ..()
/obj/machinery/disposal/singularity_pull(S, current_size)
if(current_size >= STAGE_FIVE)
@@ -275,6 +275,9 @@
//How disposal handles getting a storage dump from a storage object
/obj/machinery/disposal/storage_contents_dump_act(obj/item/weapon/storage/src_object, mob/user)
for(var/obj/item/I in src_object)
+ if(user.s_active != src_object)
+ if(I.on_found(user))
+ return
src_object.remove_from_storage(I, src)
return 1
diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm
index df47b62e337..1121faf952f 100644
--- a/code/modules/recycling/sortingmachinery.dm
+++ b/code/modules/recycling/sortingmachinery.dm
@@ -23,7 +23,7 @@
var/turf/T = get_turf(src)
for(var/atom/movable/AM in contents)
AM.loc = T
- ..()
+ return ..()
/obj/structure/bigDelivery/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/device/destTagger))
@@ -237,6 +237,6 @@
icon = 'icons/obj/items.dmi'
icon_state = "c_tube"
throwforce = 0
- w_class = 1.0
+ w_class = 1
throw_speed = 3
throw_range = 5
\ No newline at end of file
diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm
index 59205f31359..05c7eb41606 100644
--- a/code/modules/research/circuitprinter.dm
+++ b/code/modules/research/circuitprinter.dm
@@ -13,7 +13,7 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
var/g_amount = 0
var/gold_amount = 0
var/diamond_amount = 0
- var/max_material_amount = 75000.0
+ var/max_material_amount = 75000
var/efficiency_coeff
reagents = new(0)
@@ -48,7 +48,7 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
G.reagents.trans_to(src, G.reagents.total_volume)
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
T += M.rating
- max_material_amount = T * 75000.0
+ max_material_amount = T * 75000
T = 0
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
T += M.rating
diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm
index 4f7414e3457..6cd81aee185 100644
--- a/code/modules/research/designs.dm
+++ b/code/modules/research/designs.dm
@@ -24,7 +24,7 @@ Design Guidlines
reliability_mod (starts at 0, gets improved through experimentation). Example: PACMAN generator. 79 base reliablity + 6 tech
(3 plasmatech, 3 powerstorage) + 0 (since it's completely new) = 85% reliability. Reliability is the chance it works CORRECTLY.
- When adding new designs, check rdreadme.dm to see what kind of things have already been made and where new stuff is needed.
-- A single sheet of anything is 3750 units of material. Materials besides metal/glass require help from other jobs (mining for
+- A single sheet of anything is 2000 units of material. Materials besides metal/glass require help from other jobs (mining for
other types of metals and chemistry for reagents).
- Add the AUTOLATHE tag to
*/
@@ -40,6 +40,7 @@ other types of metals and chemistry for reagents).
var/construction_time //Amount of time required for building the object
var/build_path = "" //The file path of the object that gets created
var/list/category = null //Primarily used for Mech Fabricators, but can be used for anything
+ var/list/reagents = list() //List of reagents. Format: "id" = amount.
//A proc to calculate the reliability of a design based on tech levels and innate modifiers.
@@ -64,13 +65,13 @@ other types of metals and chemistry for reagents).
icon = 'icons/obj/cloning.dmi'
icon_state = "datadisk2"
item_state = "card-id"
- w_class = 1.0
+ w_class = 1
materials = list(MAT_METAL=30, MAT_GLASS=10)
var/datum/design/blueprint
/obj/item/weapon/disk/design_disk/New()
- src.pixel_x = rand(-5.0, 5)
- src.pixel_y = rand(-5.0, 5)
+ src.pixel_x = rand(-5, 5)
+ src.pixel_y = rand(-5, 5)
///////////////////////////////////
/////Non-Board Computer Stuff//////
@@ -141,7 +142,7 @@ other types of metals and chemistry for reagents).
id = "drill_diamond"
req_tech = list("materials" = 6, "powerstorage" = 4, "engineering" = 4)
build_type = PROTOLATHE
- materials = list(MAT_METAL = 6000, MAT_GLASS = 1000, MAT_DIAMOND = 3750) //Yes, a whole diamond is needed.
+ materials = list(MAT_METAL = 6000, MAT_GLASS = 1000, MAT_DIAMOND = 2000) //Yes, a whole diamond is needed.
reliability = 79
build_path = /obj/item/weapon/pickaxe/drill/diamonddrill
category = list("Mining Designs")
diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm
index 5a68e76e7e2..7cf5fff85f4 100644
--- a/code/modules/research/designs/autolathe_designs.dm
+++ b/code/modules/research/designs/autolathe_designs.dm
@@ -111,7 +111,7 @@
id = "power control"
build_type = AUTOLATHE
materials = list(MAT_METAL = 100, MAT_GLASS = 100)
- build_path = /obj/item/weapon/module/power_control
+ build_path = /obj/item/weapon/electronics/apc
category = list("initial", "Electronics")
/datum/design/airlock_board
@@ -119,7 +119,7 @@
id = "airlock_board"
build_type = AUTOLATHE
materials = list(MAT_METAL = 50, MAT_GLASS = 50)
- build_path = /obj/item/weapon/airlock_electronics
+ build_path = /obj/item/weapon/electronics/airlock
category = list("initial", "Electronics")
/datum/design/firelock_board
@@ -127,7 +127,7 @@
id = "firelock_board"
build_type = AUTOLATHE
materials = list(MAT_METAL = 50, MAT_GLASS = 50)
- build_path = /obj/item/weapon/firelock_board
+ build_path = /obj/item/weapon/electronics/firelock
category = list("initial", "Electronics")
/datum/design/airalarm_electronics
@@ -135,7 +135,7 @@
id = "airalarm_electronics"
build_type = AUTOLATHE
materials = list(MAT_METAL = 50, MAT_GLASS = 50)
- build_path = /obj/item/weapon/airalarm_electronics
+ build_path = /obj/item/weapon/electronics/airalarm
category = list("initial", "Electronics")
/datum/design/firealarm_electronics
@@ -143,7 +143,7 @@
id = "firealarm_electronics"
build_type = AUTOLATHE
materials = list(MAT_METAL = 50, MAT_GLASS = 50)
- build_path = /obj/item/weapon/firealarm_electronics
+ build_path = /obj/item/weapon/electronics/firealarm
category = list("initial", "Electronics")
/datum/design/pipe_painter
@@ -190,7 +190,7 @@
name = "Compressed matter cardridge"
id = "rcd_ammo"
build_type = AUTOLATHE
- materials = list(MAT_METAL = 16000, MAT_GLASS=8000)
+ materials = list(MAT_METAL = 3000, MAT_GLASS=2000)
build_path = /obj/item/weapon/rcd_ammo
category = list("initial","Construction")
@@ -266,6 +266,14 @@
build_path = /obj/item/weapon/reagent_containers/glass/beaker/large
category = list("initial", "Medical")
+/datum/design/healthanalyzer
+ name = "Health Analyzer"
+ id = "healthanalyzer"
+ build_type = AUTOLATHE
+ materials = list(MAT_METAL = 500, MAT_GLASS = 50)
+ build_path = /obj/item/device/healthanalyzer
+ category = list("initial", "Medical")
+
/datum/design/beanbag_slug
name = "Beanbag slug"
id = "beanbag_slug"
@@ -346,6 +354,14 @@
build_path = /obj/item/device/assembly/infra
category = list("initial", "Misc")
+/datum/design/health_sensor
+ name = "Health sensor"
+ id = "health_sensor"
+ build_type = AUTOLATHE
+ materials = list(MAT_METAL = 800, MAT_GLASS = 200)
+ build_path = /obj/item/device/assembly/health
+ category = list("initial", "Medical")
+
/datum/design/timer
name = "Timer"
id = "timer"
@@ -383,7 +399,7 @@
id = "camera_assembly"
build_type = AUTOLATHE
materials = list(MAT_METAL = 400, MAT_GLASS = 250)
- build_path = /obj/item/weapon/camera_assembly
+ build_path = /obj/item/wallframe/camera
category = list("initial", "Construction")
/datum/design/newscaster_frame
@@ -391,7 +407,7 @@
id = "newscaster_frame"
build_type = AUTOLATHE
materials = list(MAT_METAL = 14000, MAT_GLASS = 8000)
- build_path = /obj/item/newscaster_frame
+ build_path = /obj/item/wallframe/newscaster
category = list("initial", "Construction")
/datum/design/syringe
diff --git a/code/modules/research/designs/comp_board_designs.dm b/code/modules/research/designs/comp_board_designs.dm
index 0f657da38b0..9748ab6ffbe 100644
--- a/code/modules/research/designs/comp_board_designs.dm
+++ b/code/modules/research/designs/comp_board_designs.dm
@@ -110,15 +110,6 @@
build_path = /obj/item/weapon/circuitboard/crew
category = list("Computer Boards")
-/datum/design/teleconsole
- name = "Computer Design (Teleporter Console)"
- desc = "Allows for the construction of circuit boards used to build a teleporter control console."
- id = "teleconsole"
- req_tech = list("programming" = 3, "bluespace" = 2)
- build_type = IMPRINTER
- materials = list(MAT_GLASS = 1000, "sacid" = 20)
- build_path = /obj/item/weapon/circuitboard/teleporter
- category = list("Computer Boards")
/datum/design/secdata
name = "Computer Design (Security Records Console)"
@@ -160,36 +151,6 @@
build_path = /obj/item/weapon/circuitboard/robotics
category = list("Computer Boards")
-/datum/design/clonecontrol
- name = "Computer Design (Cloning Machine Console)"
- desc = "Allows for the construction of circuit boards used to build a new Cloning Machine console."
- id = "clonecontrol"
- req_tech = list("programming" = 3, "biotech" = 3)
- build_type = IMPRINTER
- materials = list(MAT_GLASS = 1000, "sacid" = 20)
- build_path = /obj/item/weapon/circuitboard/cloning
- category = list("Computer Boards")
-
-/datum/design/clonepod
- name = "Machine Design (Clone Pod)"
- desc = "Allows for the construction of circuit boards used to build a Cloning Pod."
- id = "clonepod"
- req_tech = list("programming" = 3, "biotech" = 3)
- build_type = IMPRINTER
- materials = list(MAT_GLASS = 1000, "sacid" = 20)
- build_path = /obj/item/weapon/circuitboard/clonepod
- category = list("Computer Boards")
-
-/datum/design/clonescanner
- name = "Machine Design (Cloning Scanner)"
- desc = "Allows for the construction of circuit boards used to build a Cloning Scanner."
- id = "clonescanner"
- req_tech = list("programming" = 3, "biotech" = 3)
- build_type = IMPRINTER
- materials = list(MAT_GLASS = 1000, "sacid" = 20)
- build_path = /obj/item/weapon/circuitboard/clonescanner
- category = list("Computer Boards")
-
/datum/design/arcadebattle
name = "Computer Design (Battle Arcade Machine)"
desc = "Allows for the construction of circuit boards used to build a new arcade machine."
@@ -350,16 +311,6 @@
build_path = /obj/item/weapon/circuitboard/comm_traffic
category = list("Computer Boards")
-/datum/design/telesci_console
- name = "Computer Design (Telepad Control Console Board)"
- desc = "Allows for the construction of circuit boards used to build a telescience console."
- id = "telesci_console"
- req_tech = list("programming" = 3, "bluespace" = 2)
- build_type = IMPRINTER
- materials = list(MAT_GLASS = 1000, "sacid" = 20)
- build_path = /obj/item/weapon/circuitboard/telesci_console
- category = list("Computer Boards")
-
/datum/design/aifixer
name = "Computer Design (AI Integrity Restorer)"
desc = "Allows for the construction of circuit boards used to build an AI Integrity Restorer."
diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm
index 75202c87387..2d20c8371bf 100644
--- a/code/modules/research/designs/machine_designs.dm
+++ b/code/modules/research/designs/machine_designs.dm
@@ -32,6 +32,16 @@
build_path = /obj/item/weapon/circuitboard/turbine_computer
category = list ("Engineering Machinery")
+/datum/design/emitter
+ name = "Machine Design (Emitter Board)"
+ desc = "The circuit board for an emitter."
+ id = "emitter"
+ req_tech = list("programming" = 4, "powerstorage" = 5, "engineering" = 5)
+ build_type = IMPRINTER
+ materials = list(MAT_GLASS = 1000, "sacid" = 20)
+ build_path = /obj/item/weapon/circuitboard/emitter
+ category = list ("Engineering Machinery")
+
/datum/design/power_compressor
name = "Machine Design (Power Compressor Board)"
desc = "The circuit board for a power compressor."
@@ -92,6 +102,26 @@
build_path = /obj/item/weapon/circuitboard/telesci_pad
category = list ("Teleportation Machinery")
+/datum/design/teleconsole
+ name = "Computer Design (Teleporter Console)"
+ desc = "Allows for the construction of circuit boards used to build a teleporter control console."
+ id = "teleconsole"
+ req_tech = list("programming" = 3, "bluespace" = 2)
+ build_type = IMPRINTER
+ materials = list(MAT_GLASS = 1000, "sacid" = 20)
+ build_path = /obj/item/weapon/circuitboard/teleporter
+ category = list("Teleportation Machinery")
+
+/datum/design/telesci_console
+ name = "Computer Design (Telepad Control Console Board)"
+ desc = "Allows for the construction of circuit boards used to build a telescience console."
+ id = "telesci_console"
+ req_tech = list("programming" = 3, "bluespace" = 2)
+ build_type = IMPRINTER
+ materials = list(MAT_GLASS = 1000, "sacid" = 20)
+ build_path = /obj/item/weapon/circuitboard/telesci_console
+ category = list("Teleportation Machinery")
+
/datum/design/sleeper
name = "Machine Design (Sleeper Board)"
desc = "The circuit board for a sleeper."
@@ -142,6 +172,36 @@
build_path = /obj/item/weapon/circuitboard/chem_heater
category = list ("Medical Machinery")
+/datum/design/clonecontrol
+ name = "Computer Design (Cloning Machine Console)"
+ desc = "Allows for the construction of circuit boards used to build a new Cloning Machine console."
+ id = "clonecontrol"
+ req_tech = list("programming" = 3, "biotech" = 3)
+ build_type = IMPRINTER
+ materials = list(MAT_GLASS = 1000, "sacid" = 20)
+ build_path = /obj/item/weapon/circuitboard/cloning
+ category = list("Medical Machinery")
+
+/datum/design/clonepod
+ name = "Machine Design (Clone Pod)"
+ desc = "Allows for the construction of circuit boards used to build a Cloning Pod."
+ id = "clonepod"
+ req_tech = list("programming" = 3, "biotech" = 3)
+ build_type = IMPRINTER
+ materials = list(MAT_GLASS = 1000, "sacid" = 20)
+ build_path = /obj/item/weapon/circuitboard/clonepod
+ category = list("Medical Machinery")
+
+/datum/design/clonescanner
+ name = "Machine Design (Cloning Scanner)"
+ desc = "Allows for the construction of circuit boards used to build a Cloning Scanner."
+ id = "clonescanner"
+ req_tech = list("programming" = 3, "biotech" = 3)
+ build_type = IMPRINTER
+ materials = list(MAT_GLASS = 1000, "sacid" = 20)
+ build_path = /obj/item/weapon/circuitboard/clonescanner
+ category = list("Medical Machinery")
+
/datum/design/biogenerator
name = "Machine Design (Biogenerator Board)"
desc = "The circuit board for a biogenerator."
diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm
index c3a14613b65..b480ed8ab8c 100644
--- a/code/modules/research/designs/mechfabricator_designs.dm
+++ b/code/modules/research/designs/mechfabricator_designs.dm
@@ -670,7 +670,7 @@
build_type = MECHFAB
build_path = /obj/item/borg/upgrade/ddrill
req_tech = list("engineering" = 5, "materials" = 5)
- materials = list(MAT_METAL=10000, MAT_DIAMOND=3750)
+ materials = list(MAT_METAL=10000, MAT_DIAMOND=2000)
construction_time = 120
category = list("Cyborg Upgrade Modules")
@@ -695,6 +695,16 @@
construction_time = 120
category = list("Cyborg Upgrade Modules")
+/datum/design/borg_upgrade_selfrepair
+ name = "Cyborg Upgrade (Self-repair)"
+ id = "borg_upgrade_selfrepair"
+ build_type = MECHFAB
+ build_path = /obj/item/borg/upgrade/selfrepair
+ req_tech = list("materials" = 4, "engineering" = 4)
+ materials = list(MAT_METAL=15000, MAT_GLASS=15000)
+ construction_time = 120
+ category = list("Cyborg Upgrade Modules")
+
//Misc
/datum/design/mecha_tracking
name = "Exosuit Tracking Beacon"
diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm
index 1501167a730..cf283810d38 100644
--- a/code/modules/research/designs/medical_designs.dm
+++ b/code/modules/research/designs/medical_designs.dm
@@ -2,6 +2,7 @@
////////////Medical Tools////////////////
/////////////////////////////////////////
+
/datum/design/mass_spectrometer
name = "Mass-Spectrometer"
desc = "A device for analyzing chemicals in the blood."
@@ -70,7 +71,7 @@
materials = list(MAT_METAL = 750, MAT_GLASS = 750)
construction_time = 100
reliability = 76
- build_path = /obj/item/device/flash/handheld
+ build_path = /obj/item/device/assembly/flash/handheld
category = list("Misc")
/datum/design/bluespacebeaker
@@ -111,15 +112,27 @@
//////////Cybernetic Implants////////////
/////////////////////////////////////////
+/datum/design/cyberimp_welding
+ name = "Welding Shield implant"
+ desc = "These reactive micro-shields will protect you from welders and flashes without obscuring your vision."
+ id = "ci-welding"
+ req_tech = list("materials" = 4, "biotech" = 2)
+ build_type = PROTOLATHE | MECHFAB
+ construction_time = 40
+ materials = list(MAT_METAL = 200, MAT_GLASS = 400)
+ build_path = /obj/item/organ/internal/cyberimp/eyes/shield
+ category = list("Misc", "Medical Designs")
+
/datum/design/cyberimp_medical_hud
name = "Medical HUD implant"
desc = "These cybernetic eyes will display a medical HUD over everything you see. Wiggle eyes to control."
id = "ci-medhud"
req_tech = list("materials" = 6, "programming" = 4, "biotech" = 4)
build_type = PROTOLATHE | MECHFAB
+ construction_time = 50
materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_SILVER = 500, MAT_GOLD = 500)
build_path = /obj/item/organ/internal/cyberimp/eyes/hud/medical
- category = list("Medical Designs")
+ category = list("Misc", "Medical Designs")
/datum/design/cyberimp_security_hud
name = "Security HUD implant"
@@ -127,9 +140,10 @@
id = "ci-sechud"
req_tech = list("materials" = 6, "programming" = 5, "biotech" = 4, "combat" = 2)
build_type = PROTOLATHE | MECHFAB
+ construction_time = 50
materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_SILVER = 750, MAT_GOLD = 750)
build_path = /obj/item/organ/internal/cyberimp/eyes/hud/security
- category = list("Medical Designs")
+ category = list("Misc", "Medical Designs")
/datum/design/cyberimp_xray
name = "X-Ray implant"
@@ -137,9 +151,10 @@
id = "ci-xray"
req_tech = list("materials" = 7, "programming" = 5, "biotech" = 6, "magnets" = 5)
build_type = PROTOLATHE | MECHFAB
+ construction_time = 60
materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_SILVER = 600, MAT_GOLD = 600, MAT_PLASMA = 1000, MAT_URANIUM = 1000, MAT_DIAMOND = 2000)
build_path = /obj/item/organ/internal/cyberimp/eyes/xray
- category = list("Medical Designs")
+ category = list("Misc", "Medical Designs")
/datum/design/cyberimp_thermals
name = "Thermals implant"
@@ -147,9 +162,10 @@
id = "ci-thermals"
req_tech = list("materials" = 7, "programming" = 5, "biotech" = 5, "magnets" = 5, "syndicate" = 5)
build_type = PROTOLATHE | MECHFAB
+ construction_time = 60
materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_SILVER = 600, MAT_GOLD = 600, MAT_PLASMA = 1000, MAT_DIAMOND = 2000)
build_path = /obj/item/organ/internal/cyberimp/eyes/thermals
- category = list("Medical Designs")
+ category = list("Misc", "Medical Designs")
/datum/design/cyberimp_antidrop
name = "Anti-Drop implant"
@@ -157,6 +173,7 @@
id = "ci-antidrop"
req_tech = list("materials" = 7, "programming" = 5, "biotech" = 5)
build_type = PROTOLATHE | MECHFAB
+ construction_time = 60
materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_SILVER = 400, MAT_GOLD = 400)
build_path = /obj/item/organ/internal/cyberimp/brain/anti_drop
category = list("Medical Designs")
@@ -167,6 +184,7 @@
id = "ci-antistun"
req_tech = list("materials" = 7, "programming" = 5, "biotech" = 6)
build_type = PROTOLATHE | MECHFAB
+ construction_time = 60
materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_SILVER = 500, MAT_GOLD = 1000)
build_path = /obj/item/organ/internal/cyberimp/brain/anti_stun
category = list("Medical Designs")
@@ -177,6 +195,7 @@
id = "ci-nutriment"
req_tech = list("materials" = 6, "programming" = 4, "biotech" = 5)
build_type = PROTOLATHE | MECHFAB
+ construction_time = 40
materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_GOLD = 500, MAT_URANIUM = 500)
build_path = /obj/item/organ/internal/cyberimp/chest/nutriment
category = list("Medical Designs")
@@ -187,6 +206,7 @@
id = "ci-nutrimentplus"
req_tech = list("materials" = 6, "programming" = 4, "biotech" = 6)
build_type = PROTOLATHE | MECHFAB
+ construction_time = 50
materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_GOLD = 500, MAT_URANIUM = 750)
build_path = /obj/item/organ/internal/cyberimp/chest/nutriment/plus
category = list("Medical Designs")
@@ -197,6 +217,52 @@
id = "ci-reviver"
req_tech = list("materials" = 6, "programming" = 4, "biotech" = 7, "syndicate" = 4)
build_type = PROTOLATHE | MECHFAB
+ construction_time = 60
materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_GOLD = 500, MAT_URANIUM = 1000, MAT_DIAMOND = 2000)
build_path = /obj/item/organ/internal/cyberimp/chest/reviver
+ category = list("Misc", "Medical Designs")
+
+
+/////////////////////////////////////////
+////////////Regular Implants/////////////
+/////////////////////////////////////////
+
+/datum/design/implanter
+ name = "Implanter"
+ desc = "A sterile automatic implant injector."
+ id = "implanter"
+ req_tech = list("materials" = 1, "programming" = 2, "biotech" = 3)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 600, MAT_GLASS = 200)
+ build_path = /obj/item/weapon/implanter
+ category = list("Medical Designs")
+
+/datum/design/implantcase
+ name = "Implant Case"
+ desc = "A glass case containing an implant."
+ id = "implantcase"
+ req_tech = list("materials" = 1, "biotech" = 2)
+ build_type = PROTOLATHE
+ materials = list(MAT_GLASS = 500)
+ build_path = /obj/item/weapon/implantcase
+ category = list("Medical Designs")
+
+/datum/design/implant_freedom
+ name = "Freedom Implant Case"
+ desc = "A glass case containing an implant."
+ id = "implant_freedom"
+ req_tech = list("materials" = 2, "biotech" = 3, "magnets" = 3, "syndicate" = 5)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 50, MAT_GLASS = 500, MAT_GOLD = 250)
+ build_path = /obj/item/weapon/implantcase/freedom
+ category = list("Medical Designs")
+
+/datum/design/implant_adrenalin
+ name = "Adrenalin Implant Case"
+ desc = "A glass case containing an implant."
+ id = "implant_adrenalin"
+ req_tech = list("materials" = 2, "biotech" = 5, "combat" = 3, "syndicate" = 6)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 50, MAT_GLASS = 500, MAT_GOLD = 500, MAT_URANIUM = 100, MAT_DIAMOND = 200)
+ build_path = /obj/item/weapon/implantcase/adrenaline
category = list("Medical Designs")
\ No newline at end of file
diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm
index 88c008128a8..c2edf89e874 100644
--- a/code/modules/research/designs/weapon_designs.dm
+++ b/code/modules/research/designs/weapon_designs.dm
@@ -69,7 +69,8 @@
id = "decloner"
req_tech = list("combat" = 8, "materials" = 7, "biotech" = 5, "powerstorage" = 6)
build_type = PROTOLATHE
- materials = list(MAT_GOLD = 5000,MAT_URANIUM = 10000, "mutagen" = 40)
+ materials = list(MAT_GOLD = 5000,MAT_URANIUM = 10000)
+ reagents = list("mutagen" = 40)
build_path = /obj/item/weapon/gun/energy/decloner
category = list("Weapons")
@@ -110,7 +111,8 @@
id = "flora_gun"
req_tech = list("materials" = 2, "biotech" = 3, "powerstorage" = 3)
build_type = PROTOLATHE
- materials = list(MAT_METAL = 2000, MAT_GLASS = 500, "radium" = 20)
+ materials = list(MAT_METAL = 2000, MAT_GLASS = 500)
+ reagents = list("radium" = 20)
build_path = /obj/item/weapon/gun/energy/floragun
category = list("Weapons")
@@ -126,8 +128,8 @@
category = list("Weapons")
/datum/design/smg
- name = "Prototype Submachine Gun"
- desc = "A prototype weapon made using lightweight materials on a traditional frame, designed to fire standard 9mm rounds."
+ name = "NanoTrasen Saber SMG"
+ desc = "A prototype advancment over the WT-550 auto rifle made using lightweight materials on a traditional frame, designed to fire standard 9mm rounds."
id = "smg"
req_tech = list("combat" = 4, "materials" = 3)
build_type = PROTOLATHE
@@ -175,9 +177,44 @@
build_path = /obj/item/weaponcrafting/reciever
category = list("Weapons")
+//WT550 Mags
+
+/datum/design/mag_oldsmg
+ name = "WT-550 Auto Gun Magazine (9mm)"
+ desc = "A 20 round magazine for the out of date security WT-550 Auto Rifle"
+ id = "mag_oldsmg"
+ req_tech = list("combat" = 1, "materials" = 1)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 4000)
+ build_path = /obj/item/ammo_box/magazine/wt550m9
+ category = list("Ammo")
+
+/datum/design/mag_oldsmg/ap_mag
+ name = "WT-550 Auto Gun Armour Piercing Magazine (9mmAP)"
+ desc = "A 20 round armour piercing magazine for the out of date security WT-550 Auto Rifle"
+ id = "mag_oldsmg_ap"
+ materials = list(MAT_METAL = 6000, MAT_SILVER = 200)
+ build_path = /obj/item/ammo_box/magazine/wt550m9/wtap
+
+/datum/design/mag_oldsmg/ic_mag
+ name = "WT-550 Auto Gun Incendiary Magazine (9mmIC)"
+ desc = "A 20 round armour piercing magazine for the out of date security WT-550 Auto Rifle"
+ id = "mag_oldsmg_ic"
+ materials = list(MAT_METAL = 6000, MAT_SILVER = 200, MAT_GLASS = 800)
+ build_path = /obj/item/ammo_box/magazine/wt550m9/wtic
+
+/datum/design/mag_oldsmg/tx_mag
+ name = "WT-550 Auto Gun Urnaium Magazine (9mmTX)"
+ desc = "A 20 round urnaium tipped magazine for the out of date security WT-550 Auto Rifle"
+ id = "mag_oldsmg_tx"
+ materials = list(MAT_METAL = 6000, MAT_SILVER = 400, MAT_URANIUM = 2000)
+ build_path = /obj/item/ammo_box/magazine/wt550m9/wttx
+
+//SABR Mags
+
/datum/design/mag_smg
- name = "Submachine Gun Magazine (9mm)"
- desc = "A 20-round magazine for the prototype submachine gun."
+ name = "SABR SMG Magazine (9mm)"
+ desc = "A 30-round magazine for the prototype submachine gun."
id = "mag_smg"
req_tech = list("combat" = 4, "materials" = 3)
build_type = PROTOLATHE
@@ -185,6 +222,27 @@
build_path = /obj/item/ammo_box/magazine/smgm9mm
category = list("Ammo")
+/datum/design/mag_smg/ap_mag
+ name = "SABR SMG Armour Piercing Magazine (9mmAP)"
+ desc = "A 30-round armour piercing magazine for the prototype submachine gun. Deals slightly less damage by bypasses most armour"
+ id = "mag_smg_ap"
+ materials = list(MAT_METAL = 3000, MAT_SILVER = 100)
+ build_path = /obj/item/ammo_box/magazine/smgm9mm/ap
+
+/datum/design/mag_smg/incin_mag
+ name = "SABR SMG Incendiary Magazine (9mmIC)"
+ desc = "A 30-round incindiary round magazine for the prototype submachine gun. Deals significanlty less damage but sets the target on fire"
+ id = "mag_smg_ic"
+ materials = list(MAT_METAL = 3000, MAT_SILVER = 100, MAT_GLASS = 400)
+ build_path = /obj/item/ammo_box/magazine/smgm9mm/fire
+
+/datum/design/mag_smg/incin_tox
+ name = "SABR SMG Urnaium Magazine (9mmTX)"
+ desc = "A 30-round urnaium tipped round magazine for the prototype submachine gun. Deals toxin damage, but less overall damage."
+ id = "mag_smg_tx"
+ materials = list(MAT_METAL = 3000, MAT_GLASS = 200, MAT_URANIUM = 1000)
+ build_path = /obj/item/ammo_box/magazine/smgm9mm/toxin
+
/datum/design/stunshell
name = "Stun Shell"
desc = "A stunning shell for a shotgun."
@@ -201,7 +259,7 @@
id = "techshotshell"
req_tech = list("combat" = 3, "materials" = 3, "powerstorage" = 4, "magnets" = 3)
build_type = PROTOLATHE
- materials = list(MAT_METAL = 1000, MAT_GLASS = 200, MAT_SILVER = 300)
+ materials = list(MAT_METAL = 1000, MAT_GLASS = 200)
build_path = /obj/item/ammo_casing/shotgun/techshell
category = list("Ammo")
diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm
index e57a3762319..8924a827921 100644
--- a/code/modules/research/experimentor.dm
+++ b/code/modules/research/experimentor.dm
@@ -127,7 +127,9 @@
if(exchange_parts(user, O))
return
- default_deconstruction_crowbar(O)
+ if(panel_open && istype(O, /obj/item/weapon/crowbar))
+ default_deconstruction_crowbar(O)
+ return
if(!checkCircumstances(O))
user << "The [O] is not yet valid for the [src] and must be completed!"
@@ -138,10 +140,10 @@
if (!linked_console)
user << "The [src] must be linked to an R&D console first!"
return
- if (busy)
- user << "The [src] is busy right now."
+ if (loaded_item)
+ user << "The [src] is already loaded."
return
- if (istype(O, /obj/item) && !loaded_item)
+ if (istype(O, /obj/item))
if(!O.origin_tech)
user << "This doesn't seem to have a tech origin!"
return
@@ -154,7 +156,6 @@
return
if(!user.drop_item())
return
- busy = 1
loaded_item = O
O.loc = src
user << "You add the [O.name] to the machine."
@@ -455,8 +456,8 @@
visible_message("[src]'s crushing mechanism slowly and smoothly descends, flattening the [exp_on]!")
new /obj/item/stack/sheet/plasteel(get_turf(pick(oview(1,src))))
if(linked_console.linked_lathe)
- linked_console.linked_lathe.m_amount += min((linked_console.linked_lathe.max_material_storage - linked_console.linked_lathe.TotalMaterials()), (exp_on.materials[MAT_METAL]))
- linked_console.linked_lathe.g_amount += min((linked_console.linked_lathe.max_material_storage - linked_console.linked_lathe.TotalMaterials()), (exp_on.materials[MAT_GLASS]))
+ for(var/material in exp_on.materials)
+ linked_console.linked_lathe.materials.insert_amount( min((linked_console.linked_lathe.materials.max_amount - linked_console.linked_lathe.materials.total_amount), (exp_on.materials[material])), material)
if(prob(EFFECT_PROB_VERYLOW-badThingCoeff))
visible_message("[src]'s crusher goes way too many levels too high, crushing right through space-time!")
playsound(src.loc, 'sound/effects/supermatter.ogg', 50, 1, -3)
@@ -544,7 +545,6 @@
spawn(resetTime)
icon_state = "h_lathe"
- busy = 0
recentlyExperimented = 0
/obj/machinery/r_n_d/experimentor/Topic(href, href_list)
@@ -562,7 +562,6 @@
if(D)
linked_console = D
else if(scantype == "eject")
- busy = 0
ejectItem()
else if(scantype == "refresh")
src.updateUsrDialog()
@@ -578,7 +577,7 @@
experiment(dotype,process)
use_power(750)
if(dotype != FAIL)
- if(process.origin_tech)
+ if(process && process.origin_tech)
var/list/temp_tech = ConvertReqString2List(process.origin_tech)
for(var/T in temp_tech)
linked_console.files.UpdateTech(T, temp_tech[T])
@@ -681,7 +680,7 @@
user << message
var/animals = rand(1,25)
var/counter
- var/list/valid_animals = list(/mob/living/simple_animal/parrot,/mob/living/simple_animal/butterfly,/mob/living/simple_animal/pet/cat,/mob/living/simple_animal/pet/dog/corgi,/mob/living/simple_animal/crab,/mob/living/simple_animal/pet/fox,/mob/living/simple_animal/lizard,/mob/living/simple_animal/mouse,/mob/living/simple_animal/pet/pug,/mob/living/simple_animal/hostile/bear,/mob/living/simple_animal/hostile/poison/bees,/mob/living/simple_animal/hostile/carp)
+ var/list/valid_animals = list(/mob/living/simple_animal/parrot,/mob/living/simple_animal/butterfly,/mob/living/simple_animal/pet/cat,/mob/living/simple_animal/pet/dog/corgi,/mob/living/simple_animal/crab,/mob/living/simple_animal/pet/fox,/mob/living/simple_animal/lizard,/mob/living/simple_animal/mouse,/mob/living/simple_animal/pet/dog/pug,/mob/living/simple_animal/hostile/bear,/mob/living/simple_animal/hostile/poison/bees,/mob/living/simple_animal/hostile/carp)
for(counter = 1; counter < animals; counter++)
var/mobType = pick(valid_animals)
new mobType(get_turf(src))
@@ -703,7 +702,8 @@
R.realProc = realProc
R.revealed = TRUE
dupes |= R
- R.throw_at(pick(oview(7,get_turf(src))),10,1)
+ spawn()
+ R.throw_at(pick(oview(7,get_turf(src))),10,1)
counter = 0
spawn(rand(10,100))
for(counter = 1; counter <= dupes.len; counter++)
diff --git a/code/modules/research/message_server.dm b/code/modules/research/message_server.dm
index 901d291e947..5ddfa1770f8 100644
--- a/code/modules/research/message_server.dm
+++ b/code/modules/research/message_server.dm
@@ -76,7 +76,7 @@ var/global/list/obj/machinery/message_server/message_servers = list()
icon_state = "server"
name = "Messaging Server"
density = 1
- anchored = 1.0
+ anchored = 1
use_power = 1
idle_power_usage = 10
active_power_usage = 100
@@ -96,8 +96,7 @@ var/global/list/obj/machinery/message_server/message_servers = list()
/obj/machinery/message_server/Destroy()
message_servers -= src
- ..()
- return
+ return ..()
/obj/machinery/message_server/proc/GenerateKey()
//Feel free to move to Helpers.
@@ -211,7 +210,7 @@ var/obj/machinery/blackbox_recorder/blackbox
icon_state = "blackbox"
name = "Blackbox Recorder"
density = 1
- anchored = 1.0
+ anchored = 1
use_power = 1
idle_power_usage = 10
active_power_usage = 100
@@ -258,7 +257,7 @@ var/obj/machinery/blackbox_recorder/blackbox
BR.messages_admin = messages_admin
if(blackbox != BR)
blackbox = BR
- ..()
+ return ..()
/obj/machinery/blackbox_recorder/proc/find_feedback_datum(variable)
for (var/datum/feedback_variable/FV in feedback)
diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm
index 0e998a0cb1b..48157bbf75d 100644
--- a/code/modules/research/protolathe.dm
+++ b/code/modules/research/protolathe.dm
@@ -13,16 +13,7 @@ Note: Must be placed west/left of and R&D console to function.
icon_state = "protolathe"
flags = OPENCONTAINER
- var/max_material_storage = 100000 //All this could probably be done better with a list but meh.
- var/m_amount = 0.0
- var/g_amount = 0.0
- var/gold_amount = 0.0
- var/silver_amount = 0.0
- var/plasma_amount = 0.0
- var/uranium_amount = 0.0
- var/diamond_amount = 0.0
- var/clown_amount = 0.0
- var/adamantine_amount = 0.0
+ var/datum/material_container/materials
var/efficiency_coeff
var/list/categories = list(
@@ -51,12 +42,14 @@ Note: Must be placed west/left of and R&D console to function.
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src)
component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src)
+ materials = new(src, list(MAT_METAL=1, MAT_GLASS=1, MAT_SILVER=1, MAT_GOLD=1, MAT_DIAMOND=1, MAT_PLASMA=1, MAT_URANIUM=1, MAT_BANANIUM=1))
RefreshParts()
reagents.my_atom = src
-/obj/machinery/r_n_d/protolathe/proc/TotalMaterials() //returns the total of all the stored materials. Makes code neater.
- return m_amount + g_amount + gold_amount + silver_amount + plasma_amount + uranium_amount + diamond_amount + clown_amount
+/obj/machinery/r_n_d/protolathe/Destroy()
+ qdel(materials)
+ return ..()
/obj/machinery/r_n_d/protolathe/RefreshParts()
var/T = 0
@@ -64,34 +57,19 @@ Note: Must be placed west/left of and R&D console to function.
G.reagents.trans_to(src, G.reagents.total_volume)
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
T += M.rating
- max_material_storage = T * 75000
+ materials.max_amount = T * 75000
T = 0
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
T += (M.rating/3)
efficiency_coeff = max(T, 1)
/obj/machinery/r_n_d/protolathe/proc/check_mat(datum/design/being_built, M) // now returns how many times the item can be built with the material
- var/A = 0
- switch(M)
- if(MAT_METAL)
- A = m_amount
- if(MAT_GLASS)
- A = g_amount
- if(MAT_GOLD)
- A = gold_amount
- if(MAT_SILVER)
- A = silver_amount
- if(MAT_PLASMA)
- A = plasma_amount
- if(MAT_URANIUM)
- A = uranium_amount
- if(MAT_DIAMOND)
- A = diamond_amount
- if(MAT_BANANIUM)
- A = clown_amount
- else
- A = reagents.get_reagent_amount(M)
- A = A / max(1, (being_built.materials[M]/efficiency_coeff))
+ var/A = materials.amount(M)
+ if(!A)
+ A = reagents.get_reagent_amount(M)
+ A = A / max(1, (being_built.reagents[M]/efficiency_coeff))
+ else
+ A = A / max(1, (being_built.materials[M]/efficiency_coeff))
return A
/obj/machinery/r_n_d/protolathe/attackby(obj/item/O, mob/user, params)
@@ -110,33 +88,7 @@ Note: Must be placed west/left of and R&D console to function.
if(istype(O, /obj/item/weapon/crowbar))
for(var/obj/item/weapon/reagent_containers/glass/G in component_parts)
reagents.trans_to(G, G.reagents.maximum_volume)
- if(m_amount >= MINERAL_MATERIAL_AMOUNT)
- var/obj/item/stack/sheet/metal/G = new /obj/item/stack/sheet/metal(src.loc)
- G.amount = round(m_amount / G.perunit)
- if(g_amount >= MINERAL_MATERIAL_AMOUNT)
- var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(src.loc)
- G.amount = round(g_amount / G.perunit)
- if(plasma_amount >= MINERAL_MATERIAL_AMOUNT)
- var/obj/item/stack/sheet/mineral/plasma/G = new /obj/item/stack/sheet/mineral/plasma(src.loc)
- G.amount = round(plasma_amount / G.perunit)
- if(silver_amount >= MINERAL_MATERIAL_AMOUNT)
- var/obj/item/stack/sheet/mineral/silver/G = new /obj/item/stack/sheet/mineral/silver(src.loc)
- G.amount = round(silver_amount / G.perunit)
- if(gold_amount >= MINERAL_MATERIAL_AMOUNT)
- var/obj/item/stack/sheet/mineral/gold/G = new /obj/item/stack/sheet/mineral/gold(src.loc)
- G.amount = round(gold_amount / G.perunit)
- if(uranium_amount >= MINERAL_MATERIAL_AMOUNT)
- var/obj/item/stack/sheet/mineral/uranium/G = new /obj/item/stack/sheet/mineral/uranium(src.loc)
- G.amount = round(uranium_amount / G.perunit)
- if(diamond_amount >= MINERAL_MATERIAL_AMOUNT)
- var/obj/item/stack/sheet/mineral/diamond/G = new /obj/item/stack/sheet/mineral/diamond(src.loc)
- G.amount = round(diamond_amount / G.perunit)
- if(clown_amount >= MINERAL_MATERIAL_AMOUNT)
- var/obj/item/stack/sheet/mineral/bananium/G = new /obj/item/stack/sheet/mineral/bananium(src.loc)
- G.amount = round(clown_amount / G.perunit)
- if(adamantine_amount >= MINERAL_MATERIAL_AMOUNT)
- var/obj/item/stack/sheet/mineral/adamantine/G = new /obj/item/stack/sheet/mineral/adamantine(src.loc)
- G.amount = round(adamantine_amount / G.perunit)
+ materials.retrieve_all()
default_deconstruction_crowbar(O)
return 1
else
@@ -152,52 +104,29 @@ Note: Must be placed west/left of and R&D console to function.
return 1
if (O.is_open_container())
return
- if (!istype(O, /obj/item/stack/sheet) || istype(O, /obj/item/stack/sheet/mineral/wood))
- user << "You cannot insert this item into the [src.name]!"
- return 1
if (stat)
return 1
- if(istype(O,/obj/item/stack/sheet))
- var/obj/item/stack/sheet/S = O
- if (TotalMaterials() + S.perunit > max_material_storage)
- user << "The [src.name]'s material bin is full! Please remove material before adding more."
- return 1
+ if(!istype(O,/obj/item/stack/sheet))
+ return 1
+
+ if(!materials.has_space( materials.get_item_material_amount(O) ))
+ user << "The [src.name]'s material bin is full! Please remove material before adding more."
+ return 1
var/obj/item/stack/sheet/stack = O
var/amount = round(input("How many sheets do you want to add?") as num)//No decimals
- if(!stack || stack.amount <= 0 || amount <= 0 || !in_range(src, stack) || !user.Adjacent(src))
+ if(!in_range(src, stack) || !user.Adjacent(src))
return
- if(amount > stack.amount)
- amount = stack.amount
- if(max_material_storage - TotalMaterials() < (amount*stack.perunit))//Can't overfill
- amount = min(stack.amount, round((max_material_storage-TotalMaterials())/stack.perunit))
-
- busy = 1
- use_power(max(1000, (MINERAL_MATERIAL_AMOUNT*amount/10)))
- user << "You add [amount] sheets to the [src.name]."
- if(istype(stack, /obj/item/stack/sheet/metal))
- m_amount += amount * MINERAL_MATERIAL_AMOUNT
- else if(istype(stack, /obj/item/stack/sheet/glass))
- g_amount += amount * MINERAL_MATERIAL_AMOUNT
- else if(istype(stack, /obj/item/stack/sheet/mineral/gold))
- gold_amount += amount * MINERAL_MATERIAL_AMOUNT
- else if(istype(stack, /obj/item/stack/sheet/mineral/silver))
- silver_amount += amount * MINERAL_MATERIAL_AMOUNT
- else if(istype(stack, /obj/item/stack/sheet/mineral/plasma))
- plasma_amount += amount * MINERAL_MATERIAL_AMOUNT
- else if(istype(stack, /obj/item/stack/sheet/mineral/uranium))
- uranium_amount += amount * MINERAL_MATERIAL_AMOUNT
- else if(istype(stack, /obj/item/stack/sheet/mineral/diamond))
- diamond_amount += amount * MINERAL_MATERIAL_AMOUNT
- else if(istype(stack, /obj/item/stack/sheet/mineral/bananium))
- clown_amount += amount * MINERAL_MATERIAL_AMOUNT
- else if(istype(stack, /obj/item/stack/sheet/mineral/adamantine))
- adamantine_amount += amount * MINERAL_MATERIAL_AMOUNT
- stack.use(amount)
+ var/amount_inserted = materials.insert_stack(O,amount)
+ if(!amount_inserted)
+ return 1
+ else
+ var/stack_name = stack.name
+ busy = 1
+ use_power(max(1000, (MINERAL_MATERIAL_AMOUNT*amount_inserted/10)))
+ user << "You add [amount_inserted] sheets to the [src.name]."
+ overlays += "protolathe_[stack_name]"
+ sleep(10)
+ overlays -= "protolathe_[stack_name]"
+ busy = 0
updateUsrDialog()
-
- overlays += "protolathe_[stack.name]"
- sleep(10)
- overlays -= "protolathe_[stack.name]"
- busy = 0
-
diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm
index a3e8c47888d..b15c8600c3c 100644
--- a/code/modules/research/rdconsole.dm
+++ b/code/modules/research/rdconsole.dm
@@ -60,7 +60,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
check_tech = new T()
if(check_tech.id == ID)
return_name = check_tech.name
- del(check_tech)
+ qdel(check_tech)
check_tech = null
break
@@ -94,7 +94,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
temp_reagent = new R()
if(temp_reagent.id == ID)
return_name = temp_reagent.name
- del(temp_reagent)
+ qdel(temp_reagent)
temp_reagent = null
break
return return_name
@@ -276,9 +276,9 @@ won't update every console in existence) but it's more of a hassle to do. Also,
else //Same design always gain quality
screen = 2.3 //Crit fail gives the same design a lot of reliability, like really a lot
if(linked_lathe) //Also sends salvaged materials to a linked protolathe, if any.
- linked_lathe.m_amount += min((linked_lathe.max_material_storage - linked_lathe.TotalMaterials()), (linked_destroy.loaded_item.materials[MAT_METAL]*(linked_destroy.decon_mod/10)))
- linked_lathe.g_amount += min((linked_lathe.max_material_storage - linked_lathe.TotalMaterials()), (linked_destroy.loaded_item.materials[MAT_GLASS]*(linked_destroy.decon_mod/10)))
- feedback_add_details("item_deconstructed","[linked_destroy.loaded_item.name]")
+ for(var/material in linked_destroy.loaded_item.materials)
+ linked_lathe.materials.insert_amount(min((linked_lathe.materials.max_amount - linked_lathe.materials.total_amount), (linked_destroy.loaded_item.materials[material]*(linked_destroy.decon_mod/10))), material)
+ feedback_add_details("item_deconstructed","[linked_destroy.loaded_item.type]")
linked_destroy.loaded_item = null
else
screen = 1.0
@@ -377,33 +377,25 @@ won't update every console in existence) but it's more of a hassle to do. Also,
flick("protolathe_n",linked_lathe)
use_power(power)
- for(var/M in being_built.materials)
- if(linked_lathe.check_mat(being_built, M) < amount)
- src.visible_message("The [src.name] beeps, \"Not enough materials to complete prototype.\"")
- enough_materials = 0
- g2g = 0
- break
+ var/list/efficient_mats = list()
+ for(var/MAT in being_built.materials)
+ efficient_mats[MAT] = being_built.materials[MAT] / coeff
+
+ if(!linked_lathe.materials.has_materials(efficient_mats, amount))
+ src.visible_message("The [src.name] beeps, \"Not enough materials to complete prototype.\"")
+ enough_materials = 0
+ g2g = 0
+ else
+ for(var/R in being_built.reagents)
+ if(!linked_lathe.reagents.has_reagent(R, being_built.reagents[R]/coeff))
+ src.visible_message("The [src.name] beeps, \"Not enough reagents to complete prototype.\"")
+ enough_materials = 0
+ g2g = 0
+
if(enough_materials)
- for(var/M in being_built.materials)
- switch(M)
- if(MAT_METAL)
- linked_lathe.m_amount = max(0, (linked_lathe.m_amount-(being_built.materials[M]/coeff * amount)))
- if(MAT_GLASS)
- linked_lathe.g_amount = max(0, (linked_lathe.g_amount-(being_built.materials[M]/coeff * amount)))
- if(MAT_GOLD)
- linked_lathe.gold_amount = max(0, (linked_lathe.gold_amount-(being_built.materials[M]/coeff * amount)))
- if(MAT_SILVER)
- linked_lathe.silver_amount = max(0, (linked_lathe.silver_amount-(being_built.materials[M]/coeff * amount)))
- if(MAT_PLASMA)
- linked_lathe.plasma_amount = max(0, (linked_lathe.plasma_amount-(being_built.materials[M]/coeff * amount)))
- if(MAT_URANIUM)
- linked_lathe.uranium_amount = max(0, (linked_lathe.uranium_amount-(being_built.materials[M]/coeff * amount)))
- if(MAT_DIAMOND)
- linked_lathe.diamond_amount = max(0, (linked_lathe.diamond_amount-(being_built.materials[M]/coeff * amount)))
- if(MAT_BANANIUM)
- linked_lathe.clown_amount = max(0, (linked_lathe.clown_amount-(being_built.materials[M]/coeff * amount)))
- else
- linked_lathe.reagents.remove_reagent(M, being_built.materials[M]/coeff * amount)
+ linked_lathe.materials.use_amount(efficient_mats, amount)
+ for(var/R in being_built.reagents)
+ linked_lathe.reagents.remove_reagent(R, being_built.reagents[R]/coeff)
var/P = being_built.build_path //lets save these values before the spawn() just in case. Nobody likes runtimes.
var/R = being_built.reliability
@@ -421,7 +413,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
R = max((new_item.reliability/2), 0)
new_item.loc = linked_lathe.loc
if(!already_logged)
- feedback_add_details("item_printed","[new_item.name]|[amount]")
+ feedback_add_details("item_printed","[new_item.type]|[amount]")
already_logged = 1
linked_lathe.busy = 0
screen = old_screen
@@ -476,7 +468,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
var/obj/item/new_item = new P(src)
new_item.reliability = R
new_item.loc = linked_imprinter.loc
- feedback_add_details("circuit_printed","[new_item.name]")
+ feedback_add_details("circuit_printed","[new_item.type]")
linked_imprinter.busy = 0
screen = old_screen
updateUsrDialog()
@@ -495,40 +487,26 @@ won't update every console in existence) but it's more of a hassle to do. Also,
else if(href_list["lathe_ejectsheet"] && linked_lathe) //Causes the protolathe to eject a sheet of material
var/desired_num_sheets = text2num(href_list["lathe_ejectsheet_amt"])
- var/res_amount, type
+ var/MAT
switch(href_list["lathe_ejectsheet"])
if("metal")
- type = /obj/item/stack/sheet/metal
- res_amount = "m_amount"
+ MAT = MAT_METAL
if("glass")
- type = /obj/item/stack/sheet/glass
- res_amount = "g_amount"
+ MAT = MAT_GLASS
if("gold")
- type = /obj/item/stack/sheet/mineral/gold
- res_amount = "gold_amount"
+ MAT = MAT_GOLD
if("silver")
- type = /obj/item/stack/sheet/mineral/silver
- res_amount = "silver_amount"
+ MAT = MAT_SILVER
if("plasma")
- type = /obj/item/stack/sheet/mineral/plasma
- res_amount = "plasma_amount"
+ MAT = MAT_PLASMA
if("uranium")
- type = /obj/item/stack/sheet/mineral/uranium
- res_amount = "uranium_amount"
+ MAT = MAT_URANIUM
if("diamond")
- type = /obj/item/stack/sheet/mineral/diamond
- res_amount = "diamond_amount"
+ MAT = MAT_DIAMOND
if("clown")
- type = /obj/item/stack/sheet/mineral/bananium
- res_amount = "clown_amount"
- if(ispath(type) && hasvar(linked_lathe, res_amount))
- var/obj/item/stack/sheet/sheet = new type(linked_lathe.loc)
- var/available_num_sheets = round(linked_lathe.vars[res_amount]/sheet.perunit)
- if(available_num_sheets>0)
- sheet.amount = min(available_num_sheets, desired_num_sheets)
- linked_lathe.vars[res_amount] = max(0, (linked_lathe.vars[res_amount]-sheet.amount * sheet.perunit))
- else
- qdel(sheet)
+ MAT = MAT_BANANIUM
+ linked_lathe.materials.retrieve_sheets(desired_num_sheets, MAT)
+
else if(href_list["imprinter_ejectsheet"] && linked_imprinter) //Causes the protolathe to eject a sheet of material
var/desired_num_sheets = text2num(href_list["imprinter_ejectsheet_amt"])
var/res_amount, type
@@ -575,7 +553,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
var/choice = alert("R&D Console Database Reset", "Are you sure you want to reset the R&D console's database? Data lost cannot be recovered.", "Continue", "Cancel")
if(choice == "Continue")
screen = 0.0
- del(files)
+ qdel(files)
files = new /datum/research(src)
spawn(20)
screen = 1.6
@@ -715,11 +693,14 @@ won't update every console in existence) but it's more of a hassle to do. Also,
dat += "Load Design to Disk"
else
dat += "Name: [d_disk.blueprint.name] "
- dat += "Level: [Clamp((d_disk.blueprint.reliability + rand(-15,15)), 0, 100)] "
- switch(d_disk.blueprint.build_type)
- if(IMPRINTER) dat += "Lathe Type: Circuit Imprinter "
- if(PROTOLATHE) dat += "Lathe Type: Proto-lathe "
- if(AUTOLATHE) dat += "Lathe Type: Auto-lathe "
+ dat += "Level: [d_disk.blueprint.reliability] "
+ var/b_type = d_disk.blueprint.build_type
+ if(b_type)
+ dat += "Lathe Types: "
+ if(b_type & IMPRINTER) dat += "Circuit Imprinter "
+ if(b_type & PROTOLATHE) dat += "Proto-lathe "
+ if(b_type & AUTOLATHE) dat += "Auto-lathe "
+ if(b_type & MECHFAB) dat += "Mech Fabricator "
dat += "Required Materials: "
for(var/M in d_disk.blueprint.materials)
if(copytext(M, 1, 2) == "$") dat += "* [copytext(M, 2)] x [d_disk.blueprint.materials[M]] "
@@ -790,7 +771,12 @@ won't update every console in existence) but it's more of a hassle to do. Also,
dat += "Origin Tech: "
var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech)
for(var/T in temp_tech)
- dat += "* [CallTechName(T)] [temp_tech[T]] "
+ dat += "* [CallTechName(T)] [temp_tech[T]]"
+ for(var/datum/tech/F in files.known_tech)
+ if(F.name == CallTechName(T))
+ dat += " (Current: [F.level])"
+ break
+ dat += " "
dat += "