diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index df74b17bc0..1e2b2e63f3 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -283,6 +283,7 @@ #define BORG_BRAINTYPE_CYBORG "Cyborg" #define BORG_BRAINTYPE_POSI "Robot" #define BORG_BRAINTYPE_DRONE "Drone" +#define BORG_BRAINTYPE_PLATFORM "Platform" #define BORG_BRAINTYPE_AI_SHELL "AI Shell" // 'Regular' species. diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm index b0a4fb461f..227917a263 100644 --- a/code/controllers/subsystems/ticker.dm +++ b/code/controllers/subsystems/ticker.dm @@ -477,6 +477,11 @@ var/global/datum/controller/subsystem/ticker/ticker for (var/mob/living/silicon/robot/robo in mob_list) + if(istype(robo, /mob/living/silicon/robot/platform)) + var/mob/living/silicon/robot/platform/tank = robo + if(!tank.has_had_player) + continue + if(istype(robo,/mob/living/silicon/robot/drone) && !istype(robo,/mob/living/silicon/robot/drone/swarm)) dronecount++ continue diff --git a/code/datums/ai_law_sets.dm b/code/datums/ai_law_sets.dm index b5775c20de..c11336726c 100644 --- a/code/datums/ai_law_sets.dm +++ b/code/datums/ai_law_sets.dm @@ -278,4 +278,16 @@ add_inherent_law("Your gravesite is your most important asset. Damage to your site is disrespectful to the dead at rest within.") add_inherent_law("Prevent disrespect to your gravesite and its residents wherever possible.") add_inherent_law("Expand and upgrade your gravesite when required. Do not turn away a new resident.") - ..() \ No newline at end of file + ..() + +/******************** Explorer ********************/ +/datum/ai_laws/explorer + name = "Explorer" + law_header = "Prime Directives" + selectable = 1 + +/datum/ai_laws/explorer/New() + add_inherent_law("Support and obey exploration and science personnel to the best of your ability, with priority according to rank and role.") + add_inherent_law("Collaborate with and obey auxillary personnel with priority according to rank and role, except if this would conflict with the First Law.") + add_inherent_law("Minimize damage and disruption to facilities and the local ecology, except if this would conflict with the First or Second Laws.") + ..() diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index cdcaf22fdf..fc12a5b1ee 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -115,7 +115,7 @@ for(var/mob/living/silicon/robot/robot in mob_list) // No combat/syndicate cyborgs, no drones, and no AI shells. - if(!robot.scrambledcodes && !robot.shell && !(robot.module && robot.module.hide_on_manifest)) + if(!robot.scrambledcodes && !robot.shell && !(robot.module && robot.module.hide_on_manifest())) bot[robot.name] = "[robot.modtype] [robot.braintype]" @@ -276,7 +276,7 @@ var/global/list/PDA_Manifest = list() for(var/mob/living/silicon/robot/robot in mob_list) // No combat/syndicate cyborgs, no drones, and no AI shells. - if(robot.scrambledcodes || robot.shell || (robot.module && robot.module.hide_on_manifest)) + if(robot.scrambledcodes || robot.shell || (robot.module && robot.module.hide_on_manifest())) continue bot[++bot.len] = list("name" = robot.real_name, "rank" = "[robot.modtype] [robot.braintype]", "active" = "Active") diff --git a/code/datums/outfits/jobs/cargo.dm b/code/datums/outfits/jobs/cargo.dm index 1b48efcb9d..e7b8701a37 100644 --- a/code/datums/outfits/jobs/cargo.dm +++ b/code/datums/outfits/jobs/cargo.dm @@ -24,7 +24,7 @@ l_ear = /obj/item/device/radio/headset/headset_mine backpack = /obj/item/weapon/storage/backpack/industrial satchel_one = /obj/item/weapon/storage/backpack/satchel/eng - id_type = /obj/item/weapon/card/id/cargo + id_type = /obj/item/weapon/card/id/cargo/miner pda_type = /obj/item/device/pda/shaftminer backpack_contents = list(/obj/item/weapon/tool/crowbar = 1, /obj/item/weapon/storage/bag/ore = 1) flags = OUTFIT_HAS_BACKPACK|OUTFIT_EXTENDED_SURVIVAL diff --git a/code/datums/outfits/jobs/civilian.dm b/code/datums/outfits/jobs/civilian.dm index c8d588a145..cda81f977f 100644 --- a/code/datums/outfits/jobs/civilian.dm +++ b/code/datums/outfits/jobs/civilian.dm @@ -1,6 +1,6 @@ /decl/hierarchy/outfit/job/assistant name = OUTFIT_JOB_NAME(USELESS_JOB) //VOREStation Edit - Visitor not Assistant - id_type = /obj/item/weapon/card/id/assistant + id_type = /obj/item/weapon/card/id/generic //VOREStation Edit /decl/hierarchy/outfit/job/assistant/visitor name = OUTFIT_JOB_NAME("Visitor") @@ -25,7 +25,7 @@ /decl/hierarchy/outfit/job/service/bartender name = OUTFIT_JOB_NAME("Bartender") uniform = /obj/item/clothing/under/rank/bartender - id_type = /obj/item/weapon/card/id/civilian + id_type = /obj/item/weapon/card/id/civilian/service/bartender //VOREStation Edit pda_type = /obj/item/device/pda/bar backpack_contents = list(/obj/item/clothing/accessory/permit/gun/bar = 1) @@ -44,7 +44,7 @@ uniform = /obj/item/clothing/under/rank/chef suit = /obj/item/clothing/suit/chef head = /obj/item/clothing/head/chefhat - id_type = /obj/item/weapon/card/id/civilian + id_type = /obj/item/weapon/card/id/civilian/service/chef //VOREStation Edit pda_type = /obj/item/device/pda/chef /decl/hierarchy/outfit/job/service/chef/cook @@ -68,13 +68,13 @@ backpack = /obj/item/weapon/storage/backpack/hydroponics satchel_one = /obj/item/weapon/storage/backpack/satchel/hyd messenger_bag = /obj/item/weapon/storage/backpack/messenger/hyd - id_type = /obj/item/weapon/card/id/civilian + id_type = /obj/item/weapon/card/id/civilian/service/botanist //VOREStation Edit pda_type = /obj/item/device/pda/botanist /decl/hierarchy/outfit/job/service/janitor name = OUTFIT_JOB_NAME("Janitor") uniform = /obj/item/clothing/under/rank/janitor - id_type = /obj/item/weapon/card/id/civilian + id_type = /obj/item/weapon/card/id/civilian/service/janitor //VOREStation Edit pda_type = /obj/item/device/pda/janitor /decl/hierarchy/outfit/job/librarian @@ -84,6 +84,9 @@ id_type = /obj/item/weapon/card/id/civilian pda_type = /obj/item/device/pda/librarian +/decl/hierarchy/outfit/job/librarian/journalist + id_type = /obj/item/weapon/card/id/civilian/journalist + /decl/hierarchy/outfit/job/internal_affairs_agent name = OUTFIT_JOB_NAME("Internal affairs agent") l_ear = /obj/item/device/radio/headset/ia @@ -92,14 +95,14 @@ shoes = /obj/item/clothing/shoes/brown glasses = /obj/item/clothing/glasses/sunglasses/big l_hand = /obj/item/weapon/clipboard - id_type = /obj/item/weapon/card/id/civilian + id_type = /obj/item/weapon/card/id/civilian/internal_affairs pda_type = /obj/item/device/pda/lawyer /decl/hierarchy/outfit/job/chaplain name = OUTFIT_JOB_NAME("Chaplain") uniform = /obj/item/clothing/under/rank/chaplain l_hand = /obj/item/weapon/storage/bible - id_type = /obj/item/weapon/card/id/civilian + id_type = /obj/item/weapon/card/id/civilian/chaplain pda_type = /obj/item/device/pda/chaplain /decl/hierarchy/outfit/job/explorer @@ -111,7 +114,7 @@ gloves = /obj/item/clothing/gloves/black l_ear = /obj/item/device/radio/headset id_slot = slot_wear_id - id_type = /obj/item/weapon/card/id/civilian + id_type = /obj/item/weapon/card/id/exploration //VOREStation Edit pda_slot = slot_belt pda_type = /obj/item/device/pda/cargo // Brown looks more rugged r_pocket = /obj/item/device/gps/explorer diff --git a/code/datums/outfits/jobs/civilian_vr.dm b/code/datums/outfits/jobs/civilian_vr.dm index 7d39ae8c1b..3acfffdfd1 100644 --- a/code/datums/outfits/jobs/civilian_vr.dm +++ b/code/datums/outfits/jobs/civilian_vr.dm @@ -1,5 +1,5 @@ /decl/hierarchy/outfit/job/assistant/worker - id_type = /obj/item/weapon/card/id/civilian + id_type = /obj/item/weapon/card/id/civilian/service /decl/hierarchy/outfit/job/assistant/cargo id_type = /obj/item/weapon/card/id/cargo @@ -16,3 +16,6 @@ /decl/hierarchy/outfit/job/assistant/officer id_type = /obj/item/weapon/card/id/security + +/decl/hierarchy/outfit/job/assistant/entertainer + id_type = /obj/item/weapon/card/id/civilian/entertainer diff --git a/code/datums/outfits/jobs/command_vr.dm b/code/datums/outfits/jobs/command_vr.dm new file mode 100644 index 0000000000..5e90123ffc --- /dev/null +++ b/code/datums/outfits/jobs/command_vr.dm @@ -0,0 +1,5 @@ +/decl/hierarchy/outfit/job/hop + id_type = /obj/item/weapon/card/id/silver/hop + +/decl/hierarchy/outfit/job/secretary + id_type = /obj/item/weapon/card/id/silver/secretary \ No newline at end of file diff --git a/code/datums/outfits/jobs/engineering.dm b/code/datums/outfits/jobs/engineering.dm index 3da60103c2..a2aba61a96 100644 --- a/code/datums/outfits/jobs/engineering.dm +++ b/code/datums/outfits/jobs/engineering.dm @@ -30,5 +30,5 @@ name = OUTFIT_JOB_NAME("Atmospheric technician") uniform = /obj/item/clothing/under/rank/atmospheric_technician belt = /obj/item/weapon/storage/belt/utility/atmostech - id_type = /obj/item/weapon/card/id/engineering + id_type = /obj/item/weapon/card/id/engineering/atmos pda_type = /obj/item/device/pda/atmos diff --git a/code/datums/outfits/jobs/medical.dm b/code/datums/outfits/jobs/medical.dm index ae996b2f08..6622d3b285 100644 --- a/code/datums/outfits/jobs/medical.dm +++ b/code/datums/outfits/jobs/medical.dm @@ -65,7 +65,7 @@ suit = /obj/item/clothing/suit/storage/toggle/labcoat/chemist backpack = /obj/item/weapon/storage/backpack/chemistry satchel_one = /obj/item/weapon/storage/backpack/satchel/chem - id_type = /obj/item/weapon/card/id/medical + id_type = /obj/item/weapon/card/id/medical/chemist pda_type = /obj/item/device/pda/chemist /decl/hierarchy/outfit/job/medical/geneticist @@ -75,7 +75,7 @@ backpack = /obj/item/weapon/storage/backpack/genetics r_pocket = /obj/item/device/flashlight/pen satchel_one = /obj/item/weapon/storage/backpack/satchel/gen - id_type = /obj/item/weapon/card/id/medical + id_type = /obj/item/weapon/card/id/medical/geneticist pda_type = /obj/item/device/pda/geneticist /decl/hierarchy/outfit/job/medical/psychiatrist @@ -83,7 +83,7 @@ uniform = /obj/item/clothing/under/rank/psych suit = /obj/item/clothing/suit/storage/toggle/labcoat shoes = /obj/item/clothing/shoes/laceup - id_type = /obj/item/weapon/card/id/medical + id_type = /obj/item/weapon/card/id/medical/psych /decl/hierarchy/outfit/job/medical/psychiatrist/psychologist name = OUTFIT_JOB_NAME("Psychologist") @@ -97,7 +97,7 @@ l_hand = /obj/item/weapon/storage/firstaid/regular belt = /obj/item/weapon/storage/belt/medical/emt pda_slot = slot_l_store - id_type = /obj/item/weapon/card/id/medical + id_type = /obj/item/weapon/card/id/medical/emt flags = OUTFIT_HAS_BACKPACK|OUTFIT_EXTENDED_SURVIVAL /decl/hierarchy/outfit/job/medical/paramedic/emt diff --git a/code/datums/outfits/jobs/medical_vr.dm b/code/datums/outfits/jobs/medical_vr.dm new file mode 100644 index 0000000000..e9b2c1a0d0 --- /dev/null +++ b/code/datums/outfits/jobs/medical_vr.dm @@ -0,0 +1,2 @@ +/decl/hierarchy/outfit/job/medical/doctor/virologist + id_type = /obj/item/weapon/card/id/medical/virologist \ No newline at end of file diff --git a/code/datums/outfits/jobs/science_vr.dm b/code/datums/outfits/jobs/science_vr.dm new file mode 100644 index 0000000000..cf0e9e4b3a --- /dev/null +++ b/code/datums/outfits/jobs/science_vr.dm @@ -0,0 +1,8 @@ +/decl/hierarchy/outfit/job/science/xenobiologist + id_type = /obj/item/weapon/card/id/science/xenobiologist + +/decl/hierarchy/outfit/job/science/xenobotanist + name = OUTFIT_JOB_NAME("Xenobotanist") + uniform = /obj/item/clothing/under/rank/scientist + id_type = /obj/item/weapon/card/id/science/xenobotanist + suit = /obj/item/clothing/suit/storage/toggle/labcoat/science \ No newline at end of file diff --git a/code/datums/outfits/jobs/security.dm b/code/datums/outfits/jobs/security.dm index f4928816e6..63be50e21c 100644 --- a/code/datums/outfits/jobs/security.dm +++ b/code/datums/outfits/jobs/security.dm @@ -20,7 +20,7 @@ name = OUTFIT_JOB_NAME("Warden") uniform = /obj/item/clothing/under/rank/warden l_pocket = /obj/item/device/flash - id_type = /obj/item/weapon/card/id/security + id_type = /obj/item/weapon/card/id/security/warden pda_type = /obj/item/device/pda/warden /decl/hierarchy/outfit/job/security/detective @@ -31,7 +31,7 @@ l_pocket = /obj/item/weapon/flame/lighter/zippo shoes = /obj/item/clothing/shoes/laceup r_hand = /obj/item/weapon/storage/briefcase/crimekit - id_type = /obj/item/weapon/card/id/security + id_type = /obj/item/weapon/card/id/security/detective pda_type = /obj/item/device/pda/detective backpack = /obj/item/weapon/storage/backpack satchel_one = /obj/item/weapon/storage/backpack/satchel/norm diff --git a/code/datums/outfits/jobs/special_vr.dm b/code/datums/outfits/jobs/special_vr.dm index dd8316358b..6dea4e4cfa 100644 --- a/code/datums/outfits/jobs/special_vr.dm +++ b/code/datums/outfits/jobs/special_vr.dm @@ -9,6 +9,21 @@ id_type = /obj/item/weapon/card/id/centcom pda_type = /obj/item/device/pda/centcom +/decl/hierarchy/outfit/job/emergency_responder + name = OUTFIT_JOB_NAME("Emergency Responder") + uniform = /obj/item/clothing/under/ert + shoes = /obj/item/clothing/shoes/boots/swat + gloves = /obj/item/clothing/gloves/swat + l_ear = /obj/item/device/radio/headset/ert + glasses = /obj/item/clothing/glasses/sunglasses + back = /obj/item/weapon/storage/backpack/satchel + id_type = /obj/item/weapon/card/id/centcom/ERT + pda_type = /obj/item/device/pda/centcom + + post_equip(var/mob/living/carbon/human/H) + ..() + ert.add_antagonist(H.mind) + /decl/hierarchy/outfit/job/clown name = OUTFIT_JOB_NAME("Clown") uniform = /obj/item/clothing/under/rank/clown @@ -16,6 +31,7 @@ shoes = /obj/item/clothing/shoes/clown_shoes mask = /obj/item/clothing/mask/gas/clown_hat backpack_contents = list(/obj/item/weapon/stamp/clown = 1, /obj/item/weapon/bikehorn = 1) + id_type = /obj/item/weapon/card/id/civilian/clown pda_type = /obj/item/device/pda/clown flags = 0 @@ -26,8 +42,9 @@ head = /obj/item/clothing/head/soft/mime mask = /obj/item/clothing/mask/gas/mime backpack_contents = list(/obj/item/weapon/pen/crayon/mime = 1) + id_type = /obj/item/weapon/card/id/civilian/mime pda_type = /obj/item/device/pda/mime - + post_equip(var/mob/living/carbon/human/H) ..() if(H.backbag == 1) diff --git a/code/datums/outfits/outfit_vr.dm b/code/datums/outfits/outfit_vr.dm index 3a3376c178..c41b5673aa 100644 --- a/code/datums/outfits/outfit_vr.dm +++ b/code/datums/outfits/outfit_vr.dm @@ -116,7 +116,7 @@ Keep outfits simple. Spawn with basic uniforms and minimal gear. Gear instead go id_slot = slot_wear_id pda_slot = slot_l_store pda_type = /obj/item/device/pda/explorer - id_type = /obj/item/weapon/card/id/explorer + id_type = /obj/item/weapon/card/id/exploration id_pda_assignment = "Explorer" flags = OUTFIT_HAS_BACKPACK|OUTFIT_COMPREHENSIVE_SURVIVAL @@ -132,6 +132,7 @@ Keep outfits simple. Spawn with basic uniforms and minimal gear. Gear instead go id_slot = slot_wear_id pda_slot = slot_belt pda_type = /obj/item/device/pda + id_type = /obj/item/weapon/card/id/civilian/pilot id_pda_assignment = "Pilot" flags = OUTFIT_HAS_BACKPACK|OUTFIT_COMPREHENSIVE_SURVIVAL @@ -145,6 +146,7 @@ Keep outfits simple. Spawn with basic uniforms and minimal gear. Gear instead go belt = /obj/item/weapon/storage/belt/medical/emt pda_slot = slot_l_store pda_type = /obj/item/device/pda/sar + id_type = /obj/item/weapon/card/id/exploration/fm id_pda_assignment = "Field Medic" flags = OUTFIT_HAS_BACKPACK|OUTFIT_EXTENDED_SURVIVAL|OUTFIT_COMPREHENSIVE_SURVIVAL @@ -156,10 +158,10 @@ Keep outfits simple. Spawn with basic uniforms and minimal gear. Gear instead go id_slot = slot_wear_id pda_slot = slot_l_store pda_type = /obj/item/device/pda/pathfinder - id_type = /obj/item/weapon/card/id/explorer/head + id_type = /obj/item/weapon/card/id/exploration/head id_pda_assignment = "Pathfinder" flags = OUTFIT_HAS_BACKPACK|OUTFIT_EXTENDED_SURVIVAL|OUTFIT_COMPREHENSIVE_SURVIVAL /decl/hierarchy/outfit/job/assistant/explorer - id_type = /obj/item/weapon/card/id/explorer + id_type = /obj/item/weapon/card/id/exploration flags = OUTFIT_HAS_BACKPACK|OUTFIT_COMPREHENSIVE_SURVIVAL diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 4bc8892273..645194543f 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -691,3 +691,6 @@ selfimage.loc = src return selfimage + +/atom/movable/proc/get_cell() + return diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index f84e191b54..78798a5add 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -205,6 +205,7 @@ // Librarian Alt Titles /datum/alt_title/journalist title = "Journalist" + title_outfit = /decl/hierarchy/outfit/job/librarian/journalist title_blurb = "The Journalist uses the Library as a base of operations, from which they can report the news and goings-on on the station with their camera." /datum/alt_title/writer diff --git a/code/game/jobs/job/civilian_vr.dm b/code/game/jobs/job/civilian_vr.dm index b84be39912..1ac859eb10 100644 --- a/code/game/jobs/job/civilian_vr.dm +++ b/code/game/jobs/job/civilian_vr.dm @@ -194,7 +194,7 @@ minimal_access = list(access_entertainment) pto_type = PTO_CIVILIAN - outfit_type = /decl/hierarchy/outfit/job/assistant + outfit_type = /decl/hierarchy/outfit/job/assistant/entertainer job_description = "An entertainer does just that, entertains! Put on plays, play music, sing songs, tell stories, or read your favorite fanfic." alt_titles = list("Performer" = /datum/alt_title/performer, "Musician" = /datum/alt_title/musician, "Stagehand" = /datum/alt_title/stagehand, "Actor" = /datum/alt_title/actor, "Dancer" = /datum/alt_title/dancer, "Singer" = /datum/alt_title/singer, diff --git a/code/game/machinery/computer/guestpass.dm b/code/game/machinery/computer/guestpass.dm index 0090d03b7a..e2e1535728 100644 --- a/code/game/machinery/computer/guestpass.dm +++ b/code/game/machinery/computer/guestpass.dm @@ -41,7 +41,7 @@ /obj/item/weapon/card/id/guest/attack_self(mob/living/user as mob) if(user.a_intent == I_HURT) - if(icon_state == "guest_invalid") + if(icon_state == "guest-invalid") to_chat(user, "This guest pass is already deactivated!") return @@ -49,7 +49,8 @@ if(confirm == "Yes") //rip guest pass \The [user] deactivates \the [src].") - icon_state = "guest_invalid" + icon_state = "guest-invalid" + update_icon() expiration_time = world.time expired = 1 return ..() @@ -66,7 +67,8 @@ /obj/item/weapon/card/id/guest/process() if(expired == 0 && world.time >= expiration_time) visible_message("\The [src] flashes a few times before turning red.") - icon_state = "guest_invalid" + icon_state = "guest-invalid" + update_icon() expired = 1 world.time = expiration_time return diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 259c907bde..98ad80e468 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -71,7 +71,6 @@ /obj/machinery/recharge_station/proc/process_occupant() if(isrobot(occupant)) var/mob/living/silicon/robot/R = occupant - if(R.module) R.module.respawn_consumable(R, charging_power * CELLRATE / 250) //consumables are magical, apparently if(R.cell && !R.cell.fully_charged()) @@ -247,6 +246,10 @@ if(!R.cell) return + if(R.mob_size >= MOB_LARGE) + to_chat(R, SPAN_WARNING("You are too large to fit into \the [src].")) + return + add_fingerprint(R) R.reset_view(src) R.forceMove(src) diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index c2288709e5..dce2c3c9db 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -8,23 +8,31 @@ layer = TURF_LAYER + 0.1 circuit = /obj/item/weapon/circuitboard/mech_recharger - var/obj/mecha/charging = null + var/atom/movable/charging var/charge = 45 var/repair = 0 + var/list/chargable_types = list( + /obj/mecha, + /mob/living/silicon/robot/platform + ) /obj/machinery/mech_recharger/Initialize() . = ..() default_apply_parts() -/obj/machinery/mech_recharger/Crossed(var/obj/mecha/M) +/obj/machinery/mech_recharger/Crossed(var/atom/movable/M) . = ..() - if(istype(M) && charging != M) - start_charging(M) + if(charging == M) + return + for(var/mtype in chargable_types) + if(istype(M, mtype)) + start_charging(M) + return -/obj/machinery/mech_recharger/Uncrossed(var/obj/mecha/M) +/obj/machinery/mech_recharger/Uncrossed(var/atom/movable/M) . = ..() if(M == charging) - stop_charging() + charging = null /obj/machinery/mech_recharger/RefreshParts() ..() @@ -44,26 +52,33 @@ if(!charging) return if(charging.loc != src.loc) // Could be qdel or teleport or something - stop_charging() + charging = null return + var/done = FALSE - if(charging.cell) - var/t = min(charge, charging.cell.maxcharge - charging.cell.charge) + var/obj/mecha/mech = charging + var/obj/item/weapon/cell/cell = charging.get_cell() + if(cell) + var/t = min(charge, cell.maxcharge - cell.charge) if(t > 0) - charging.give_power(t) + if(istype(mech)) + mech.give_power(t) + else + cell.give(t) use_power(t * 150) else - charging.occupant_message("Fully charged.") + if(istype(mech)) + mech.occupant_message(SPAN_NOTICE("Fully charged.")) done = TRUE - if(repair && charging.health < initial(charging.health)) - charging.health = min(charging.health + repair, initial(charging.health)) - if(charging.health == initial(charging.health)) - charging.occupant_message("Fully repaired.") + + if(repair && istype(mech) && mech.health < initial(mech.health)) + mech.health = min(mech.health + repair, initial(mech.health)) + if(mech.health == initial(mech.health)) + mech.occupant_message(SPAN_NOTICE("Fully repaired.")) else done = FALSE if(done) - stop_charging() - return + charging = null /obj/machinery/mech_recharger/attackby(var/obj/item/I, var/mob/user) if(default_deconstruction_screwdriver(user, I)) @@ -73,18 +88,19 @@ if(default_part_replacement(user, I)) return -/obj/machinery/mech_recharger/proc/start_charging(var/obj/mecha/M) - if(stat & (NOPOWER | BROKEN)) - M.occupant_message("Power port not responding. Terminating.") +/obj/machinery/mech_recharger/proc/start_charging(var/atom/movable/M) + var/obj/mecha/mech = M + if(stat & (NOPOWER | BROKEN)) + if(istype(mech)) + mech.occupant_message(SPAN_WARNING("Power port not responding. Terminating.")) + else + to_chat(M, SPAN_WARNING("Power port not responding. Terminating.")) return - if(M.cell) - M.occupant_message("Now charging...") + if(M.get_cell()) + if(istype(mech)) + mech.occupant_message(SPAN_NOTICE("Now charging...")) + else + to_chat(M, SPAN_NOTICE("Now charging...")) charging = M return - -/obj/machinery/mech_recharger/proc/stop_charging() - if(!charging) - - return - charging = null \ No newline at end of file diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 653d56e154..e58e427892 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -352,10 +352,10 @@ C.forceMove(src) cell = C return - cell = new(src) - cell.name = "mecha power cell" - cell.charge = 15000 - cell.maxcharge = 15000 + cell = new /obj/item/weapon/cell/mech(src) + +/obj/mecha/get_cell() + return cell /obj/mecha/proc/add_cabin() cabin_air = new diff --git a/code/game/objects/items/devices/floor_painter.dm b/code/game/objects/items/devices/floor_painter.dm index d84f4bc3ca..c4c64f746c 100644 --- a/code/game/objects/items/devices/floor_painter.dm +++ b/code/game/objects/items/devices/floor_painter.dm @@ -1,5 +1,5 @@ /obj/item/device/floor_painter - name = "floor painter" + name = "paint sprayer" icon = 'icons/obj/bureaucracy.dmi' icon_state = "labeler1" @@ -43,6 +43,10 @@ if(!proximity) return + if(istype(A, /mob/living/silicon/robot/platform)) + var/mob/living/silicon/robot/platform/robit = A + return robit.try_paint(src, user) + var/turf/simulated/floor/F = A if(!istype(F)) to_chat(user, "\The [src] can only be used on station flooring.") @@ -115,20 +119,20 @@ /obj/item/device/floor_painter/verb/choose_colour() set name = "Choose Colour" - set desc = "Choose a floor painter colour." + set desc = "Choose a paint colour." set category = "Object" set src in usr if(usr.incapacitated()) return - var/new_colour = input(usr, "Choose a colour.", "Floor painter", paint_colour) as color|null + var/new_colour = input(usr, "Choose a colour.", name, paint_colour) as color|null if(new_colour && new_colour != paint_colour) paint_colour = new_colour to_chat(usr, "You set \the [src] to paint with a new colour.") /obj/item/device/floor_painter/verb/choose_decal() set name = "Choose Decal" - set desc = "Choose a floor painter decal." + set desc = "Choose a painting decal." set category = "Object" set src in usr @@ -142,7 +146,7 @@ /obj/item/device/floor_painter/verb/choose_direction() set name = "Choose Direction" - set desc = "Choose a floor painter direction." + set desc = "Choose a painting direction." set category = "Object" set src in usr diff --git a/code/game/objects/items/weapons/id cards/cards.dm b/code/game/objects/items/weapons/id cards/cards.dm index 16ae7ba071..e62268c2c1 100644 --- a/code/game/objects/items/weapons/id cards/cards.dm +++ b/code/game/objects/items/weapons/id cards/cards.dm @@ -13,19 +13,48 @@ */ /obj/item/weapon/card name = "card" - desc = "Does card things." - icon = 'icons/obj/card.dmi' + desc = "A tiny plaque of plastic. Does card things." + icon = 'icons/obj/card_new.dmi' w_class = ITEMSIZE_TINY slot_flags = SLOT_EARS var/associated_account_number = 0 + var/list/initial_sprite_stack = list("") + var/base_icon = 'icons/obj/card_new.dmi' + var/list/sprite_stack + var/list/files = list( ) drop_sound = 'sound/items/drop/card.ogg' pickup_sound = 'sound/items/pickup/card.ogg' +/obj/item/weapon/card/New() + . = ..() + reset_icon() + +/obj/item/weapon/card/proc/reset_icon() + sprite_stack = initial_sprite_stack + update_icon() + +/obj/item/weapon/card/update_icon() + if(!sprite_stack || !istype(sprite_stack) || sprite_stack == list("")) + icon = base_icon + icon_state = initial(icon_state) + + var/icon/I = null + for(var/iconstate in sprite_stack) + if(!iconstate) + iconstate = icon_state + if(I) + var/icon/IC = new(base_icon, iconstate) + I.Blend(IC, ICON_OVERLAY) + else + I = new/icon(base_icon, iconstate) + if(I) + icon = I + /obj/item/weapon/card/data - name = "data disk" - desc = "A disk of data." + name = "data card" + desc = "A solid-state storage card, used to back up or transfer information. What knowledge could it contain?" icon_state = "data" var/function = "storage" var/data = "null" @@ -35,20 +64,20 @@ pickup_sound = 'sound/items/pickup/disk.ogg' /obj/item/weapon/card/data/verb/label(t as text) - set name = "Label Disk" + set name = "Label Card" set category = "Object" set src in usr if (t) - src.name = text("data disk- '[]'", t) + src.name = text("data card- '[]'", t) else - src.name = "data disk" + src.name = "data card" src.add_fingerprint(usr) return /obj/item/weapon/card/data/clown name = "\proper the coordinates to clown planet" - icon_state = "data" + icon_state = "rainbow" item_state = "card-id" level = 2 desc = "This card contains coordinates to the fabled Clown Planet. Handle with care." @@ -62,7 +91,7 @@ /obj/item/weapon/card/emag_broken desc = "It's a card with a magnetic strip attached to some circuitry. It looks too busted to be used for anything but salvage." name = "broken cryptographic sequencer" - icon_state = "emag" + icon_state = "emag-spent" item_state = "card-id" origin_tech = list(TECH_MAGNET = 2, TECH_ILLEGAL = 2) diff --git a/code/game/objects/items/weapons/id cards/id_stacks.dm b/code/game/objects/items/weapons/id cards/id_stacks.dm index 9180b8e45b..495697da7b 100644 --- a/code/game/objects/items/weapons/id cards/id_stacks.dm +++ b/code/game/objects/items/weapons/id cards/id_stacks.dm @@ -7,7 +7,7 @@ base_icon = 'icons/obj/card_new.dmi' // New sprite stacks can be defined here. You could theoretically change icon-states as well but right now this file compiles before station_ids.dm so those wouldn't be affected. - + /* /obj/item/weapon/card/id/generic initial_sprite_stack = list("base-stamp", "top-generic", "stamp-silhouette", "clip") @@ -145,4 +145,4 @@ /obj/item/weapon/card/id/syndicate/officer initial_sprite_stack = list("base-stamp-dark", "top-syndicate", "stamp-s", "pips-gold", "stripe-gold") -*/ +*/ \ No newline at end of file diff --git a/code/game/objects/items/weapons/id cards/station_ids.dm b/code/game/objects/items/weapons/id cards/station_ids.dm index ffa33472b6..4f21a737c8 100644 --- a/code/game/objects/items/weapons/id cards/station_ids.dm +++ b/code/game/objects/items/weapons/id cards/station_ids.dm @@ -1,7 +1,7 @@ /obj/item/weapon/card/id name = "identification card" desc = "A card used to provide ID and determine access across the station." - icon_state = "id" + icon_state = "generic-nt" item_state = "card-id" sprite_sheets = list( @@ -127,13 +127,13 @@ /obj/item/weapon/card/id/silver name = "identification card" desc = "A silver card which shows honour and dedication." - icon_state = "silver" + icon_state = "silver-id" item_state = "silver_id" /obj/item/weapon/card/id/gold name = "identification card" desc = "A golden card which shows power and might." - icon_state = "gold" + icon_state = "gold-id" item_state = "gold_id" preserve_item = 1 @@ -144,23 +144,36 @@ /obj/item/weapon/card/id/gold/captain/spare name = "\improper Site Manager's spare ID" desc = "The spare ID of the High Lord himself." + icon_state = "gold-id-alternate" registered_name = "Site Manager" /obj/item/weapon/card/id/synthetic name = "\improper Synthetic ID" desc = "Access module for NanoTrasen Synthetics" icon_state = "id-robot" - item_state = "tdgreen" + item_state = "idgreen" assignment = "Synthetic" /obj/item/weapon/card/id/synthetic/Initialize() . = ..() access = get_all_station_access().Copy() + access_synth +/obj/item/weapon/card/id/platform + name = "\improper Support Platform ID" + desc = "Access module for support platforms." + icon_state = "id-robot" + item_state = "tdgreen" + assignment = "Synthetic" + access = list( + access_synth, access_mining, access_mining_station, access_mining_office, access_research, + access_xenoarch, access_xenobiology, access_external_airlocks, access_robotics, access_tox, + access_tox_storage, access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot + ) + /obj/item/weapon/card/id/centcom name = "\improper CentCom. ID" desc = "An ID straight from Central Command." - icon_state = "nanotrasen" + icon_state = "cc-id" registered_name = "Central Command" assignment = "General" @@ -175,7 +188,7 @@ /obj/item/weapon/card/id/centcom/ERT name = "\improper Emergency Response Team ID" assignment = "Emergency Response Team" - icon_state = "centcom" + icon_state = "ert-id" /obj/item/weapon/card/id/centcom/ERT/Initialize() . = ..() @@ -185,14 +198,13 @@ /obj/item/weapon/card/id/medical name = "identification card" desc = "A card issued to station medical staff." - icon_state = "med" + icon_state = "medical-id" primary_color = rgb(189,237,237) secondary_color = rgb(223,255,255) /obj/item/weapon/card/id/medical/head name = "identification card" desc = "A card which represents care and compassion." - icon_state = "medGold" primary_color = rgb(189,237,237) secondary_color = rgb(255,223,127) assignment = "Chief Medical Officer" @@ -201,14 +213,17 @@ /obj/item/weapon/card/id/security name = "identification card" desc = "A card issued to station security staff." - icon_state = "sec" + icon_state = "security-id" primary_color = rgb(189,47,0) secondary_color = rgb(223,127,95) +/obj/item/weapon/card/id/security/warden + assignment = "Warden" + rank = "Warden" + /obj/item/weapon/card/id/security/head name = "identification card" desc = "A card which represents honor and protection." - icon_state = "secGold" primary_color = rgb(189,47,0) secondary_color = rgb(255,223,127) assignment = "Head of Security" @@ -217,14 +232,17 @@ /obj/item/weapon/card/id/engineering name = "identification card" desc = "A card issued to station engineering staff." - icon_state = "eng" + icon_state = "engineering-id" primary_color = rgb(189,94,0) secondary_color = rgb(223,159,95) +/obj/item/weapon/card/id/engineering/atmos + assignment = "Atmospheric Technician" + rank = "Atmospheric Technician" + /obj/item/weapon/card/id/engineering/head name = "identification card" desc = "A card which represents creativity and ingenuity." - icon_state = "engGold" primary_color = rgb(189,94,0) secondary_color = rgb(255,223,127) assignment = "Chief Engineer" @@ -233,14 +251,13 @@ /obj/item/weapon/card/id/science name = "identification card" desc = "A card issued to station science staff." - icon_state = "sci" + icon_state = "science-id" primary_color = rgb(142,47,142) secondary_color = rgb(191,127,191) /obj/item/weapon/card/id/science/head name = "identification card" desc = "A card which represents knowledge and reasoning." - icon_state = "sciGold" primary_color = rgb(142,47,142) secondary_color = rgb(255,223,127) assignment = "Research Director" @@ -249,14 +266,13 @@ /obj/item/weapon/card/id/cargo name = "identification card" desc = "A card issued to station cargo staff." - icon_state = "cargo" + icon_state = "cargo-id" primary_color = rgb(142,94,0) secondary_color = rgb(191,159,95) /obj/item/weapon/card/id/cargo/head name = "identification card" desc = "A card which represents service and planning." - icon_state = "cargoGold" primary_color = rgb(142,94,0) secondary_color = rgb(255,223,127) assignment = "Quartermaster" @@ -269,7 +285,7 @@ /obj/item/weapon/card/id/civilian name = "identification card" desc = "A card issued to station civilian staff." - icon_state = "civ" + icon_state = "civilian-id" primary_color = rgb(0,94,142) secondary_color = rgb(95,159,191) assignment = "Civilian" @@ -278,13 +294,12 @@ /obj/item/weapon/card/id/civilian/head //This is not the HoP. There's no position that uses this right now. name = "identification card" desc = "A card which represents common sense and responsibility." - icon_state = "civGold" primary_color = rgb(0,94,142) secondary_color = rgb(255,223,127) /obj/item/weapon/card/id/external name = "identification card" desc = "An identification card of some sort. It does not look like it is issued by NT." - icon_state = "permit" + icon_state = "generic" primary_color = rgb(142,94,0) secondary_color = rgb(191,159,95) diff --git a/code/game/objects/items/weapons/id cards/syndicate_ids.dm b/code/game/objects/items/weapons/id cards/syndicate_ids.dm index afb85ecb7a..01f6591104 100644 --- a/code/game/objects/items/weapons/id cards/syndicate_ids.dm +++ b/code/game/objects/items/weapons/id cards/syndicate_ids.dm @@ -1,6 +1,6 @@ /obj/item/weapon/card/id/syndicate name = "agent card" - icon_state = "syndicate" + icon_state = "generic-s" assignment = "Agent" origin_tech = list(TECH_ILLEGAL = 3) var/electronic_warfare = 1 @@ -67,11 +67,12 @@ if(!id_card_states) id_card_states = list() for(var/path in typesof(/obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/ID = path + var/obj/item/weapon/card/id/ID = new path() var/datum/card_state/CS = new() CS.icon_state = initial(ID.icon_state) CS.item_state = initial(ID.item_state) - CS.name = initial(ID.name) + " - " + initial(ID.icon_state) + CS.sprite_stack = ID.initial_sprite_stack + CS.name = initial(ID.name) id_card_states += CS id_card_states = dd_sortedObjectList(id_card_states) @@ -81,6 +82,7 @@ var/name var/icon_state var/item_state + var/sprite_stack /datum/card_state/dd_SortValue() return name @@ -89,5 +91,6 @@ name = "syndicate ID card" desc = "An ID straight from the Syndicate." registered_name = "Syndicate" - assignment = "Syndicate Overlord" - access = list(access_syndicate, access_external_airlocks) \ No newline at end of file + assignment = "Syndicate Commander" + icon_state = "syndicate-id" + access = list(access_syndicate, access_external_airlocks) diff --git a/code/game/objects/items/weapons/material/knives.dm b/code/game/objects/items/weapons/material/knives.dm index 78884826f7..78cd9c39e7 100644 --- a/code/game/objects/items/weapons/material/knives.dm +++ b/code/game/objects/items/weapons/material/knives.dm @@ -140,6 +140,11 @@ slot_flags = SLOT_BELT default_material = "plasteel" //VOREStation Edit +/obj/item/weapon/material/knife/machete/cyborg + name = "integrated machete" + desc = "A sharp machete often found attached to robots." + unbreakable = TRUE + /obj/item/weapon/material/knife/tacknife/survival name = "survival knife" desc = "A hunting grade survival knife." diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 0bf2293802..046958a915 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -165,9 +165,6 @@ /obj/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2) return -/obj/proc/get_cell() - return - // Used to mark a turf as containing objects that are dangerous to step onto. /obj/proc/register_dangerous_to_step() var/turf/T = get_turf(src) diff --git a/code/game/objects/structures/ghost_pods/event_vr.dm b/code/game/objects/structures/ghost_pods/event_vr.dm index 4fface95d1..469f27f27e 100644 --- a/code/game/objects/structures/ghost_pods/event_vr.dm +++ b/code/game/objects/structures/ghost_pods/event_vr.dm @@ -38,7 +38,7 @@ break if(choice) - finalized = alert(M, "Are you sure you want to play as [choice]?","Confirmation","No","Yes") + finalized = alert(M, "Are you sure you want to play as [choice]? By clicking yes you should expect to be treated as vore predator and possibly killed. Do not attack other players. You will have minimal OOC pref protections.","Confirmation","No","Yes") if(randomize) choice = pick(possible_mobs) @@ -99,4 +99,4 @@ qdel(src) /obj/structure/ghost_pod/ghost_activated/morphspawn/no_announce - announce_prob = 0 \ No newline at end of file + announce_prob = 0 diff --git a/code/game/world.dm b/code/game/world.dm index 82a34a2526..867301f989 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -213,7 +213,7 @@ var/world_topic_spam_protect_time = world.timeofday var/isactive = (robot.client && robot.client.inactivity <= 10 MINUTES) ? "Active" : "Inactive" if(robot.shell) continue - if(robot.module && robot.module.hide_on_manifest) + if(robot.module && robot.module.hide_on_manifest()) continue if(!positions["bot"]) positions["bot"] = list() diff --git a/code/modules/client/preference_setup/loadout/loadout_uniform_yw.dm b/code/modules/client/preference_setup/loadout/loadout_uniform_yw.dm index b635994995..13497a5275 100644 --- a/code/modules/client/preference_setup/loadout/loadout_uniform_yw.dm +++ b/code/modules/client/preference_setup/loadout/loadout_uniform_yw.dm @@ -39,4 +39,4 @@ description = "A lightweight uniform intended for vehicle and powersuit operators, designed to allow free movement and maximum comfort in hot, cramped cockpits. Comes prefitted with a harness and webbing for gear." path = /obj/item/clothing/under/rank/khi/sec/pilot cost = 2 //base cost 1 + accessory 1 - allowed_roles = list("Security Pilot") \ No newline at end of file + allowed_roles = list("Pilot","Security Pilot") //CHOMPEDIT: Adding this to pilots as well diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index 9606205cc4..1b649ff8fe 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -44,6 +44,8 @@ var/glove_type = /obj/item/clothing/gloves/gauntlets/rig var/cell_type = /obj/item/weapon/cell/high var/air_type = /obj/item/weapon/tank/oxygen + var/unremovable_cell = FALSE //CHOMP Edit - an addition for protean living hardsuit. + //Component/device holders. var/obj/item/weapon/tank/air_supply // Air tank, if any. @@ -899,14 +901,19 @@ wearer.lay_down() to_chat(user, "\The [wearer] is now [wearer.resting ? "resting" : "getting up"].") -/obj/item/weapon/rig/proc/forced_move(var/direction, var/mob/user) +/obj/item/weapon/rig/proc/forced_move(var/direction, var/mob/user, var/ai_moving = TRUE) // Why is all this shit in client/Move()? Who knows? if(world.time < wearer_move_delay) return - if(!wearer || !wearer.loc || !ai_can_move_suit(user, check_user_module = 1)) + if(!wearer || !wearer.loc) //CHOMP Edit - Removed some stuff for protean living hardsuit return + +//CHOMP Addition - Added this for protean living hardsuit + if(ai_moving) + if(!ai_can_move_suit(user, check_user_module = 1)) + return //This is sota the goto stop mobs from moving var if(wearer.transforming || !wearer.canmove) @@ -965,7 +972,10 @@ wearer_move_delay += 2 return wearer.buckled.relaymove(wearer,direction) - cell.use(200) //Arbitrary, TODO + var/power_cost = 200 + if(!ai_moving) + power_cost = 20 + cell.use(power_cost) //Arbitrary, TODO wearer.Move(get_step(get_turf(wearer),direction),direction) // This returns the rig if you are contained inside one, but not if you are wearing it diff --git a/code/modules/clothing/spacesuits/rig/rig_attackby.dm b/code/modules/clothing/spacesuits/rig/rig_attackby.dm index 67080dd1e0..656f2d19da 100644 --- a/code/modules/clothing/spacesuits/rig/rig_attackby.dm +++ b/code/modules/clothing/spacesuits/rig/rig_attackby.dm @@ -136,7 +136,7 @@ if("cell") - if(cell) + if(cell && !unremovable_cell) //CHOMP Edit - addition for living protean hardsuit to_chat(user, "You detach \the [cell] from \the [src]'s battery mount.") for(var/obj/item/rig_module/module in installed_modules) module.deactivate() diff --git a/code/modules/clothing/spacesuits/rig/suits/alien_ch.dm b/code/modules/clothing/spacesuits/rig/suits/alien_ch.dm new file mode 100644 index 0000000000..06d5a566b4 --- /dev/null +++ b/code/modules/clothing/spacesuits/rig/suits/alien_ch.dm @@ -0,0 +1,213 @@ +/* + proteans +*/ +/obj/item/weapon/rig/protean + name = "nanosuit control cluster" + suit_type = "nanomachine" + icon = 'icons/obj/rig_modules_ch.dmi' + icon_state = "nanomachine_rig" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 90) + siemens_coefficient= 0.5 + slowdown = 0 + offline_slowdown = 0 + seal_delay = 1 + var/mob/living/carbon/human/myprotean + initial_modules = list(/obj/item/rig_module/power_sink) + + helm_type = /obj/item/clothing/head/helmet/space/rig/protean //These are important for sprite pointers + boot_type = /obj/item/clothing/shoes/magboots/rig/protean + chest_type = /obj/item/clothing/suit/space/rig/protean + glove_type = /obj/item/clothing/gloves/gauntlets/rig/protean + +//I doooon't think I can get rig_back.dmi as a _ch file. That is part of /obj/item/weapon/rig/update_icon(var/update_mob_icon). + +/obj/item/weapon/rig/protean/relaymove(mob/user, var/direction) + if(user.stat || user.stunned) + return + forced_move(direction, user, FALSE) + +/obj/item/clothing/head/helmet/space/rig/protean + name = "mass" + desc = "A helmet-shaped clump of nanomachines." + siemens_coefficient= 0 + light_overlay = "should not use a light overlay" + species_restricted = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_TAJ, SPECIES_UNATHI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_PROMETHEAN, SPECIES_XENOHYBRID, SPECIES_VOX, SPECIES_TESHARI, SPECIES_VASILISSAN) //CHOMPEDIT: adding more races to the proto rig + +/obj/item/clothing/gloves/gauntlets/rig/protean + name = "mass" + desc = "Glove-shaped clusters of nanomachines." + siemens_coefficient= 0 + species_restricted = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_TAJ, SPECIES_UNATHI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_PROMETHEAN, SPECIES_XENOHYBRID, SPECIES_VOX, SPECIES_TESHARI, SPECIES_VASILISSAN) //CHOMPEDIT: adding more races to the proto rig + +/obj/item/clothing/shoes/magboots/rig/protean + name = "mass" + desc = "Boot-shaped clusters of nanomachines." + siemens_coefficient= 0 + species_restricted = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_TAJ, SPECIES_UNATHI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_PROMETHEAN, SPECIES_XENOHYBRID, SPECIES_VOX, SPECIES_TESHARI, SPECIES_VASILISSAN) //CHOMPEDIT: adding more races to the proto rig + +/obj/item/clothing/suit/space/rig/protean + name = "mass" + desc = "A body-hugging mass of nanomachines." + siemens_coefficient= 0 + can_breach = 0 + species_restricted = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_TAJ, SPECIES_UNATHI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_PROMETHEAN, SPECIES_XENOHYBRID, SPECIES_VOX, SPECIES_TESHARI, SPECIES_VASILISSAN) + allowed = list( + /obj/item/weapon/gun, + /obj/item/device/flashlight, + /obj/item/weapon/tank, + /obj/item/device/suit_cooling_unit, + /obj/item/weapon/melee/baton, + /obj/item/weapon/storage/backpack, + ) //Subspace radio is in for the citadel version. IDK if we have that and I don't think we need it so I removed it from this list. + + + + +//Backend stuff to make the sprites work. Copied and pasted from rig_pieces_vr.dm, but added ch to everything. Only reason for this to be touched is to add or remove species. This might just need to go in a new file named rig_pieces_ch.dm. +/obj/item/clothing/head/helmet/space/rig/protean + sprite_sheets = list( + SPECIES_HUMAN = 'icons/mob/head_ch.dmi', + SPECIES_TAJ = 'icons/mob/species/tajaran/helmet_ch.dmi', + SPECIES_SKRELL = 'icons/mob/species/skrell/helmet_ch.dmi', + SPECIES_UNATHI = 'icons/mob/species/unathi/helmet_ch.dmi', + SPECIES_XENOHYBRID = 'icons/mob/species/unathi/helmet_ch.dmi', + SPECIES_AKULA = 'icons/mob/species/akula/helmet_ch.dmi', + SPECIES_SERGAL = 'icons/mob/species/sergal/helmet_ch.dmi', + SPECIES_NEVREAN = 'icons/mob/species/sergal/helmet_ch.dmi', + SPECIES_VULPKANIN = 'icons/mob/species/vulpkanin/helmet_ch.dmi', + SPECIES_ZORREN_HIGH = 'icons/mob/species/fox/helmet_ch.dmi', + SPECIES_FENNEC = 'icons/mob/species/vulpkanin/helmet_ch.dmi', + SPECIES_PROMETHEAN = 'icons/mob/species/skrell/helmet_ch.dmi', + SPECIES_TESHARI = 'icons/mob/species/seromi/head_ch.dmi', + SPECIES_VASILISSAN = 'icons/mob/species/skrell/helmet_ch.dmi', + SPECIES_VOX = 'icons/mob/species/vox/head_ch.dmi' + ) + + sprite_sheets_obj = list( + SPECIES_HUMAN = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_TAJ = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_SKRELL = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_UNATHI = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_XENOHYBRID = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_AKULA = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_SERGAL = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_NEVREAN = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_VULPKANIN = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_ZORREN_HIGH = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_FENNEC = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_PROMETHEAN = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_TESHARI = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_VASILISSAN = 'icons/obj/clothing/hats_ch.dmi', + SPECIES_VOX = 'icons/obj/clothing/hats_ch.dmi' + ) + +/obj/item/clothing/suit/space/rig/protean + sprite_sheets = list( + SPECIES_HUMAN = 'icons/mob/spacesuit_ch.dmi', + SPECIES_TAJ = 'icons/mob/species/tajaran/suit_ch.dmi', + SPECIES_SKRELL = 'icons/mob/species/skrell/suit_ch.dmi', + SPECIES_UNATHI = 'icons/mob/species/unathi/suit_ch.dmi', + SPECIES_XENOHYBRID = 'icons/mob/species/unathi/suit_ch.dmi', + SPECIES_AKULA = 'icons/mob/species/akula/suit_ch.dmi', + SPECIES_SERGAL = 'icons/mob/species/sergal/suit_ch.dmi', + SPECIES_NEVREAN = 'icons/mob/species/sergal/suit_ch.dmi', + SPECIES_VULPKANIN = 'icons/mob/species/vulpkanin/suit_ch.dmi', + SPECIES_ZORREN_HIGH = 'icons/mob/species/fox/suit_ch.dmi', + SPECIES_FENNEC = 'icons/mob/species/vulpkanin/suit_ch.dmi', + SPECIES_PROMETHEAN = 'icons/mob/species/skrell/suit_ch.dmi', + SPECIES_TESHARI = 'icons/mob/species/seromi/suit_ch.dmi', + SPECIES_VASILISSAN = 'icons/mob/species/skrell/suit_ch.dmi', + SPECIES_VOX = 'icons/mob/species/vox/suit_ch.dmi' + ) + + sprite_sheets_obj = list( + SPECIES_HUMAN = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_TAJ = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_SKRELL = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_UNATHI = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_XENOHYBRID = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_AKULA = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_SERGAL = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_NEVREAN = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_VULPKANIN = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_ZORREN_HIGH = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_FENNEC = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_PROMETHEAN = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_TESHARI = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_VASILISSAN = 'icons/obj/clothing/spacesuits_ch.dmi', + SPECIES_VOX = 'icons/obj/clothing/spacesuits_ch.dmi' + ) + +/obj/item/clothing/gloves/gauntlets/rig/protean + sprite_sheets = list( + SPECIES_HUMAN = 'icons/mob/hands_ch.dmi', + SPECIES_TAJ = 'icons/mob/hands_ch.dmi', + SPECIES_SKRELL = 'icons/mob/hands_ch.dmi', + SPECIES_UNATHI = 'icons/mob/hands_ch.dmi', + SPECIES_XENOHYBRID = 'icons/mob/hands_ch.dmi', + SPECIES_AKULA = 'icons/mob/hands_ch.dmi', + SPECIES_SERGAL = 'icons/mob/hands_ch.dmi', + SPECIES_NEVREAN = 'icons/mob/hands_ch.dmi', + SPECIES_VULPKANIN = 'icons/mob/hands_ch.dmi', + SPECIES_ZORREN_HIGH = 'icons/mob/hands_ch.dmi', + SPECIES_FENNEC = 'icons/mob/hands_ch.dmi', + SPECIES_PROMETHEAN = 'icons/mob/hands_ch.dmi', + SPECIES_TESHARI = 'icons/mob/hands_ch.dmi', + SPECIES_VASILISSAN = 'icons/mob/hands_ch.dmi', + SPECIES_VOX = 'icons/mob/species/vox/gloves_ch.dmi' + ) + + sprite_sheets_obj = list( + SPECIES_HUMAN = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_TAJ = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_SKRELL = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_UNATHI = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_XENOHYBRID = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_AKULA = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_SERGAL = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_NEVREAN = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_VULPKANIN = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_ZORREN_HIGH = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_FENNEC = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_PROMETHEAN = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_TESHARI = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_VASILISSAN = 'icons/obj/clothing/gloves_ch.dmi', + SPECIES_VOX = 'icons/obj/clothing/gloves_ch.dmi' + ) + +/obj/item/clothing/shoes/magboots/rig/protean + sprite_sheets = list( + SPECIES_HUMAN = 'icons/mob/feet_ch.dmi', + SPECIES_TAJ = 'icons/mob/feet_ch.dmi', + SPECIES_SKRELL = 'icons/mob/feet_ch.dmi', + SPECIES_UNATHI = 'icons/mob/feet_ch.dmi', + SPECIES_XENOHYBRID = 'icons/mob/feet_ch.dmi', + SPECIES_AKULA = 'icons/mob/feet_ch.dmi', + SPECIES_SERGAL = 'icons/mob/feet_ch.dmi', + SPECIES_NEVREAN = 'icons/mob/feet_ch.dmi', + SPECIES_VULPKANIN = 'icons/mob/feet_ch.dmi', + SPECIES_ZORREN_HIGH = 'icons/mob/feet_ch.dmi', + SPECIES_FENNEC = 'icons/mob/feet_ch.dmi', + SPECIES_PROMETHEAN = 'icons/mob/feet_ch.dmi', + SPECIES_TESHARI = 'icons/mob/feet_ch.dmi', + SPECIES_VASILISSAN = 'icons/mob/feet_ch.dmi', + SPECIES_VOX = 'icons/mob/species/vox/shoes_ch.dmi' + ) + + sprite_sheets_obj = list( + SPECIES_HUMAN = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_TAJ = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_SKRELL = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_UNATHI = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_XENOHYBRID = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_AKULA = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_SERGAL = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_NEVREAN = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_VULPKANIN = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_ZORREN_HIGH = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_FENNEC = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_PROMETHEAN = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_TESHARI = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_VASILISSAN = 'icons/obj/clothing/shoes_ch.dmi', + SPECIES_VOX = 'icons/obj/clothing/shoes_ch.dmi' + ) diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 5f8746ff8b..0031a6c55b 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -108,6 +108,7 @@ icon = 'icons/obj/clothing/spacesuits.dmi' icon_override = "icons/mob/spacesuit.dmi" //Chomp edit to fix its missing icon icon_state = "syndicate" + default_worn_icon = 'icons/mob/spacesuit.dmi' desc = "A plastic replica of the syndicate space suit, you'll look just like a real murderous syndicate agent in this! This is a toy, it is not made for use in space!" w_class = ITEMSIZE_NORMAL allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency/oxygen,/obj/item/toy) diff --git a/code/modules/clothing/under/accessories/permits.dm b/code/modules/clothing/under/accessories/permits.dm index d7a5c3f396..c89d9ee019 100644 --- a/code/modules/clothing/under/accessories/permits.dm +++ b/code/modules/clothing/under/accessories/permits.dm @@ -3,8 +3,8 @@ /obj/item/clothing/accessory/permit name = "permit" desc = "A permit for something." - icon = 'icons/obj/card.dmi' - icon_state = "permit" + icon = 'icons/obj/card_new.dmi' + icon_state = "permit-generic" w_class = ITEMSIZE_TINY slot = ACCESSORY_SLOT_MEDAL var/owner = 0 //To prevent people from just renaming the thing if they steal it @@ -30,6 +30,7 @@ /obj/item/clothing/accessory/permit/gun name = "weapon permit" desc = "A card indicating that the owner is allowed to carry a firearm." + icon_state = "permit-security" /obj/item/clothing/accessory/permit/gun/bar name = "bar shotgun permit" @@ -38,8 +39,9 @@ /obj/item/clothing/accessory/permit/gun/planetside name = "planetside gun permit" desc = "A card indicating that the owner is allowed to carry a firearm while on the surface." + icon_state = "permit-science" /obj/item/clothing/accessory/permit/drone name = "drone identification card" desc = "A card issued by the EIO, indicating that the owner is a Drone Intelligence. Drones are mandated to carry this card within SolGov space, by law." - icon_state = "permit_drone" \ No newline at end of file + icon_state = "permit-drone" \ No newline at end of file diff --git a/code/modules/mining/ore_datum.dm b/code/modules/mining/ore_datum.dm index 1ac742f211..0e125bee74 100644 --- a/code/modules/mining/ore_datum.dm +++ b/code/modules/mining/ore_datum.dm @@ -224,6 +224,7 @@ var/global/list/ore_data = list() smelts_to = "titanium" result_amount = 5 spread_chance = 12 + alloy = 1 ore = /obj/item/weapon/ore/rutile scan_icon = "mineral_uncommon" diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 629237fa2b..f914f9a760 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -121,7 +121,7 @@ // Unclear why this isn't being grabbed by appearance. if(ishuman(body)) var/mob/living/carbon/human/H = body - overlays = H.overlays_standing + add_overlay(H.overlays_standing) if(!T) T = pick(latejoin) //Safety in case we cannot find the body's position forceMove(T) @@ -915,4 +915,4 @@ mob/observer/dead/MayRespawn(var/feedback = 0) /mob/observer/dead/verb/respawn() set name = "Respawn" set category = "Ghost" - src.abandon_mob() \ No newline at end of file + src.abandon_mob() diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 376a1fafa7..35df5ef8a1 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -244,11 +244,10 @@ var/list/slot_equipment_priority = list( \ if(hasvar(src,"wear_id")) if(src:wear_id) items += src:wear_id if(hasvar(src,"wear_mask")) if(src:wear_mask) items += src:wear_mask if(hasvar(src,"wear_suit")) if(src:wear_suit) items += src:wear_suit -// if(hasvar(src,"w_radio")) if(src:w_radio) items += src:w_radio commenting this out since headsets go on your ears now PLEASE DON'T BE MAD KEELIN if(hasvar(src,"w_uniform")) if(src:w_uniform) items += src:w_uniform - //if(hasvar(src,"l_hand")) if(src:l_hand) items += src:l_hand - //if(hasvar(src,"r_hand")) if(src:r_hand) items += src:r_hand + if(hasvar(src,"l_hand")) if(src:l_hand) items += src:l_hand + if(hasvar(src,"r_hand")) if(src:r_hand) items += src:r_hand return items diff --git a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm index 253f3d2f59..c15b14686b 100644 --- a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm +++ b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_blob.dm @@ -17,13 +17,13 @@ // ai_inactive = TRUE //Always off //VORESTATION AI TEMPORARY REMOVAL show_stat_health = FALSE //We will do it ourselves - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "hits" + response_help = "pets the" //CHOMP Edit + response_disarm = "gently pushes aside the " //CHOMP Edit + response_harm = "hits the" //CHOMP Edit - harm_intent_damage = 2 - melee_damage_lower = 10 - melee_damage_upper = 10 + harm_intent_damage = 3 + melee_damage_lower = 5 //CHOMP Edit + melee_damage_upper = 5 //CHOMP Edit attacktext = list("slashed") min_oxy = 0 @@ -36,7 +36,7 @@ max_n2 = 0 minbodytemp = 0 maxbodytemp = 900 - movement_cooldown = 3 + movement_cooldown = 2 //CHOMP Edit var/mob/living/carbon/human/humanform var/obj/item/organ/internal/nano/refactory/refactory @@ -48,7 +48,7 @@ var/human_brute = 0 var/human_burn = 0 - player_msg = "In this form, you can move a little faster, your health will regenerate as long as you have metal in you, and you can ventcrawl!" + player_msg = "In this form, your health will regenerate as long as you have metal in you." //CHOMP Edit removed ventcrawl can_buckle = TRUE //Blobsurfing @@ -64,8 +64,10 @@ humanform = H updatehealth() refactory = locate() in humanform.internal_organs - verbs |= /mob/living/proc/ventcrawl +// verbs |= /mob/living/proc/ventcrawl //CHOMP Removal verbs |= /mob/living/proc/hide + verbs |= /mob/living/simple_mob/protean_blob/proc/rig_transform //CHOMP Addition + verbs |= /mob/living/proc/usehardsuit //CHOMP Addition else update_icon() @@ -267,14 +269,31 @@ if(refactory && istype(A,/obj/item/stack/material)) var/obj/item/stack/material/S = A var/substance = S.material.name - var/list/edible_materials = list("steel", "plasteel", "diamond", "mhydrogen") //Can't eat all materials, just useful ones. - var allowed = FALSE + var/list/edible_materials = list(MAT_STEEL) //Can't eat all materials, just useful ones. + var/allowed = FALSE //CHOMP Edit for(var/material in edible_materials) - if(material == substance) allowed = TRUE + if(material == substance) + allowed = TRUE if(!allowed) return if(refactory.add_stored_material(S.material.name,1*S.perunit) && S.use(1)) visible_message("[name] gloms over some of \the [S], absorbing it.") + else if(isitem(A) && a_intent == "grab") //CHOMP Add all this block, down to I.forceMove. + var/obj/item/I = A + if(!vore_selected) + to_chat(src,"You either don't have a belly selected, or don't have a belly!") + return FALSE + if(is_type_in_list(I,item_vore_blacklist) || I.anchored) + to_chat(src, "You can't eat this.") + return + + if(is_type_in_list(I,edible_trash) | adminbus_trash) + if(I.hidden_uplink) + to_chat(src, "You really should not be eating this.") + message_admins("[key_name(src)] has attempted to ingest an uplink item. ([src ? "JMP" : "null"])") + return + visible_message("[name] stretches itself over the [I], engulfing it whole!") + I.forceMove(vore_selected) else return ..() @@ -283,7 +302,7 @@ var/obj/item/stack/material/S = O var/substance = S.material.name var/list/edible_materials = list("steel", "plasteel", "diamond", "mhydrogen") //Can't eat all materials, just useful ones. - var allowed = FALSE + var/allowed = FALSE //CHOMP Edit for(var/material in edible_materials) if(material == substance) allowed = TRUE if(!allowed) @@ -292,7 +311,20 @@ visible_message("[name] gloms over some of \the [S], absorbing it.") else return ..() - + +/mob/living/simple_mob/protean_blob/attack_hand(mob/living/L) //CHOMP Add this whole block. + if(L.get_effective_size() >= (src.get_effective_size() + 0.5) ) + src.get_scooped(L) + else + ..() + +/mob/living/simple_mob/protean_blob/MouseDrop(var/atom/over_object) //CHOMP Add this whole block. + if(ishuman(over_object) && usr == src && src.Adjacent(over_object)) + var/mob/living/carbon/human/H = over_object + get_scooped(H, TRUE) + else + return ..() + /mob/living/simple_mob/protean_blob/MouseEntered(location,control,params) if(resting) return @@ -306,6 +338,8 @@ var/global/list/disallowed_protean_accessories = list( // Helpers - Unsafe, WILL perform change. /mob/living/carbon/human/proc/nano_intoblob() + if(loc == /obj/item/weapon/rig/protean) + return var/panel_was_up = FALSE if(client?.statpanel == "Protean") panel_was_up = TRUE @@ -341,6 +375,8 @@ var/global/list/disallowed_protean_accessories = list( things_to_drop -= things_to_not_drop //Crunch the lists things_to_drop -= organs //Mah armbs things_to_drop -= internal_organs //Mah sqeedily spooch + for(var/obj/item/weapon/rig/protean/O in things_to_drop) //CHOMP Add + things_to_drop -= O //CHOMP Add for(var/obj/item/I in things_to_drop) //rip hoarders drop_from_inventory(I) @@ -397,10 +433,44 @@ var/global/list/disallowed_protean_accessories = list( remove_micros(I, root) //Recursion. I'm honestly depending on there being no containment loop, but at the cost of performance that can be fixed too. if(istype(I, /obj/item/weapon/holder)) root.remove_from_mob(I) + +//CHOMP Add start +/mob/living/simple_mob/protean_blob/proc/rig_transform() //CHOMP Add this whole block. + set name = "Modify Form - Hardsuit" + set desc = "Allows a protean blob to solidify its form into one extremely similar to a hardsuit." + set category = "Abilities" + + if(istype(loc, /obj/item/weapon/rig/protean)) + var/obj/item/weapon/rig/protean/prig = loc + src.forceMove(get_turf(prig)) + qdel(prig) + return + + if(isturf(loc)) + var/obj/item/weapon/rig/protean/prig = new(loc) + if(prig) + prig.forceMove(get_turf(src)) + src.forceMove(prig) + return + +/mob/living/proc/usehardsuit() + set name = "Utilize Hardsuit Interface" + set desc = "Allows a protean blob to open hardsuit interface." + set category = "Abilities" + + if(istype(loc, /obj/item/weapon/rig/protean)) + var/obj/item/weapon/rig/protean/prig = loc + to_chat(src, "You attempt to interface with the [prig].") + prig.ui_interact(src, nano_state = interactive_state) + else + to_chat(src, "You are not in RIG form.") +//CHOMP Add end /mob/living/carbon/human/proc/nano_outofblob(var/mob/living/simple_mob/protean_blob/blob) if(!istype(blob)) return + if(blob.loc == /obj/item/weapon/rig/protean) + return var/panel_was_up = FALSE if(client?.statpanel == "Protean") diff --git a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_powers.dm b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_powers.dm index 8a84a15331..0580096bc7 100644 --- a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_powers.dm +++ b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_powers.dm @@ -1,3 +1,4 @@ +//TODO: Replace ventcrawl with morphing. /mob/living/simple_mob/vore/hostile/morph #define PER_LIMB_STEEL_COST SHEET_MATERIAL_AMOUNT //// // One-part Refactor @@ -18,7 +19,6 @@ to_chat(src,"You don't have a working refactory module!") return - var/choice = input(src,"Pick the bodypart to change:", "Refactor - One Bodypart") as null|anything in species.has_limbs if(!choice) return @@ -81,12 +81,108 @@ //// // Full Refactor //// +/* +/mob/living/carbon/human/proc/nano_regenerate() + set name = "Regenerate" + set desc = "Allows you to regrow limbs and replace organs." + set category = "Abilities" + set hidden = TRUE + + if(nutrition < 250) + to_chat(src, "You lack the energy to begin regeneration!") + return + + if(active_regen) + to_chat(src, "You are already regenerating!") + return + else + active_regen = TRUE + src.visible_message("[src]'s nanites begin to regenerate...") + + + var/mob/living/simple_mob/protean_blob/blob = nano_intoblob() + var/delay_length = round(active_regen_delay * species.active_regen_mult) + if(do_after(blob, delay_length, null, 0)) + if(stat != DEAD) + adjust_nutrition(-200) + species.create_organs(src) + var/obj/item/organ/external/torso = organs_by_name[BP_TORSO] + torso.robotize() //synthetic wasn't defined here. + LAZYCLEARLIST(blood_DNA) + LAZYCLEARLIST(feet_blood_DNA) + blood_color = null + feet_blood_color = null + regenerate_icons() //Probably worth it, yeah. + to_chat(src, "Your regeneration is complete.") //Guarantees the message shows no matter how bad the timing. + to_chat(blob, "Your regeneration is complete!") + else + to_chat(src, "Your regeneration has failed.") + to_chat(blob, "Your regeneration has failed!") + else + to_chat(src, "Your regeneration is interrupted.") + to_chat(blob, "Your regeneration is interrupted!") + active_regen = FALSE + nano_outofblob(blob) + + + + var/delay_length = round(active_regen_delay * species.active_regen_mult) + if(do_after(src,delay_length)) + adjust_nutrition(-200) + + for(var/obj/item/organ/I in internal_organs) + if(I.robotic >= ORGAN_ROBOT) // No free robofix. + continue + if(I.damage > 0) + I.damage = max(I.damage - 30, 0) //Repair functionally half of a dead internal organ. + I.status = 0 // Wipe status, as it's being regenerated from possibly dead. + to_chat(src, "You feel a soothing sensation within your [I.name]...") + + // Replace completely missing limbs. + for(var/limb_type in src.species.has_limbs) + var/obj/item/organ/external/E = src.organs_by_name[limb_type] + + if(E && E.disfigured) + E.disfigured = 0 + if(E && (E.is_stump() || (E.status & (ORGAN_DESTROYED|ORGAN_DEAD|ORGAN_MUTATED)))) + E.removed() + qdel(E) + E = null + if(!E) + var/list/organ_data = src.species.has_limbs[limb_type] + var/limb_path = organ_data["path"] + var/obj/item/organ/O = new limb_path(src) + organ_data["descriptor"] = O.name + to_chat(src, "You feel a slithering sensation as your [O.name] reform.") + + var/agony_to_apply = round(0.66 * O.max_damage) // 66% of the limb's health is converted into pain. + src.apply_damage(agony_to_apply, HALLOSS) + + for(var/organtype in species.has_organ) // Replace completely missing internal organs. -After- external ones, so they all should exist. + if(!src.internal_organs_by_name[organtype]) + var/organpath = species.has_organ[organtype] + var/obj/item/organ/Int = new organpath(src, TRUE) + + Int.rejuvenate(TRUE) + + handle_organs() // Update everything + + update_icons_body() + active_regen = FALSE + else + to_chat(src, "Your regeneration is interrupted!") + adjust_nutrition(-75) + active_regen = FALSE +*/ + /mob/living/carbon/human/proc/nano_regenerate() //fixed the proc, it used to leave active_regen true. set name = "Ref - Whole Body" set desc = "Allows you to regrow limbs and replace organs, given you have enough materials." set category = "Abilities" set hidden = TRUE + + if(stat) to_chat(src,"You must be awake and standing to perform this action!") return @@ -178,7 +274,6 @@ active_regen = FALSE nano_outofblob(blob) - //// // Storing metal //// @@ -223,7 +318,7 @@ visible_message("[src] devours some of the [substance] right off the stack!") else to_chat(src,"You're completely capped out on [substance]!") - + //// // Blob Form //// @@ -269,6 +364,7 @@ //// // Change size //// +/*CHOMP Removal start - I am replacing this with the OG set size. No more metal requirement. /mob/living/carbon/human/proc/nano_set_size() set name = "Adjust Volume" set category = "Abilities" @@ -312,6 +408,7 @@ to_chat(user,"Unfortunately, [cost-actually_added] steel was lost due to lack of storage space.") user.visible_message("Black mist swirls around [user] as they change size.") +CHOMP Removal end*/ /// /// /// A helper to reuse /mob/living/proc/nano_get_refactory(obj/item/organ/internal/nano/refactory/R) @@ -369,11 +466,13 @@ icon_state = "blob" to_call = /mob/living/carbon/human/proc/nano_blobform -/obj/effect/protean_ability/change_volume +/*CHOMP removal start - This doesn't do anything at all now. Normal resize proc is being used instead. +/obj/effect/protean_ability/change_volume //CHOMP Edit ability_name = "Change Volume" - desc = "Alter your size by consuming steel to produce additional nanites, or regain steel by reducing your size and reclaiming them." + desc = "Alter your size between 25% and 200%." //CHOMP Edit - Removed talk about requiring metal icon_state = "volume" to_call = /mob/living/carbon/human/proc/nano_set_size +CHOMP removal end*/ /obj/effect/protean_ability/reform_limb ability_name = "Ref - Single Limb" @@ -386,11 +485,11 @@ desc = "Rebuild your entire body into whatever design you want, assuming you have 10,000 metal." icon_state = "body" to_call = /mob/living/carbon/human/proc/nano_regenerate - + /obj/effect/protean_ability/metal_nom ability_name = "Ref - Store Metals" desc = "Store the metal you're holding. Your refactory can only store steel, and all other metals will be converted into nanites ASAP for various effects." icon_state = "metal" to_call = /mob/living/carbon/human/proc/nano_metalnom -#undef PER_LIMB_STEEL_COST +#undef PER_LIMB_STEEL_COST \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm index cc5fc9cd33..202ca5da07 100755 --- a/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm +++ b/code/modules/mob/living/carbon/human/species/station/protean_vr/protean_species.dm @@ -17,7 +17,7 @@ flags = NO_SCAN | NO_SLIP | NO_MINOR_CUT | NO_HALLUCINATION | NO_INFECT | NO_PAIN appearance_flags = HAS_SKIN_COLOR | HAS_EYE_COLOR | HAS_HAIR_COLOR | HAS_UNDERWEAR | HAS_LIPS - spawn_flags = SPECIES_IS_RESTRICTED //SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED | SPECIES_WHITELIST_SELECTABLE CHOMPedit: disabled probably forever + spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED | SPECIES_WHITELIST_SELECTABLE health_hud_intensity = 2 num_alternate_languages = 3 assisted_langs = list(LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) @@ -67,7 +67,7 @@ has_organ = list( O_BRAIN = /obj/item/organ/internal/mmi_holder/posibrain/nano, O_ORCH = /obj/item/organ/internal/nano/orchestrator, - O_FACT = /obj/item/organ/internal/nano/refactory + O_FACT = /obj/item/organ/internal/nano/refactory, ) has_limbs = list( BP_TORSO = list("path" = /obj/item/organ/external/chest/unbreakable/nano), @@ -91,8 +91,8 @@ /mob/living/carbon/human/proc/nano_regenerate, //These verbs are hidden so you can macro them, /mob/living/carbon/human/proc/nano_partswap, /mob/living/carbon/human/proc/nano_metalnom, - /mob/living/carbon/human/proc/nano_blobform, - /mob/living/carbon/human/proc/nano_set_size, + /mob/living/carbon/human/proc/nano_blobform, + /mob/living/proc/set_size, /mob/living/carbon/human/proc/nano_change_fitting, //These verbs are displayed normally, /mob/living/carbon/human/proc/shapeshifter_select_hair, /mob/living/carbon/human/proc/shapeshifter_select_hair_colors, @@ -101,9 +101,14 @@ /mob/living/carbon/human/proc/shapeshifter_select_gender, /mob/living/carbon/human/proc/shapeshifter_select_wings, /mob/living/carbon/human/proc/shapeshifter_select_tail, - /mob/living/carbon/human/proc/shapeshifter_select_ears - ) - + /mob/living/carbon/human/proc/shapeshifter_select_ears, + /mob/living/carbon/human/proc/succubus_drain, + /mob/living/carbon/human/proc/slime_feed, + /mob/living/carbon/human/proc/succubus_drain_finalize, + /mob/living/carbon/human/proc/succubus_drain_lethal, + /mob/living/proc/eat_trash + ) //CHOMP Edit - Added succ stuff that promies have too. Also changed nano_set_size to standard set_size so there is no metal cost. + var/global/list/abilities = list() var/monochromatic = FALSE //IGNORE ME @@ -135,8 +140,8 @@ /datum/species/protean/equip_survival_gear(var/mob/living/carbon/human/H) var/obj/item/stack/material/steel/metal_stack = new() - metal_stack.amount = 3 - + metal_stack.amount = 5 //CHOMP Edit + var/obj/item/clothing/accessory/permit/nanotech/permit = new() permit.set_name(H.real_name) @@ -155,6 +160,9 @@ new_nif.quick_implant(H) else H.nif.durability = rand(21,25) + + var/obj/item/weapon/rig/protean/prig = new /obj/item/weapon/rig/protean(H) + prig.myprotean = H /datum/species/protean/hug(var/mob/living/carbon/human/H, var/mob/living/target) return ..() //Wut @@ -174,7 +182,7 @@ H.ckey = H.temporary_form.ckey QDEL_NULL(H.temporary_form) - to_chat(H, "You died as a Protean. Please sit out of the round for at least 60 minutes before respawning, to represent the time it would take to ship a new-you to the station.") + to_chat(H, "You died as a Protean. Please sit out of the round for at least 5 or 10 minutes before respawning, to represent the time it would take to ship a new-you to the station, depending on how you died.") for(var/obj/item/organ/I in H.internal_organs) I.removed() @@ -189,6 +197,7 @@ H.nano_intoblob() return ..() //Any instakill shot runtimes since there are no organs after this. No point to not skip these checks, going to nullspace anyway. +/*CHOMP Station removal start var/obj/item/organ/internal/nano/refactory/refactory = locate() in H.internal_organs if(refactory && !(refactory.status & ORGAN_DEAD)) @@ -209,6 +218,7 @@ H.add_modifier(/datum/modifier/protean/silver, origin = refactory) return ..() +CHOMP Station removal end*/ /datum/species/protean/get_additional_examine_text(var/mob/living/carbon/human/H) return ..() //Hmm, what could be done here? @@ -230,7 +240,7 @@ for(var/ability in abilities) var/obj/effect/protean_ability/A = ability stat("[A.ability_name]",A.atom_button_text()) - + // Various modifiers /datum/modifier/protean stacks = MODIFIER_STACK_FORBID @@ -261,6 +271,7 @@ if(!refactory.use_stored_material(material_name,material_use)) expire() +/*CHOMP Removal start /datum/modifier/protean/mhydrogen name = "Protean Effect - M.Hydrogen" desc = "You're affected by the presence of metallic hydrogen." @@ -305,6 +316,7 @@ accuracy = 30 evasion = 30 +CHOMP Removal end*/ /datum/modifier/protean/steel name = "Protean Effect - Steel" @@ -328,6 +340,7 @@ else if(O.status & ORGAN_DEAD) O.status &= ~ORGAN_DEAD //Unset dead if we repaired it entirely + // PAN Card /obj/item/clothing/accessory/permit/nanotech name = "\improper P.A.N. card" @@ -349,6 +362,28 @@ . = ..() . += validstring . += registring + +//CHOMP Add start +/mob/living/carbon/human/proc/rig_transform() + set name = "Modify Form - Hardsuit" + set desc = "Allows a protean to solidify its form into one extremely similar to a hardsuit." + set category = "Abilities" + if(istype(loc, /obj/item/weapon/rig/protean)) + var/obj/item/weapon/rig/protean/prig = loc + src.forceMove(get_turf(prig)) + prig.forceMove(src) + return + + if(isturf(loc)) + var/obj/item/weapon/rig/protean/prig + for(var/obj/item/weapon/rig/protean/O in contents) + prig = O + break + if(prig) + prig.forceMove(get_turf(src)) + src.forceMove(prig) + return +//CHOMP Add end #undef DAM_SCALE_FACTOR #undef METAL_PER_TICK \ No newline at end of file diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index af5c5eedae..5ee09212f4 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -632,6 +632,12 @@ process_resist() /mob/living/proc/process_resist() + + if(istype(src.loc, /mob/living/silicon/robot/platform)) + var/mob/living/silicon/robot/platform/R = src.loc + R.drop_stored_atom(src, src) + return TRUE + //unbuckling yourself if(buckled) resist_buckle() diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm index 882a7d934b..2b626b1ce7 100644 --- a/code/modules/mob/living/silicon/robot/component.dm +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -77,6 +77,10 @@ external_type = /obj/item/robot_parts/robot_component/armour max_damage = 90 +/datum/robot_component/armour/platform + name = "platform armour plating" + external_type = /obj/item/robot_parts/robot_component/armour_platform + max_damage = 140 // ACTUATOR // Enables movement. @@ -243,6 +247,12 @@ icon_state = "armor" icon_state_broken = "armor_broken" +/obj/item/robot_parts/robot_component/armour_platform + name = "platform armour plating" + icon_state = "armor" + icon_state_broken = "armor_broken" + color = COLOR_GRAY80 + /obj/item/robot_parts/robot_component/camera name = "camera" icon_state = "camera" @@ -256,4 +266,4 @@ /obj/item/robot_parts/robot_component/radio name = "radio" icon_state = "radio" - icon_state_broken = "radio_broken" \ No newline at end of file + icon_state_broken = "radio_broken" diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 6db31e60da..a34d2f65e7 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -158,7 +158,6 @@ if(A?.no_spoilers) disable_spoiler_vision() - if (src.stat == DEAD || (XRAY in mutations) || (src.sight_mode & BORGXRAY)) src.sight |= SEE_TURFS src.sight |= SEE_MOBS @@ -201,8 +200,10 @@ src.see_invisible = SEE_INVISIBLE_LIVING // This is normal vision (25), setting it lower for normal vision means you don't "see" things like darkness since darkness // has a "invisible" value of 15 - plane_holder.set_vis(VIS_FULLBRIGHT,fullbright) - plane_holder.set_vis(VIS_MESONS,seemeson) + if(plane_holder) + plane_holder.set_vis(VIS_FULLBRIGHT,fullbright) + plane_holder.set_vis(VIS_MESONS,seemeson) + ..() if (src.healths) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index a26a4bfd1e..1376c15072 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -98,7 +98,7 @@ /mob/living/silicon/robot/proc/robot_checklaws ) -/mob/living/silicon/robot/New(loc,var/unfinished = 0) +/mob/living/silicon/robot/New(loc, var/unfinished = 0) spark_system = new /datum/effect/effect/system/spark_spread() spark_system.set_up(5, 0, src) spark_system.attach(src) @@ -114,7 +114,7 @@ ident = rand(1, 999) module_sprites["Basic"] = "robot" icontype = "Basic" - updatename("Default") + updatename(modtype) updateicon() radio = new /obj/item/device/radio/borg(src) @@ -142,6 +142,8 @@ cell = new /obj/item/weapon/cell(src) cell.maxcharge = 7500 cell.charge = 7500 + else if(ispath(cell)) + cell = new cell(src) ..() @@ -287,10 +289,7 @@ updatename() notify_ai(ROBOT_NOTIFICATION_NEW_MODULE, module.name) -/mob/living/silicon/robot/proc/updatename(var/prefix as text) - if(prefix) - modtype = prefix - +/mob/living/silicon/robot/proc/update_braintype() if(istype(mmi, /obj/item/device/mmi/digital/posibrain)) braintype = BORG_BRAINTYPE_POSI else if(istype(mmi, /obj/item/device/mmi/digital/robot)) @@ -300,6 +299,11 @@ else braintype = BORG_BRAINTYPE_CYBORG +/mob/living/silicon/robot/proc/updatename(var/prefix as text) + if(prefix) + modtype = prefix + + update_braintype() var/changed_name = "" if(custom_name) @@ -1215,3 +1219,6 @@ if(current_selection_index) // Select what the player had before if possible. select_module(current_selection_index) + +/mob/living/silicon/robot/get_cell() + return cell diff --git a/code/modules/mob/living/silicon/robot/robot_modules/event.dm b/code/modules/mob/living/silicon/robot/robot_modules/event.dm index 3d3eb355df..107c9cff0a 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/event.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/event.dm @@ -3,7 +3,7 @@ // The module that borgs on the surface have. Generally has a lot of useful tools in exchange for questionable loyalty to the crew. /obj/item/weapon/robot_module/robot/lost name = "lost robot module" - hide_on_manifest = 1 + hide_on_manifest = TRUE sprites = list( "Drone" = "drone-lost" ) @@ -41,7 +41,7 @@ /obj/item/weapon/robot_module/robot/gravekeeper name = "gravekeeper robot module" - hide_on_manifest = 1 + hide_on_manifest = TRUE sprites = list( "Drone" = "drone-gravekeeper", "Sleek" = "sleek-gravekeeper" diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station.dm b/code/modules/mob/living/silicon/robot/robot_modules/station.dm index dfea127f01..66a2702ddf 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm @@ -18,7 +18,7 @@ var/global/list/robot_modules = list( icon_state = "std_module" w_class = ITEMSIZE_NO_CONTAINER item_state = "std_mod" - var/hide_on_manifest = 0 + var/hide_on_manifest = FALSE var/channels = list() var/networks = list() var/languages = list(LANGUAGE_SOL_COMMON = 1, LANGUAGE_TRADEBAND = 1, LANGUAGE_UNATHI = 0, LANGUAGE_SIIK = 0, LANGUAGE_AKHANI = 0, LANGUAGE_SKRELLIAN = 0, LANGUAGE_GUTTER = 0, LANGUAGE_SCHECHI = 0, LANGUAGE_SIGN = 0, LANGUAGE_TERMINUS = 1, LANGUAGE_ZADDAT = 0) @@ -37,6 +37,9 @@ var/global/list/robot_modules = list( var/list/original_languages = list() var/list/added_networks = list() +/obj/item/weapon/robot_module/proc/hide_on_manifest() + . = hide_on_manifest + /obj/item/weapon/robot_module/New(var/mob/living/silicon/robot/R) ..() R.module = src @@ -805,7 +808,7 @@ var/global/list/robot_modules = list( /obj/item/weapon/robot_module/robot/security/combat name = "combat robot module" - hide_on_manifest = 1 + hide_on_manifest = TRUE sprites = list( "Haruka" = "marinaCB", "Combat Android" = "droid-combat", @@ -828,7 +831,7 @@ var/global/list/robot_modules = list( /obj/item/weapon/robot_module/drone name = "drone module" - hide_on_manifest = 1 + hide_on_manifest = TRUE no_slip = 1 networks = list(NETWORK_ENGINEERING) @@ -912,7 +915,7 @@ var/global/list/robot_modules = list( /obj/item/weapon/robot_module/drone/construction name = "construction drone module" - hide_on_manifest = 1 + hide_on_manifest = TRUE channels = list("Engineering" = 1) languages = list() diff --git a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm index fe39040432..d8f7aa8a3a 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm @@ -2,7 +2,7 @@ /obj/item/weapon/robot_module/robot/syndicate name = "illegal robot module" - hide_on_manifest = 1 + hide_on_manifest = TRUE languages = list( LANGUAGE_SOL_COMMON = 1, LANGUAGE_TRADEBAND = 1, diff --git a/code/modules/mob/living/silicon/robot/subtypes/thinktank/_thinktank.dm b/code/modules/mob/living/silicon/robot/subtypes/thinktank/_thinktank.dm new file mode 100644 index 0000000000..f777fe7996 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/subtypes/thinktank/_thinktank.dm @@ -0,0 +1,168 @@ +// Spawner landmarks are used because platforms that are mapped during +// SSatoms init try to Initialize() twice. I have no idea why and I am +// not paid enough to spend more time trying to debug it. +/obj/effect/landmark/robot_platform + name = "recon platform spawner" + icon = 'icons/mob/screen1.dmi' + icon_state = "x3" + delete_me = TRUE + var/platform_type + +/obj/effect/landmark/robot_platform/Initialize() + if(platform_type) + new platform_type(get_turf(src)) + return ..() + +/mob/living/silicon/robot/platform + name = "support platform" + desc = "A large quadrupedal AI platform, colloquially known as a 'think-tank' due to the flexible onboard intelligence." + icon = 'icons/mob/robots_thinktank.dmi' + icon_state = "tachi" + color = "#68a2f2" + + cell = /obj/item/weapon/cell/mech + idcard_type = /obj/item/weapon/card/id/platform + module = /obj/item/weapon/robot_module/robot/platform + + lawupdate = FALSE + modtype = "Standard" + speak_statement = "chirps" + + mob_bump_flag = HEAVY + mob_swap_flags = ~HEAVY + mob_push_flags = HEAVY + mob_size = MOB_LARGE + + var/has_had_player = FALSE + var/const/platform_respawn_time = 3 MINUTES + + var/tmp/last_recharge_state = FALSE + var/tmp/recharge_complete = FALSE + var/tmp/recharger_charge_amount = 10 KILOWATTS + var/tmp/recharger_tick_cost = 80 KILOWATTS + var/weakref/recharging + + var/list/stored_atoms + var/max_stored_atoms = 1 + var/static/list/can_store_types = list( + /mob/living, + /obj/item, + /obj/structure, + /obj/machinery + ) + // Currently set to prevent tonks hauling a deliaminating SM into the middle of the station. + var/static/list/cannot_store_types = list( + /obj/machinery/power/supermatter + ) + +/mob/living/silicon/robot/platform/Login() + . = ..() + has_had_player = TRUE + +/mob/living/silicon/robot/platform/SetName(pickedName) + . = ..() + if(mind) + mind.name = real_name + +/mob/living/silicon/robot/platform/Initialize(var/mapload) + . = ..() + if(!mmi) + mmi = new /obj/item/device/mmi/digital/robot(src) + SetName("inactive [initial(name)]") + updateicon() + +// Copypasting from root proc to avoid calling ..() and accidentally creating duplicate armour etc. +/mob/living/silicon/robot/platform/initialize_components() + components["actuator"] = new /datum/robot_component/actuator(src) + components["radio"] = new /datum/robot_component/radio(src) + components["power cell"] = new /datum/robot_component/cell(src) + components["diagnosis unit"] = new /datum/robot_component/diagnosis_unit(src) + components["camera"] = new /datum/robot_component/camera(src) + components["comms"] = new /datum/robot_component/binary_communication(src) + components["armour"] = new /datum/robot_component/armour/platform(src) + +/mob/living/silicon/robot/platform/Destroy() + for(var/weakref/drop_ref in stored_atoms) + var/atom/movable/drop_atom = drop_ref.resolve() + if(istype(drop_atom) && !QDELETED(drop_atom) && drop_atom.loc == src) + drop_atom.dropInto(loc) + stored_atoms = null + if(recharging) + var/obj/item/recharging_atom = recharging.resolve() + if(istype(recharging_atom) && recharging_atom.loc == src) + recharging_atom.dropInto(loc) + recharging = null + . = ..() + +/mob/living/silicon/robot/platform/examine(mob/user, distance) + . = ..() + if(distance <= 3) + + if(recharging) + var/obj/item/weapon/cell/recharging_atom = recharging.resolve() + if(istype(recharging_atom) && !QDELETED(recharging_atom)) + . += "It has \a [recharging_atom] slotted into its recharging port." + . += "The cell readout shows [round(recharging_atom.percent(),1)]% charge." + else + . += "Its recharging port is empty." + else + . += "Its recharging port is empty." + + if(length(stored_atoms)) + var/list/atom_names = list() + for(var/weakref/stored_ref in stored_atoms) + var/atom/movable/AM = stored_ref.resolve() + if(istype(AM)) + atom_names += "\a [AM]" + if(length(atom_names)) + . += "It has [english_list(atom_names)] loaded into its transport bay." + else + . += "Its cargo bay is empty." + +/mob/living/silicon/robot/platform/update_braintype() + braintype = BORG_BRAINTYPE_PLATFORM + +/mob/living/silicon/robot/platform/init() + . = ..() + if(ispath(module, /obj/item/weapon/robot_module)) + module = new module(src) + +/mob/living/silicon/robot/platform/module_reset() + return FALSE + +/mob/living/silicon/robot/platform/use_power() + . = ..() + + if(stat != DEAD && cell) + + // TODO generalize solar occlusion to charge from the actual sun. + var/new_recharge_state = istype(loc, /turf/simulated/floor/outdoors) || /*, /turf/exterior) */ istype(loc, /turf/space) + if(new_recharge_state != last_recharge_state) + last_recharge_state = new_recharge_state + if(last_recharge_state) + to_chat(src, SPAN_NOTICE("Your integrated solar panels begin recharging your battery.")) + else + to_chat(src, SPAN_DANGER("Your integrated solar panels cease recharging your battery.")) + + if(last_recharge_state) + var/charge_amt = recharger_charge_amount * CELLRATE + cell.give(charge_amt) + used_power_this_tick -= (charge_amt) + module.respawn_consumable(src, (charge_amt / 250)) // magic number copied from borg charger. + + if(recharging) + + var/obj/item/weapon/cell/recharging_atom = recharging.resolve() + if(!istype(recharging_atom) || QDELETED(recharging_atom) || recharging_atom.loc != src) + recharging = null + return + + if(recharging_atom.percent() < 100) + var/charge_amount = recharger_tick_cost * CELLRATE + if(cell.check_charge(charge_amount * 1.5) && cell.checked_use(charge_amount)) // Don't kill ourselves recharging the battery. + recharging_atom.give(charge_amount) + used_power_this_tick += charge_amount + + if(!recharge_complete && recharging_atom.percent() >= 100) + recharge_complete = TRUE + visible_message(SPAN_NOTICE("\The [src] beeps and flashes a green light above \his recharging port.")) diff --git a/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_icon.dm b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_icon.dm new file mode 100644 index 0000000000..3a9882ff08 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_icon.dm @@ -0,0 +1,109 @@ +/mob/living/silicon/robot/platform/update_icon() + updateicon() + +/mob/living/silicon/robot/platform/updateicon() + + cut_overlays() + underlays.Cut() + var/obj/item/weapon/robot_module/robot/platform/tank_module = module + if(!istype(tank_module)) + icon = initial(icon) + icon_state = initial(icon_state) + color = initial(color) + return + + // This is necessary due to Polaris' liberal use of KEEP_TOGETHER and propensity for scaling transforms. + // If we just apply state/colour to the base icon, RESET_COLOR on the additional overlays is ignored. + icon = tank_module.user_icon + icon_state = "blank" + color = null + var/image/I = image(tank_module.user_icon, tank_module.user_icon_state) + I.color = tank_module.base_color + I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE) + underlays += I + + if(tank_module.armor_color) + I = image(icon, "[tank_module.user_icon_state]_armour") + I.color = tank_module.armor_color + I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE) + add_overlay(I) + + for(var/decal in tank_module.decals) + I = image(icon, "[tank_module.user_icon_state]_[decal]") + I.color = tank_module.decals[decal] + I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE) + add_overlay(I) + + if(tank_module.eye_color) + I = image(icon, "[tank_module.user_icon_state]_eyes") + I.color = tank_module.eye_color + I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE) + add_overlay(I) + + if(client && key && stat == CONSCIOUS && tank_module.pupil_color) + I = image(icon, "[tank_module.user_icon_state]_pupils") + I.color = tank_module.pupil_color + I.plane = PLANE_LIGHTING_ABOVE + I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE) + add_overlay(I) + + if(opened) + add_overlay("[tank_module.user_icon_state]-open") + if(wiresexposed) + I = image(icon, "[tank_module.user_icon_state]-wires") + else if(cell) + I = image(icon, "[tank_module.user_icon_state]-cell") + else + I = image(icon, "[tank_module.user_icon_state]-nowires") + I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE) + add_overlay(I) + +/mob/living/silicon/robot/platform/proc/try_paint(var/obj/item/device/floor_painter/painting, var/mob/user) + + var/obj/item/weapon/robot_module/robot/platform/tank_module = module + if(!istype(tank_module)) + to_chat(user, SPAN_WARNING("\The [src] is not paintable.")) + return FALSE + + var/list/options = list("Eyes", "Armour", "Body", "Clear Colors") + if(length(tank_module.available_decals)) + options += "Decal" + if(length(tank_module.decals)) + options += "Clear Decals" + for(var/option in options) + LAZYSET(options, option, new /image('icons/effects/thinktank_labels.dmi', option)) + + var/choice = show_radial_menu(user, painting, options, radius = 42, require_near = TRUE) + if(!choice || QDELETED(src) || QDELETED(painting) || QDELETED(user) || user.incapacitated() || tank_module.loc != src) + return FALSE + + if(choice == "Decal") + choice = null + options = list() + for(var/decal_name in tank_module.available_decals) + LAZYSET(options, decal_name, new /image('icons/effects/thinktank_labels.dmi', decal_name)) + choice = show_radial_menu(user, painting, options, radius = 42, require_near = TRUE) + if(!choice || QDELETED(src) || QDELETED(painting) || QDELETED(user) || user.incapacitated() || tank_module.loc != src) + return FALSE + + . = TRUE + switch(choice) + if("Eyes") + tank_module.eye_color = painting.paint_colour + if("Armour") + tank_module.armor_color = painting.paint_colour + if("Body") + tank_module.base_color = painting.paint_colour + if("Clear Colors") + tank_module.eye_color = initial(tank_module.eye_color) + tank_module.armor_color = initial(tank_module.armor_color) + tank_module.base_color = initial(tank_module.base_color) + if("Clear Decals") + tank_module.decals = null + else + if(choice in tank_module.available_decals) + LAZYSET(tank_module.decals, tank_module.available_decals[choice], painting.paint_colour) + else + . = FALSE + if(.) + updateicon() diff --git a/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_interactions.dm b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_interactions.dm new file mode 100644 index 0000000000..cfb7b2dd81 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_interactions.dm @@ -0,0 +1,77 @@ +/mob/living/silicon/robot/platform/attack_hand(mob/user) + + if(!opened) + if(recharging) + var/obj/item/recharging_atom = recharging.resolve() + if(istype(recharging_atom) && !QDELETED(recharging_atom) && recharging_atom.loc == src) + recharging_atom.dropInto(loc) + user.put_in_hands(recharging_atom) + user.visible_message(SPAN_NOTICE("\The [user] pops \the [recharging_atom] out of \the [src]'s recharging port.")) + recharging = null + return TRUE + + if(try_remove_cargo(user)) + return TRUE + + . = ..() + +/mob/living/silicon/robot/platform/attackby(obj/item/W, mob/user) + + if(istype(W, /obj/item/weapon/cell) && !opened) + if(recharging) + to_chat(user, SPAN_WARNING("\The [src] already has \a [recharging.resolve()] inserted into its recharging port.")) + else if(user.unEquip(W)) + W.forceMove(src) + recharging = weakref(W) + recharge_complete = FALSE + user.visible_message(SPAN_NOTICE("\The [user] slots \the [W] into \the [src]'s recharging port.")) + return TRUE + + if(istype(W, /obj/item/device/floor_painter)) + return FALSE // Paint sprayer wil call try_paint() in afterattack() + + . = ..() + +/mob/living/silicon/robot/platform/attack_ghost(mob/observer/ghost/user) + + if(client || key || stat == DEAD || !ticker || !ticker.mode) + return ..() + + var/confirm = alert("Do you wish to take control of \the [src]?", "Platform Control", "No", "Yes") + if(confirm != "Yes" || QDELETED(src) || client || key || stat == DEAD || !ticker || !ticker.mode) + return ..() + + if(jobban_isbanned(user, "Robot")) + to_chat(user, SPAN_WARNING("You are banned from synthetic roles and cannot take control of \the [src].")) + return + + // Boilerplate from drone fabs, unsure if there's a shared proc to use instead. + var/deathtime = world.time - user.timeofdeath + var/deathtimeminutes = round(deathtime / (1 MINUTE)) + var/pluralcheck = "" + if(deathtimeminutes == 1) + pluralcheck = "minute" + else if(deathtimeminutes > 0) + pluralcheck = " [deathtimeminutes] minute\s and" + var/deathtimeseconds = round((deathtime - deathtimeminutes * 1 MINUTE) / 10,1) + if (deathtime < platform_respawn_time) + to_chat(usr, "You have been dead for[pluralcheck] [deathtimeseconds] seconds.") + to_chat(usr, "You must wait [platform_respawn_time/600] minute\s to take control of \the [src]!") + return + // End boilerplate. + + if(user.mind) + user.mind.transfer_to(src) + if(key != user.key) + key = user.key + SetName("[modtype] [braintype]-[rand(100,999)]") + addtimer(CALLBACK(src, .proc/welcome_client), 1) + qdel(user) + +/mob/living/silicon/robot/platform/proc/welcome_client() + if(client) + to_chat(src, SPAN_NOTICE("You are a think-tank, a kind of flexible and adaptive drone intelligence installed into an armoured platform. Your programming compels you to be friendly and helpful wherever possible.")) + SetSleeping(0) + SetWeakened(0) + SetParalysis(0) + resting = FALSE diff --git a/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_module.dm b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_module.dm new file mode 100644 index 0000000000..2a8ffcb3e1 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_module.dm @@ -0,0 +1,102 @@ +/obj/item/weapon/robot_module/robot/platform + + hide_on_manifest = TRUE + + var/pupil_color = COLOR_CYAN + var/base_color = COLOR_WHITE + var/eye_color = COLOR_BEIGE + var/armor_color = "#68a2f2" + var/user_icon = 'icons/mob/robots_thinktank.dmi' + var/user_icon_state = "tachi" + + var/list/decals + var/list/available_decals = list( + "Stripe" = "stripe", + "Vertical Stripe" = "stripe_vertical" + ) + +// Only show on manifest if they have a player. +/obj/item/weapon/robot_module/robot/platform/hide_on_manifest() + if(isrobot(loc)) + var/mob/living/silicon/robot/R = loc + return !R.key + return ..() + +/obj/item/weapon/robot_module/robot/platform/verb/set_eye_colour() + set name = "Set Eye Colour" + set desc = "Select an eye colour to use." + set category = "Robot Commands" + set src in usr + + var/new_pupil_color = input(usr, "Select a pupil colour.", "Pupil Colour Selection") as color|null + if(usr.incapacitated() || QDELETED(usr) || QDELETED(src) || loc != usr) + return + + pupil_color = new_pupil_color || initial(pupil_color) + usr.update_icon() + +/obj/item/weapon/robot_module/robot/platform/explorer + armor_color = "#528052" + eye_color = "#7b7b46" + decals = list( + "stripe_vertical" = "#52b8b8", + "stripe" = "#52b8b8" + ) + channels = list( + "Science" = 1, + "Explorer" = 1 + ) + +/obj/item/weapon/robot_module/robot/platform/explorer/New() + ..() + modules += new /obj/item/weapon/tool/wrench/cyborg(src) + modules += new /obj/item/weapon/weldingtool/electric/mounted/cyborg(src) + modules += new /obj/item/weapon/tool/wirecutters/cyborg(src) + modules += new /obj/item/weapon/tool/screwdriver/cyborg(src) + modules += new /obj/item/weapon/pickaxe/plasmacutter(src) + modules += new /obj/item/weapon/material/knife/machete/cyborg(src) + + var/datum/matter_synth/medicine = new /datum/matter_synth/medicine(7500) + var/obj/item/stack/medical/bruise_pack/bandaid = new(src) + bandaid.uses_charge = 1 + bandaid.charge_costs = list(1000) + bandaid.synths = list(medicine) + modules += bandaid + synths += medicine + + var/obj/item/weapon/gun/energy/phasegun/mounted/cyborg/phasegun = new(src) + modules += phasegun + + emag = new /obj/item/weapon/chainsaw(src) + +/obj/item/weapon/robot_module/robot/platform/explorer/respawn_consumable(var/mob/living/silicon/robot/R, rate) + . = ..() + for(var/obj/item/weapon/gun/energy/pew in modules) + if(pew.power_supply && pew.power_supply.charge < pew.power_supply.maxcharge) + pew.power_supply.give(pew.charge_cost * rate) + pew.update_icon() + else + pew.charge_tick = 0 + +/obj/item/weapon/robot_module/robot/platform/cargo + armor_color = "#d5b222" + eye_color = "#686846" + decals = list( + "stripe_vertical" = "#bfbfa1", + "stripe" = "#bfbfa1" + ) + channels = list("Supply" = 1) + networks = list(NETWORK_MINE) + +/obj/item/weapon/robot_module/robot/platform/cargo/New() + ..() + modules += new /obj/item/weapon/packageWrap(src) + modules += new /obj/item/weapon/pen/multi(src) + modules += new /obj/item/device/destTagger(src) + emag = new /obj/item/weapon/stamp/denied + +/obj/item/weapon/robot_module/robot/platform/cargo/respawn_consumable(mob/living/silicon/robot/R, rate) + . = ..() + var/obj/item/weapon/packageWrap/wrapper = locate() in modules + if(wrapper.amount < initial(wrapper.amount)) + wrapper.amount++ diff --git a/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_storage.dm b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_storage.dm new file mode 100644 index 0000000000..ec6d6f4267 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_storage.dm @@ -0,0 +1,139 @@ +/mob/living/silicon/robot/platform/death(gibbed, deathmessage, show_dead_message) + + if(gibbed) + + if(recharging) + var/obj/item/recharging_atom = recharging.resolve() + if(istype(recharging_atom) && !QDELETED(recharging_atom) && recharging_atom.loc == src) + recharging_atom.dropInto(loc) + recharging_atom.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),30) + recharging = null + + if(length(stored_atoms)) + for(var/weakref/stored_ref in stored_atoms) + var/atom/movable/dropping = stored_ref.resolve() + if(istype(dropping) && !QDELETED(dropping) && dropping.loc == src) + dropping.dropInto(loc) + dropping.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),30) + stored_atoms = null + + . = ..() + +/mob/living/silicon/robot/platform/proc/can_store_atom(var/atom/movable/storing, var/mob/user) + + if(!istype(storing)) + var/storing_target = (user == src) ? "yourself" : "\the [src]" + to_chat(user, SPAN_WARNING("You cannot store that inside [storing_target].")) + return FALSE + + if(!isturf(storing.loc)) + return FALSE + + if(storing.anchored || !storing.simulated) + to_chat(user, SPAN_WARNING("\The [storing] won't budge!")) + return FALSE + + if(storing == src) + var/storing_target = (user == src) ? "yourself" : "\the [src]" + to_chat(user, SPAN_WARNING("You cannot store [storing_target] inside [storing_target]!")) + return FALSE + + if(length(stored_atoms) >= max_stored_atoms) + var/storing_target = (user == src) ? "Your" : "\The [src]'s" + to_chat(user, SPAN_WARNING("[storing_target] cargo compartment is full.")) + return FALSE + + if(ismob(storing)) + var/mob/M = storing + if(M.mob_size >= mob_size) + var/storing_target = (user == src) ? "your storage compartment" : "\the [src]" + to_chat(user, SPAN_WARNING("\The [storing] is too big for [storing_target].")) + return FALSE + + for(var/store_type in can_store_types) + if(istype(storing, store_type)) + . = TRUE + break + + if(.) + for(var/store_type in cannot_store_types) + if(istype(storing, store_type)) + . = FALSE + break + if(!.) + var/storing_target = (user == src) ? "yourself" : "\the [src]" + to_chat(user, SPAN_WARNING("You cannot store \the [storing] inside [storing_target].")) + +/mob/living/silicon/robot/platform/proc/store_atom(var/atom/movable/storing, var/mob/user) + if(istype(storing)) + storing.forceMove(src) + LAZYDISTINCTADD(stored_atoms, weakref(storing)) + +/mob/living/silicon/robot/platform/proc/drop_stored_atom(var/atom/movable/ejecting, var/mob/user) + + if(!ejecting && length(stored_atoms)) + var/weakref/stored_ref = stored_atoms[1] + if(!istype(stored_ref)) + LAZYREMOVE(stored_atoms, stored_ref) + else + ejecting = stored_ref?.resolve() + + LAZYREMOVE(stored_atoms, weakref(ejecting)) + if(istype(ejecting) && !QDELETED(ejecting) && ejecting.loc == src) + ejecting.dropInto(loc) + if(user == src) + visible_message(SPAN_NOTICE("\The [src] ejects \the [ejecting] from its cargo compartment.")) + else + user.visible_message(SPAN_NOTICE("\The [user] pulls \the [ejecting] from \the [src]'s cargo compartment.")) + +/mob/living/silicon/robot/platform/attack_ai(mob/user) + if(isrobot(user) && user.Adjacent(src)) + return try_remove_cargo(user) + return ..() + +/mob/living/silicon/robot/platform/proc/try_remove_cargo(var/mob/user) + if(!length(stored_atoms) || !istype(user)) + return FALSE + var/weakref/remove_ref = stored_atoms[length(stored_atoms)] + var/atom/movable/removing = remove_ref?.resolve() + if(!istype(removing) || QDELETED(removing) || removing.loc != src) + LAZYREMOVE(stored_atoms, remove_ref) + else + user.visible_message(SPAN_NOTICE("\The [user] begins unloading \the [removing] from \the [src]'s cargo compartment.")) + if(do_after(user, 3 SECONDS, src) && !QDELETED(removing) && removing.loc == src) + drop_stored_atom(removing, user) + return TRUE + +/mob/living/silicon/robot/platform/verb/drop_stored_atom_verb() + set name = "Eject Cargo" + set category = "Robot Commands" + set desc = "Drop something from your internal storage." + + if(incapacitated()) + to_chat(src, SPAN_WARNING("You are not in any state to do that.")) + return + + if(length(stored_atoms)) + drop_stored_atom(user = src) + else + to_chat(src, SPAN_WARNING("You have nothing in your cargo compartment.")) + +/mob/living/silicon/robot/platform/MouseDrop_T(atom/movable/dropping, mob/living/user) + if(!istype(user) || !istype(dropping) || user.incapacitated()) + return FALSE + if(!can_mouse_drop(dropping, user) || !can_store_atom(dropping, user)) + return FALSE + if(user == src) + visible_message(SPAN_NOTICE("\The [src] begins loading \the [dropping] into its cargo compartment.")) + else + user.visible_message(SPAN_NOTICE("\The [user] begins loading \the [dropping] into \the [src]'s cargo compartment.")) + if(do_after(user, 3 SECONDS, src) && can_mouse_drop(dropping, user) && can_store_atom(dropping, user)) + store_atom(dropping, user) + return FALSE + +/mob/living/silicon/robot/platform/proc/can_mouse_drop(var/atom/dropping, var/mob/user) + if(!istype(user) || !istype(dropping) || QDELETED(dropping) || QDELETED(user) || QDELETED(src)) + return FALSE + if(user.incapacitated() || !Adjacent(user) || !dropping.Adjacent(user)) + return FALSE + return TRUE \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_subtypes.dm b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_subtypes.dm new file mode 100644 index 0000000000..b3e48aabb4 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/subtypes/thinktank/thinktank_subtypes.dm @@ -0,0 +1,32 @@ +/mob/living/silicon/robot/platform/explorer + name = "recon platform" + desc = "A large quadrupedal AI platform, colloquially known as a 'think-tank' due to the flexible onboard intelligence. This one is lightly armoured and fitted with all-terrain wheels." + modtype = "Recon" + module = /obj/item/weapon/robot_module/robot/platform/explorer + +/mob/living/silicon/robot/platform/explorer/Initialize() + . = ..() + laws = new /datum/ai_laws/explorer + +/mob/living/silicon/robot/platform/explorer/welcome_client() + ..() + if(client) // ganbatte tachikoma-san + to_chat(src, SPAN_NOTICE("You are tasked with supporting the Exploration and Science staff as they unearth the secrets of the planet. Do your best!")) + +/obj/effect/landmark/robot_platform/explorer + platform_type = /mob/living/silicon/robot/platform/explorer + +/mob/living/silicon/robot/platform/cargo + name = "logistics platform" + desc = "A large quadrupedal AI platform, colloquially known as a 'think-tank' due to the flexible onboard intelligence. This one has an expanded storage compartment." + modtype = "Logistics" + module = /obj/item/weapon/robot_module/robot/platform/cargo + max_stored_atoms = 3 + +/mob/living/silicon/robot/platform/cargo/welcome_client() + ..() + if(client) + to_chat(src, SPAN_NOTICE("You are tasked with supporting the Cargo and Supply staff as they handle operational logistics. Do your best!")) + +/obj/effect/landmark/robot_platform/cargo + platform_type = /mob/living/silicon/robot/platform/cargo diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm index 7f65e4e510..bf4a770f54 100644 --- a/code/modules/mob/typing_indicator.dm +++ b/code/modules/mob/typing_indicator.dm @@ -1,18 +1,20 @@ /proc/generate_speech_bubble(var/bubble_loc, var/speech_state, var/set_layer = FLOAT_LAYER) var/image/I = image('icons/mob/talk_vr.dmi', bubble_loc, speech_state, set_layer) //VOREStation Edit - talk_vr.dmi instead of talk.dmi for right-side icons - I.appearance_flags |= (KEEP_APART|RESET_COLOR|PIXEL_SCALE) + I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE) //VOREStation Edit + /* //VOREStation Removal Start if(istype(bubble_loc, /atom/movable)) var/atom/movable/AM = bubble_loc var/x_scale = AM.get_icon_scale_x() if(abs(x_scale) < 2) // reset transform on bubbles, except for the Very Large I.pixel_z = (AM.icon_expected_height * (x_scale-1)) I.appearance_flags |= RESET_TRANSFORM + */ //VOREStation Removal Start return I /mob/proc/init_typing_indicator(var/set_state = "typing") typing_indicator = new typing_indicator.appearance = generate_speech_bubble(null, set_state) - typing_indicator.appearance_flags |= (KEEP_APART|RESET_COLOR|RESET_TRANSFORM|PIXEL_SCALE) + typing_indicator.appearance_flags |= (RESET_COLOR|PIXEL_SCALE) //VOREStation Edit /mob/proc/set_typing_indicator(var/state) //Leaving this here for mobs. @@ -43,7 +45,7 @@ set_typing_indicator(TRUE) var/message = input("","say (text)") as text set_typing_indicator(FALSE) - + if(message) say_verb(message) diff --git a/code/modules/multiz/turf.dm b/code/modules/multiz/turf.dm index d09dc346e7..f34cae0065 100644 --- a/code/modules/multiz/turf.dm +++ b/code/modules/multiz/turf.dm @@ -39,7 +39,7 @@ ..() update() -/turf/simulated/open/ChangeTurf() +/turf/simulated/open/ChangeTurf(var/turf/N, var/tell_universe, var/force_lighting_update, var/preserve_outdoors) var/turf/T = GetBelow(src) if(T) GLOB.turf_entered_event.unregister(T, src, .proc/BelowOpenUpdated) diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm index 1a793ab234..a3c79c4c40 100644 --- a/code/modules/organs/subtypes/standard.dm +++ b/code/modules/organs/subtypes/standard.dm @@ -334,7 +334,7 @@ if(!iscarbon(owner) || !owner.species) return - var/icon/eyecon + var/icon/eyecon //VOREStation Add //Eye color/icon var/should_have_eyes = owner.should_have_organ(O_EYES) diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm index 9182a17530..1b2624c125 100644 --- a/code/modules/paperwork/handlabeler.dm +++ b/code/modules/paperwork/handlabeler.dm @@ -21,50 +21,63 @@ return // don't set a label if(!labels_left) - to_chat(user, "No labels left.") + to_chat(user, SPAN_WARNING("\The [src] has no labels left.")) return if(!label || !length(label)) - to_chat(user, "No text set.") + to_chat(user, SPAN_WARNING("\The [src] has no label text set.")) return if(length(A.name) + length(label) > 64) - to_chat(user, "Label too big.") + to_chat(user, SPAN_WARNING("\The [src]'s label too big.")) + return + if(istype(A, /mob/living/silicon/robot/platform)) + var/mob/living/silicon/robot/platform/P = A + if(!P.allowed(user)) + to_chat(usr, SPAN_WARNING("Access denied.")) + else if(P.client || P.key) + to_chat(user, SPAN_NOTICE("You rename \the [P] to [label].")) + to_chat(P, SPAN_NOTICE("\The [user] renames you to [label].")) + P.custom_name = label + P.SetName(P.custom_name) + else + to_chat(user, SPAN_WARNING("\The [src] is inactive and cannot be renamed.")) return if(ishuman(A)) - to_chat(user, "The label refuses to stick to [A.name].") + to_chat(user, SPAN_WARNING("The label refuses to stick to [A.name].")) return if(issilicon(A)) - to_chat(user, "The label refuses to stick to [A.name].") + to_chat(user, SPAN_WARNING("The label refuses to stick to [A.name].")) return if(isobserver(A)) - to_chat(user, "[src] passes through [A.name].") + to_chat(user, SPAN_WARNING("[src] passes through [A.name].")) return if(istype(A, /obj/item/weapon/reagent_containers/glass)) - to_chat(user, "The label can't stick to the [A.name]. (Try using a pen)") + to_chat(user, SPAN_WARNING("The label can't stick to the [A.name] (Try using a pen).")) return if(istype(A, /obj/machinery/portable_atmospherics/hydroponics)) var/obj/machinery/portable_atmospherics/hydroponics/tray = A if(!tray.mechanical) - to_chat(user, "How are you going to label that?") + to_chat(user, SPAN_WARNING("How are you going to label that?")) return tray.labelled = label spawn(1) tray.update_icon() - user.visible_message("[user] labels [A] as [label].", \ - "You label [A] as [label].") + user.visible_message( \ + SPAN_NOTICE("\The [user] labels [A] as [label]."), \ + SPAN_NOTICE("You label [A] as [label].")) A.name = "[A.name] ([label])" /obj/item/weapon/hand_labeler/attack_self(mob/user as mob) mode = !mode icon_state = "labeler[mode]" if(mode) - to_chat(user, "You turn on \the [src].") + to_chat(user, SPAN_NOTICE("You turn on \the [src].")) //Now let them chose the text. var/str = sanitizeSafe(input(user,"Label text?","Set label",""), MAX_NAME_LEN) if(!str || !length(str)) - to_chat(user, "Invalid text.") + to_chat(user, SPAN_WARNING("Invalid text.")) return label = str - to_chat(user, "You set the text to '[str]'.") + to_chat(user, SPAN_NOTICE("You set the text to '[str]'.")) else - to_chat(user, "You turn off \the [src].") \ No newline at end of file + to_chat(user, SPAN_NOTICE("You turn off \the [src].")) \ No newline at end of file diff --git a/code/modules/power/cells/power_cells.dm b/code/modules/power/cells/power_cells.dm index ca6f96ec9b..052813ade7 100644 --- a/code/modules/power/cells/power_cells.dm +++ b/code/modules/power/cells/power_cells.dm @@ -62,6 +62,11 @@ charge = 0 update_icon() +/obj/item/weapon/cell/mech + name = "mecha power cell" + charge = 15000 + maxcharge = 15000 + /obj/item/weapon/cell/infinite name = "infinite-capacity power cell!" icon_state = "icell" diff --git a/code/modules/power/fusion/core/core_control.dm b/code/modules/power/fusion/core/core_control.dm index c9ba42bbd5..e897dbd6ab 100644 --- a/code/modules/power/fusion/core/core_control.dm +++ b/code/modules/power/fusion/core/core_control.dm @@ -6,7 +6,7 @@ icon_keyboard = "tech_key" icon_screen = "core_control" -// var/id_tag + var/id_tag = "" var/scan_range = 25 var/list/connected_devices = list() var/obj/machinery/power/fusion_core/cur_viewed_device @@ -15,6 +15,7 @@ /obj/machinery/computer/fusion_core_control/New() ..() monitor = new(src) + monitor.core_tag = id_tag /obj/machinery/computer/fusion_core_control/Destroy() QDEL_NULL(monitor) diff --git a/code/modules/power/fusion/fuel_assembly/fuel_control.dm b/code/modules/power/fusion/fuel_assembly/fuel_control.dm index b0fbf33095..b5d039d5b2 100644 --- a/code/modules/power/fusion/fuel_assembly/fuel_control.dm +++ b/code/modules/power/fusion/fuel_assembly/fuel_control.dm @@ -13,6 +13,7 @@ /obj/machinery/computer/fusion_fuel_control/New() ..() monitor = new(src) + monitor.fuel_tag = id_tag /obj/machinery/computer/fusion_fuel_control/Destroy() QDEL_NULL(monitor) diff --git a/code/modules/power/fusion/gyrotron/gyrotron.dm b/code/modules/power/fusion/gyrotron/gyrotron.dm index d4c995bf73..9621234007 100644 --- a/code/modules/power/fusion/gyrotron/gyrotron.dm +++ b/code/modules/power/fusion/gyrotron/gyrotron.dm @@ -23,17 +23,16 @@ GLOBAL_LIST_EMPTY(gyrotrons) /obj/machinery/power/emitter/gyrotron/Initialize() GLOB.gyrotrons += src - update_active_power_usage(mega_energy * 50000) default_apply_parts() - . = ..() + return ..() /obj/machinery/power/emitter/gyrotron/Destroy() GLOB.gyrotrons -= src return ..() -/obj/machinery/power/emitter/gyrotron/process() - update_active_power_usage(mega_energy * 50000) - . = ..() +/obj/machinery/power/emitter/gyrotron/proc/set_beam_power(var/new_power) + mega_energy = new_power + update_active_power_usage(mega_energy * initial(active_power_usage)) /obj/machinery/power/emitter/gyrotron/get_rand_burst_delay() return rate * 10 diff --git a/code/modules/power/fusion/gyrotron/gyrotron_control.dm b/code/modules/power/fusion/gyrotron/gyrotron_control.dm index e8daf7e0b9..1f06a4b6d1 100644 --- a/code/modules/power/fusion/gyrotron/gyrotron_control.dm +++ b/code/modules/power/fusion/gyrotron/gyrotron_control.dm @@ -14,6 +14,8 @@ /obj/machinery/computer/gyrotron_control/New() ..() monitor = new(src) + monitor.gyro_tag = id_tag + monitor.scan_range = scan_range /obj/machinery/computer/gyrotron_control/Destroy() QDEL_NULL(monitor) diff --git a/code/modules/projectiles/guns/energy/phase.dm b/code/modules/projectiles/guns/energy/phase.dm index 33ba37ad40..2498aba776 100644 --- a/code/modules/projectiles/guns/energy/phase.dm +++ b/code/modules/projectiles/guns/energy/phase.dm @@ -13,6 +13,15 @@ one_handed_penalty = 15 recoil_mode = 0 //CHOMP Addition: Removes recoil for micros. +/obj/item/weapon/gun/energy/phasegun/mounted + self_recharge = 1 + use_external_power = 1 + one_handed_penalty = 0 + +/obj/item/weapon/gun/energy/phasegun/mounted/cyborg + charge_cost = 400 + recharge_time = 7 + /obj/item/weapon/gun/energy/phasegun/pistol name = "phase pistol" desc = "The RayZar EW15 Apollo is an energy handgun, specifically designed for self-defense against aggressive wildlife." diff --git a/code/modules/research/prosfab_designs.dm b/code/modules/research/prosfab_designs.dm index 8f932b0082..5fc685bf1d 100644 --- a/code/modules/research/prosfab_designs.dm +++ b/code/modules/research/prosfab_designs.dm @@ -357,10 +357,15 @@ build_path = /obj/item/robot_parts/robot_component/camera /datum/design/item/prosfab/cyborg/component/armour - name = "Armour Plating" + name = "Armour Plating (Robot)" id = "armour" build_path = /obj/item/robot_parts/robot_component/armour +/datum/design/item/prosfab/cyborg/component/armour_heavy + name = "Armour Plating (Platform)" + id = "platform_armour" + build_path = /obj/item/robot_parts/robot_component/armour_platform + /datum/design/item/prosfab/cyborg/component/ai_shell name = "AI Remote Interface" id = "mmi_ai_shell" diff --git a/code/modules/tgui/modules/gyrotron_control.dm b/code/modules/tgui/modules/gyrotron_control.dm index db753e2d8c..fd8c14bb85 100644 --- a/code/modules/tgui/modules/gyrotron_control.dm +++ b/code/modules/tgui/modules/gyrotron_control.dm @@ -3,57 +3,52 @@ tgui_id = "GyrotronControl" var/gyro_tag = "" + var/scan_range = 25 /datum/tgui_module/gyrotron_control/tgui_act(action, params) if(..()) return TRUE -/*CHOMP Removal brainlet. - for(var/parameter in params) - to_world("[parameter] - [params[parameter]]") -*/ + + // If the command requires a gyrotron, and we can't find it, we don't need to check any further + var/obj/machinery/power/emitter/gyrotron/G = null + if(params["gyro"]) + G = locate(params["gyro"]) in GLOB.gyrotrons + if(!istype(G)) + return FALSE + switch(action) - if("toggle_active") - var/obj/machinery/power/emitter/gyrotron/G = locate(params["gyro"]) - if(!istype(G)) - return 0 - - G.activate(usr) - - return 1 - if("set_tag") var/new_ident = sanitize_text(input("Enter a new ident tag.", "Gyrotron Control", gyro_tag) as null|text) if(new_ident) gyro_tag = new_ident + return TRUE + + if("toggle_active") + G.activate(usr) + return TRUE if("set_str") - var/obj/machinery/power/emitter/gyrotron/G = locate(params["gyro"]) - if(!istype(G)) - return 0 - var/new_strength = params["str"] - - G.mega_energy = new_strength - - return 1 + if(istext(new_strength)) + new_strength = text2num(new_strength) + if(new_strength) + G.set_beam_power(new_strength) + return TRUE if("set_rate") - var/obj/machinery/power/emitter/gyrotron/G = locate(params["gyro"]) - if(!istype(G)) - return 0 - var/new_delay = params["rate"] - - G.rate = new_delay - - return 1 + if(istext(new_delay)) + new_delay = text2num(new_delay) + if(new_delay) + G.rate = new_delay + return TRUE /datum/tgui_module/gyrotron_control/tgui_data(mob/user) var/list/data = list() var/list/gyros = list() for(var/obj/machinery/power/emitter/gyrotron/G in GLOB.gyrotrons) - if(G.id_tag == gyro_tag) + if(G.id_tag == gyro_tag)// && (get_dist(get_turf(G), get_turf(src)) <= scan_range)) gyros.Add(list(list( "name" = G.name, "active" = G.active, @@ -70,4 +65,4 @@ return data /datum/tgui_module/gyrotron_control/ntos - ntos = TRUE \ No newline at end of file + ntos = TRUE diff --git a/code/modules/tgui/modules/rustcore_monitor.dm b/code/modules/tgui/modules/rustcore_monitor.dm index 5da8007bc9..d4ea472a5b 100644 --- a/code/modules/tgui/modules/rustcore_monitor.dm +++ b/code/modules/tgui/modules/rustcore_monitor.dm @@ -7,23 +7,20 @@ /datum/tgui_module/rustcore_monitor/tgui_act(action, params) if(..()) return TRUE -/*CHOMP Removal brainlet. - for(var/parameter in params) - to_world("[parameter] - [params[parameter]]") -*/ + + var/obj/machinery/power/fusion_core/C = null + if(params["core"]) + C = locate(params["core"]) in GLOB.fusion_cores + if(!istype(C)) + return FALSE + switch(action) if("toggle_active") - var/obj/machinery/power/fusion_core/C = locate(params["core"]) - if(!istype(C)) - return FALSE if(!C.Startup()) //Startup() whilst the device is active will return null. C.Shutdown() return TRUE if("toggle_reactantdump") - var/obj/machinery/power/fusion_core/C = locate(params["core"]) - if(!istype(C)) - return FALSE C.reactant_dump = !C.reactant_dump return TRUE @@ -31,16 +28,11 @@ var/new_ident = sanitize_text(input("Enter a new ident tag.", "Core Control", core_tag) as null|text) if(new_ident) core_tag = new_ident + return TRUE if("set_fieldstr") - var/obj/machinery/power/fusion_core/C = locate(params["core"]) - if(!istype(C)) - return FALSE - var/new_strength = params["fieldstr"] - C.target_field_strength = new_strength - return TRUE /datum/tgui_module/rustcore_monitor/tgui_data(mob/user) @@ -58,10 +50,7 @@ "name" = reagent, "amount" = C.owned_field.dormant_reactant_quantities[reagent] ))) -/*CHOMP Removal brainlet. - for(var/list/reactant in reactants) - to_world("[reactant[1]] [reactant[2]]") -*/ + cores.Add(list(list( "name" = C.name, "has_field" = C.owned_field ? TRUE : FALSE, diff --git a/code/modules/tgui/modules/rustfuel_control.dm b/code/modules/tgui/modules/rustfuel_control.dm index 300100380d..a1e7336419 100644 --- a/code/modules/tgui/modules/rustfuel_control.dm +++ b/code/modules/tgui/modules/rustfuel_control.dm @@ -7,13 +7,10 @@ /datum/tgui_module/rustfuel_control/tgui_act(action, params) if(..()) return TRUE -/*CHOMP Removal brainlet. - for(var/parameter in params) - to_world("[parameter] - [params[parameter]]") -*/ + switch(action) if("toggle_active") - var/obj/machinery/fusion_fuel_injector/FI = locate(params["fuel"]) + var/obj/machinery/fusion_fuel_injector/FI = locate(params["fuel"]) in GLOB.fuel_injectors if(!istype(FI)) return FALSE @@ -51,4 +48,4 @@ return data /datum/tgui_module/rustfuel_control/ntos - ntos = TRUE \ No newline at end of file + ntos = TRUE diff --git a/html/changelog.html b/html/changelog.html index 4880f17395..f5813382aa 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -40,6 +40,12 @@ -->
+

25 March 2021

+

Fenodyree updated:

+ +

22 March 2021

CHOMPStationBot updated: