diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index 5f963fe8ba..4c7d0c336c 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -821,6 +821,9 @@ proc/GaussRandRound(var/sigma,var/roundto) for(var/mob/M in T) if(istype(M, /mob/observer/eye)) continue // If we need to check for more mobs, I'll add a variable M.loc = X + if(istype(M, /mob/living)) + var/mob/living/LM = M + LM.check_shadow() // Need to check their Z-shadow, which is normally done in forceMove(). if(shuttlework) var/turf/simulated/shuttle/SS = T diff --git a/code/datums/autolathe/arms.dm b/code/datums/autolathe/arms.dm index 44ece529ba..e5831cec71 100644 --- a/code/datums/autolathe/arms.dm +++ b/code/datums/autolathe/arms.dm @@ -416,7 +416,7 @@ /datum/category_item/autolathe/arms/knuckledusters name = "knuckle dusters" - path =/obj/item/weapon/material/knuckledusters + path =/obj/item/clothing/gloves/knuckledusters hidden = 1 /datum/category_item/autolathe/arms/tacknife diff --git a/code/datums/repositories/radiation.dm b/code/datums/repositories/radiation.dm index 5d06eccc77..46f4a9a5b7 100644 --- a/code/datums/repositories/radiation.dm +++ b/code/datums/repositories/radiation.dm @@ -116,7 +116,7 @@ var/global/repository/radiation/radiation_repository = new() else if(O.density) //So open doors don't get counted var/material/M = O.get_material() if(!M) continue - cached_rad_resistance += M.radiation_resistance + cached_rad_resistance += M.weight + M.radiation_resistance // Looks like storing the contents length is meant to be a basic check if the cache is stale due to items enter/exiting. Better than nothing so I'm leaving it as is. ~Leshana radiation_repository.resistance_cache[src] = (length(contents) + 1) diff --git a/code/datums/supplypacks/hospitality.dm b/code/datums/supplypacks/hospitality.dm index 83d46edde1..f3de751f23 100644 --- a/code/datums/supplypacks/hospitality.dm +++ b/code/datums/supplypacks/hospitality.dm @@ -61,3 +61,17 @@ cost = 15 containertype = /obj/structure/closet/crate/freezer containername = "Pizza crate" + +/datum/supply_packs/hospitality/gifts + name = "Gift crate" + contains = list( + /obj/item/toy/bouquet = 3, + /obj/item/weapon/storage/fancy/heartbox = 2, + /obj/item/weapon/paper/card/smile, + /obj/item/weapon/paper/card/heart, + /obj/item/weapon/paper/card/cat, + /obj/item/weapon/paper/card/flower + ) + cost = 10 + containertype = /obj/structure/closet/crate + containername = "crate of gifts" \ No newline at end of file diff --git a/code/datums/wires/mines.dm b/code/datums/wires/mines.dm new file mode 100644 index 0000000000..2d0aecaaf0 --- /dev/null +++ b/code/datums/wires/mines.dm @@ -0,0 +1,81 @@ +/datum/wires/mines + wire_count = 6 + random = 1 + holder_type = /obj/effect/mine + +#define WIRE_DETONATE 1 +#define WIRE_TIMED_DET 2 +#define WIRE_DISARM 4 +#define WIRE_DUMMY_1 8 +#define WIRE_DUMMY_2 16 +#define WIRE_BADDISARM 32 + +/datum/wires/mines/GetInteractWindow() + . = ..() + . += "
\n["Warning: detonation may occur even with proper equipment."]" + return . + +/datum/wires/mines/proc/explode() + return + +/datum/wires/mines/UpdateCut(var/index, var/mended) + var/obj/effect/mine/C = holder + + switch(index) + if(WIRE_DETONATE) + C.visible_message("\icon[C] *BEEE-*", "\icon[C] *BEEE-*") + C.explode() + + if(WIRE_TIMED_DET) + C.visible_message("\icon[C] *BEEE-*", "\icon[C] *BEEE-*") + C.explode() + + if(WIRE_DISARM) + C.visible_message("\icon[C] *click!*", "\icon[C] *click!*") + new C.mineitemtype(get_turf(C)) + spawn(0) + qdel(C) + return + + if(WIRE_DUMMY_1) + return + + + if(WIRE_DUMMY_2) + return + + if(WIRE_BADDISARM) + C.visible_message("\icon[C] *BEEPBEEPBEEP*", "\icon[C] *BEEPBEEPBEEP*") + spawn(20) + C.explode() + return + +/datum/wires/mines/UpdatePulsed(var/index) + var/obj/effect/mine/C = holder + if(IsIndexCut(index)) + return + switch(index) + if(WIRE_DETONATE) + C.visible_message("\icon[C] *beep*", "\icon[C] *beep*") + + if(WIRE_TIMED_DET) + C.visible_message("\icon[C] *BEEPBEEPBEEP*", "\icon[C] *BEEPBEEPBEEP*") + spawn(20) + C.explode() + + if(WIRE_DISARM) + C.visible_message("\icon[C] *ping*", "\icon[C] *ping*") + + if(WIRE_DUMMY_1) + C.visible_message("\icon[C] *ping*", "\icon[C] *ping*") + + if(WIRE_DUMMY_2) + C.visible_message("\icon[C] *beep*", "\icon[C] *beep*") + + if(WIRE_BADDISARM) + C.visible_message("\icon[C] *ping*", "\icon[C] *ping*") + return + +/datum/wires/mines/CanUse(var/mob/living/L) + var/obj/effect/mine/M = holder + return M.panel_open diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 02eb04b0d6..ae21bf8093 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -52,7 +52,11 @@ if (danger_level == 0) atmosphere_alarm.clearAlarm(src, alarm_source) else - atmosphere_alarm.triggerAlarm(src, alarm_source, severity = danger_level) + var/obj/machinery/alarm/atmosalarm = alarm_source //maybe other things can trigger these, who knows + if(istype(atmosalarm)) + atmosphere_alarm.triggerAlarm(src, alarm_source, severity = danger_level, hidden = atmosalarm.alarms_hidden) + else + atmosphere_alarm.triggerAlarm(src, alarm_source, severity = danger_level) //Check all the alarms before lowering atmosalm. Raising is perfectly fine. for (var/obj/machinery/alarm/AA in src) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index b00bf09529..d23f53c23a 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -389,6 +389,7 @@ /atom/proc/add_vomit_floor(mob/living/carbon/M as mob, var/toxvomit = 0) if( istype(src, /turf/simulated) ) var/obj/effect/decal/cleanable/vomit/this = new /obj/effect/decal/cleanable/vomit(src) + this.virus2 = virus_copylist(M.virus2) // Make toxins vomit look different if(toxvomit) diff --git a/code/game/gamemodes/changeling/powers/fabricate_clothing.dm b/code/game/gamemodes/changeling/powers/fabricate_clothing.dm index bc37afc1ea..aad702ea49 100644 --- a/code/game/gamemodes/changeling/powers/fabricate_clothing.dm +++ b/code/game/gamemodes/changeling/powers/fabricate_clothing.dm @@ -277,6 +277,9 @@ var/global/list/changeling_fabricated_clothing = list( /obj/item/weapon/card/id/syndicate/changeling/New(mob/user as mob) ..() registered_user = user + +/obj/item/weapon/card/id/syndicate/changeling/initialize() + . = ..() access = null /obj/item/weapon/card/id/syndicate/changeling/verb/shred() diff --git a/code/game/gamemodes/technomancer/spells/control.dm b/code/game/gamemodes/technomancer/spells/control.dm index 7302a34b75..e76e63490c 100644 --- a/code/game/gamemodes/technomancer/spells/control.dm +++ b/code/game/gamemodes/technomancer/spells/control.dm @@ -41,8 +41,8 @@ /mob/living/simple_animal/hostile/malf_drone, /mob/living/simple_animal/hostile/giant_spider, /mob/living/simple_animal/hostile/hivebot, - /mob/living/simple_animal/hostile/diyaab, //Doubt these will get used but might as well, - /mob/living/simple_animal/hostile/samak, + /mob/living/simple_animal/retaliate/diyaab, //Doubt these will get used but might as well, + /mob/living/simple_animal/hostile/savik, /mob/living/simple_animal/hostile/shantak ) diff --git a/code/game/gamemodes/technomancer/spells/modifier/corona.dm b/code/game/gamemodes/technomancer/spells/modifier/corona.dm index 74a06855d9..24d571d4c2 100644 --- a/code/game/gamemodes/technomancer/spells/modifier/corona.dm +++ b/code/game/gamemodes/technomancer/spells/modifier/corona.dm @@ -26,7 +26,7 @@ on_created_text = "You start to glow very brightly!" on_expired_text = "Your glow has ended." - evasion = -2 + evasion = -30 stacks = MODIFIER_STACK_EXTEND /datum/modifier/technomancer/corona/tick() diff --git a/code/game/gamemodes/technomancer/spells/modifier/repel_missiles.dm b/code/game/gamemodes/technomancer/spells/modifier/repel_missiles.dm index 6ead04f30c..6f3b4b892f 100644 --- a/code/game/gamemodes/technomancer/spells/modifier/repel_missiles.dm +++ b/code/game/gamemodes/technomancer/spells/modifier/repel_missiles.dm @@ -24,5 +24,5 @@ on_created_text = "You have a repulsion field around you, which will attempt to deflect projectiles." on_expired_text = "Your repulsion field has expired." - evasion = 3 + evasion = 45 stacks = MODIFIER_STACK_EXTEND \ No newline at end of file diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 7d786ce1a3..f6f7fd0c92 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -23,6 +23,7 @@ if(sleepernew) sleeper = sleepernew sleepernew.console = src + set_dir(get_dir(src, sleepernew)) return return diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 349d9fbc07..8190d79fd0 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -230,9 +230,11 @@ // Loop through every direction for(dir in list(NORTH, EAST, SOUTH, WEST)) // Loop through every direction bodyscannernew = locate(/obj/machinery/bodyscanner, get_step(src, dir)) // Try to find a scanner in that direction - if(bodyscannernew) - scanner = bodyscannernew - bodyscannernew.console = src + if(bodyscannernew) + scanner = bodyscannernew + bodyscannernew.console = src + set_dir(get_dir(src, bodyscannernew)) + return return /obj/machinery/body_scanconsole/attack_ai(user as mob) diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index b0019f9fa5..76eafc2a05 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -81,6 +81,8 @@ var/report_danger_level = 1 + var/alarms_hidden = FALSE //If the alarms from this machine are visible on consoles + /obj/machinery/alarm/nobreach breach_detection = 0 @@ -88,6 +90,9 @@ report_danger_level = 0 breach_detection = 0 +/obj/machinery/alarm/alarms_hidden + alarms_hidden = TRUE + /obj/machinery/alarm/server/New() ..() req_access = list(access_rd, access_atmospherics, access_engine_equip) @@ -813,6 +818,10 @@ FIRE ALARM panel_open = 0 var/seclevel circuit = /obj/item/weapon/circuitboard/firealarm + var/alarms_hidden = FALSE //If the alarms from this machine are visible on consoles + +/obj/machinery/firealarm/alarms_hidden + alarms_hidden = TRUE /obj/machinery/firealarm/update_icon() overlays.Cut() @@ -981,7 +990,7 @@ FIRE ALARM return var/area/area = get_area(src) for(var/obj/machinery/firealarm/FA in area) - fire_alarm.triggerAlarm(loc, FA, duration) + fire_alarm.triggerAlarm(loc, FA, duration, hidden = alarms_hidden) update_icon() playsound(src.loc, 'sound/machines/airalarm.ogg', 25, 0, 4) return diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm index 5203d7ec2e..829c819faf 100644 --- a/code/game/machinery/biogenerator.dm +++ b/code/game/machinery/biogenerator.dm @@ -46,6 +46,8 @@ return if(default_part_replacement(user, O)) return + if(default_unfasten_wrench(user, O, 40)) + return if(istype(O, /obj/item/weapon/reagent_containers/glass)) if(beaker) user << "]The [src] is already loaded." diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm index 7a4e5e3ab6..0a43acb172 100644 --- a/code/game/machinery/bioprinter.dm +++ b/code/game/machinery/bioprinter.dm @@ -44,6 +44,8 @@ return if(default_part_replacement(user, O)) return + if(default_unfasten_wrench(user, O, 20)) + return return ..() /obj/machinery/organ_printer/update_icon() diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index d546ef4676..df2387e71f 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -27,7 +27,8 @@ /obj/item/toy/waterflower = 1, /obj/random/action_figure = 1, /obj/random/plushie = 1, - /obj/item/toy/cultsword = 1 + /obj/item/toy/cultsword = 1, + /obj/item/toy/bouquet/fake = 1 ) /obj/machinery/computer/arcade/New() diff --git a/code/game/machinery/computer/guestpass.dm b/code/game/machinery/computer/guestpass.dm index 501bf91071..3a70d57173 100644 --- a/code/game/machinery/computer/guestpass.dm +++ b/code/game/machinery/computer/guestpass.dm @@ -54,8 +54,8 @@ expired = 1 return ..() -/obj/item/weapon/card/id/guest/New() - ..() +/obj/item/weapon/card/id/guest/initialize() + . = ..() processing_objects.Add(src) update_icon() diff --git a/code/game/machinery/computer3/lapvend.dm b/code/game/machinery/computer3/lapvend.dm index 4aa5d318f4..e1e70ca3a7 100644 --- a/code/game/machinery/computer3/lapvend.dm +++ b/code/game/machinery/computer3/lapvend.dm @@ -29,6 +29,9 @@ /obj/machinery/lapvend/attackby(obj/item/weapon/W as obj, mob/user as mob) var/obj/item/weapon/card/id/I = W.GetID() + if(default_unfasten_wrench(user, W, 20)) + return + if(vendmode == 1 && I) scan_id(I, W) vendmode = 0 diff --git a/code/game/machinery/frame.dm b/code/game/machinery/frame.dm index 09cbeb2e00..3e998e87d6 100644 --- a/code/game/machinery/frame.dm +++ b/code/game/machinery/frame.dm @@ -551,15 +551,15 @@ for(var/I in req_components) if(istype(P, I) && (req_components[I] > 0)) playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - if(istype(P, /obj/item/stack/material/glass/reinforced)) - var/obj/item/stack/material/glass/reinforced/CP = P - if(CP.get_amount() > 1) - var/camt = min(CP.amount, req_components[I]) // amount of glass to take, idealy amount required, but limited by amount provided - var/obj/item/stack/material/glass/reinforced/CC = new /obj/item/stack/material/glass/reinforced(src) - CC.amount = camt - CC.update_icon() - CP.use(camt) - components += CC + if(istype(P, /obj/item/stack)) + var/obj/item/stack/ST = P + if(ST.get_amount() > 1) + var/camt = min(ST.amount, req_components[I]) // amount of stack to take, idealy amount required, but limited by amount provided + var/obj/item/stack/NS = new ST.stacktype(src) + NS.amount = camt + NS.update_icon() + ST.use(camt) + components += NS req_components[I] -= camt update_desc() break diff --git a/code/game/machinery/kitchen/cooking_machines/_cooker.dm b/code/game/machinery/kitchen/cooking_machines/_cooker.dm index 26b21c9a13..9f43092942 100644 --- a/code/game/machinery/kitchen/cooking_machines/_cooker.dm +++ b/code/game/machinery/kitchen/cooking_machines/_cooker.dm @@ -50,6 +50,9 @@ user << "\The [src] is running!" return + if(default_unfasten_wrench(user, I, 20)) + return + // We are trying to cook a grabbed mob. var/obj/item/weapon/grab/G = I if(istype(G)) diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm index f3d4e69611..9b6b503237 100644 --- a/code/game/machinery/kitchen/gibber.dm +++ b/code/game/machinery/kitchen/gibber.dm @@ -92,6 +92,9 @@ /obj/machinery/gibber/attackby(var/obj/item/W, var/mob/user) var/obj/item/weapon/grab/G = W + if(default_unfasten_wrench(user, W, 40)) + return + if(!istype(G)) return ..() diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm index c789c94db5..fa81ff1620 100644 --- a/code/game/machinery/kitchen/microwave.dm +++ b/code/game/machinery/kitchen/microwave.dm @@ -87,7 +87,7 @@ src.icon_state = "mw" src.broken = 0 // Fix it! src.dirty = 0 // just to be sure - src.flags = OPENCONTAINER + src.flags = OPENCONTAINER | NOREACT else user << "It's broken!" return 1 @@ -95,6 +95,8 @@ return else if(default_deconstruction_crowbar(user, O)) return + else if(default_unfasten_wrench(user, O, 10)) + return else if(src.dirty==100) // The microwave is all dirty so can't be used! if(istype(O, /obj/item/weapon/reagent_containers/spray/cleaner) || istype(O, /obj/item/weapon/soap)) // If they're trying to clean it then let them @@ -110,7 +112,7 @@ src.dirty = 0 // It's clean! src.broken = 0 // just to be sure src.icon_state = "mw" - src.flags = OPENCONTAINER + src.flags = OPENCONTAINER | NOREACT else //Otherwise bad luck!! user << "It's dirty!" return 1 diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index 86b481b31b..a2f5c00ad1 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -22,6 +22,7 @@ var/locked = 0 var/scan_id = 1 var/is_secure = 0 + var/wrenchable = 0 var/datum/wires/smartfridge/wires = null /obj/machinery/smartfridge/secure @@ -128,6 +129,7 @@ /obj/machinery/smartfridge/drying_rack name = "\improper Drying Rack" desc = "A machine for drying plants." + wrenchable = 1 icon_state = "drying_rack" icon_on = "drying_rack_on" icon_off = "drying_rack" @@ -217,6 +219,9 @@ nanomanager.update_uis(src) return + if(wrenchable && default_unfasten_wrench(user, O, 20)) + return + if(istype(O, /obj/item/device/multitool)||istype(O, /obj/item/weapon/wirecutters)) if(panel_open) attack_hand(user) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index c616d1ee5b..673e366313 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -112,7 +112,7 @@ Class Procs: var/panel_open = 0 var/global/gl_uid = 1 var/interact_offline = 0 // Can the machine be interacted with while de-powered. - var/circuit = null + var/obj/item/weapon/circuitboard/circuit = null /obj/machinery/New(l, d=0) ..(l) @@ -402,7 +402,7 @@ Class Procs: if(A.frame_type.circuit) A.need_circuit = 0 - if(A.frame_type.frame_class == "machine") + if(A.frame_type.frame_class == FRAME_CLASS_MACHINE) for(var/obj/D in component_parts) D.forceMove(src.loc) if(A.components) @@ -412,15 +412,15 @@ Class Procs: component_parts = list() A.check_components() - if(A.frame_type.frame_class == "alarm") - A.state = 2 - else if(A.frame_type.frame_class == "computer" || A.frame_type.frame_class == "display") + if(A.frame_type.frame_class == FRAME_CLASS_ALARM) + A.state = FRAME_FASTENED + else if(A.frame_type.frame_class == FRAME_CLASS_COMPUTER || A.frame_type.frame_class == FRAME_CLASS_DISPLAY) if(stat & BROKEN) - A.state = 3 + A.state = FRAME_WIRED else - A.state = 4 + A.state = FRAME_PANELED else - A.state = 3 + A.state = FRAME_WIRED A.set_dir(dir) A.pixel_x = pixel_x @@ -430,4 +430,4 @@ Class Procs: M.loc = null M.deconstruct(src) qdel(src) - return 1 \ No newline at end of file + return 1 diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 34e89ac6fd..d4d3cedb47 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -105,16 +105,25 @@ var/mob/living/carbon/human/H = occupant // In case they somehow end up with positive values for otherwise unobtainable damage... - if(H.getToxLoss()>0) H.adjustToxLoss(-(rand(1,3))) - if(H.getOxyLoss()>0) H.adjustOxyLoss(-(rand(1,3))) - if(H.getCloneLoss()>0) H.adjustCloneLoss(-(rand(1,3))) - if(H.getBrainLoss()>0) H.adjustBrainLoss(-(rand(1,3))) + if(H.getToxLoss() > 0) + H.adjustToxLoss(-(rand(1,3))) + if(H.getOxyLoss() > 0) + H.adjustOxyLoss(-(rand(1,3))) + if(H.getCloneLoss() > 0) + H.adjustCloneLoss(-(rand(1,3))) + if(H.getBrainLoss() > 0) + H.adjustBrainLoss(-(rand(1,3))) // Also recharge their internal battery. if(!isnull(H.internal_organs_by_name["cell"]) && H.nutrition < 450) H.nutrition = min(H.nutrition+10, 450) cell.use(7000/450*10) + // And clear up radiation + if(H.radiation > 0) + H.radiation = max(H.radiation - rand(5, 15), 0) + + /obj/machinery/recharge_station/examine(mob/user) ..(user) user << "The charge meter reads: [round(chargepercentage())]%" diff --git a/code/game/machinery/seed_extractor.dm b/code/game/machinery/seed_extractor.dm index c7d6b7c514..ac88069151 100644 --- a/code/game/machinery/seed_extractor.dm +++ b/code/game/machinery/seed_extractor.dm @@ -40,4 +40,7 @@ obj/machinery/seed_extractor/attackby(var/obj/item/O as obj, var/mob/user as mob user << "You extract some seeds from the grass tile." new /obj/item/seeds/grassseed(loc) + else if(default_unfasten_wrench(user, O, 20)) + return + return \ No newline at end of file diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index f245682861..309c9cf2a4 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -88,6 +88,8 @@ return if(default_deconstruction_crowbar(user, W)) return + if(default_unfasten_wrench(user, W, 40)) + return /*if(istype(W,/obj/item/weapon/screwdriver)) panel = !panel user << "You [panel ? "open" : "close"] the [src]'s maintenance panel"*/ diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index 3cdca23fde..1b38fae182 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -247,3 +247,9 @@ var/global/list/image/splatter_cache=list() /obj/effect/decal/cleanable/mucus/New() spawn(DRYING_TIME * 2) dry=1 + +//This version should be used for admin spawns and pre-mapped virus vectors (e.g. in PoIs), this version does not dry +/obj/effect/decal/cleanable/mucus/mapped/New() + ...() + virus2 = new /datum/disease2/disease + virus2.makerandom() diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm index 5d2482d60c..ab01bfa005 100644 --- a/code/game/objects/effects/decals/Cleanable/misc.dm +++ b/code/game/objects/effects/decals/Cleanable/misc.dm @@ -100,6 +100,7 @@ icon = 'icons/effects/blood.dmi' icon_state = "vomit_1" random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") + var/list/datum/disease2/disease/virus2 = list() /obj/effect/decal/cleanable/tomato_smudge name = "tomato smudge" diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index 52f920775e..47fa55be1a 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -1,105 +1,274 @@ /obj/effect/mine - name = "Mine" - desc = "I Better stay away from that thing." - density = 1 + name = "land mine" //The name and description are deliberately NOT modified, so you can't game the mines you find. + desc = "A small explosive land mine." + density = 0 anchored = 1 - layer = 3 icon = 'icons/obj/weapons.dmi' icon_state = "uglymine" - var/triggerproc = "explode" //name of the proc thats called when the mine is triggered var/triggered = 0 + var/smoke_strength = 3 + var/mineitemtype = /obj/item/weapon/mine + var/panel_open = 0 + var/datum/wires/mines/wires = null /obj/effect/mine/New() icon_state = "uglyminearmed" + wires = new(src) + +/obj/effect/mine/proc/explode(var/mob/living/M) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() + triggered = 1 + s.set_up(3, 1, src) + s.start() + explosion(loc, 0, 2, 3, 4) //land mines are dangerous, folks. + visible_message("\The [src.name] detonates!") + qdel(s) + qdel(src) + +/obj/effect/mine/bullet_act() + if(prob(50)) + explode() + +/obj/effect/mine/ex_act(severity) + if(severity <= 2 || prob(50)) + explode() + ..() /obj/effect/mine/Crossed(AM as mob|obj) Bumped(AM) /obj/effect/mine/Bumped(mob/M as mob|obj) - if(triggered) return + if(triggered) + return - if(istype(M, /mob/living/carbon/human)) - for(var/mob/O in viewers(world.view, src.loc)) - O << "[M] triggered the \icon[src] [src]" - triggered = 1 - call(src,triggerproc)(M) + if(istype(M, /mob/living/)) + if(!M.hovering) + explode(M) -/obj/effect/mine/proc/triggerrad(obj) +/obj/effect/mine/attackby(obj/item/W as obj, mob/living/user as mob) + if(isscrewdriver(W)) + panel_open = !panel_open + user.visible_message("[user] very carefully screws the mine's panel [panel_open ? "open" : "closed"].", + "You very carefully screw the mine's panel [panel_open ? "open" : "closed"].") + playsound(src.loc, W.usesound, 50, 1) + + else if((iswirecutter(W) || ismultitool(W)) && panel_open) + interact(user) + else + ..() + +/obj/effect/mine/interact(mob/living/user as mob) + if(!panel_open || istype(user, /mob/living/silicon/ai)) + return + user.set_machine(src) + wires.Interact(user) + +/obj/effect/mine/dnascramble + mineitemtype = /obj/item/weapon/mine/dnascramble + +/obj/effect/mine/dnascramble/explode(var/mob/living/M) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() + triggered = 1 + s.set_up(3, 1, src) + s.start() + if(M) + M.radiation += 50 + randmutb(M) + domutcheck(M,null) + visible_message("\The [src.name] flashes violently before disintegrating!") + spawn(0) + qdel(s) + qdel(src) + +/obj/effect/mine/stun + mineitemtype = /obj/item/weapon/mine/stun + +/obj/effect/mine/stun/explode(var/mob/living/M) + triggered = 1 var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() s.set_up(3, 1, src) s.start() - obj:radiation += 50 - randmutb(obj) - domutcheck(obj,null) - spawn(0) - qdel(src) - -/obj/effect/mine/proc/triggerstun(obj) - if(ismob(obj)) - var/mob/M = obj + if(M) M.Stun(30) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() - s.set_up(3, 1, src) - s.start() + visible_message("\The [src.name] flashes violently before disintegrating!") spawn(0) + qdel(s) qdel(src) -/obj/effect/mine/proc/triggern2o(obj) - //example: n2o triggerproc - //note: im lazy +/obj/effect/mine/n2o + mineitemtype = /obj/item/weapon/mine/n2o +/obj/effect/mine/n2o/explode(var/mob/living/M) + triggered = 1 for (var/turf/simulated/floor/target in range(1,src)) if(!target.blocks_air) target.assume_gas("sleeping_agent", 30) - + visible_message("\The [src.name] detonates!") spawn(0) qdel(src) -/obj/effect/mine/proc/triggerphoron(obj) +/obj/effect/mine/phoron + mineitemtype = /obj/item/weapon/mine/phoron + +/obj/effect/mine/phoron/explode(var/mob/living/M) + triggered = 1 for (var/turf/simulated/floor/target in range(1,src)) if(!target.blocks_air) target.assume_gas("phoron", 30) - target.hotspot_expose(1000, CELL_VOLUME) - + visible_message("\The [src.name] detonates!") spawn(0) qdel(src) -/obj/effect/mine/proc/triggerkick(obj) +/obj/effect/mine/kick + mineitemtype = /obj/item/weapon/mine/kick + +/obj/effect/mine/kick/explode(var/mob/living/M) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() + triggered = 1 + s.set_up(3, 1, src) + s.start() + if(M) + qdel(M.client) + spawn(0) + qdel(s) + qdel(src) + +/obj/effect/mine/frag + mineitemtype = /obj/item/weapon/mine/frag + var/fragment_types = list(/obj/item/projectile/bullet/pellet/fragment) + var/num_fragments = 20 //total number of fragments produced by the grenade + //The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern + var/spread_range = 7 + +/obj/effect/mine/frag/explode(var/mob/living/M) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() + triggered = 1 + s.set_up(3, 1, src) + s.start() + var/turf/O = get_turf(src) + if(!O) + return + src.fragmentate(O, 20, 7, list(/obj/item/projectile/bullet/pellet/fragment)) //only 20 weak fragments because you're stepping directly on it + visible_message("\The [src.name] detonates!") + spawn(0) + qdel(s) + qdel(src) + +/obj/effect/mine/training //Name and Desc commented out so it's possible to trick people with the training mines +// name = "training mine" +// desc = "A mine with its payload removed, for EOD training and demonstrations." + mineitemtype = /obj/item/weapon/mine/training + +/obj/effect/mine/training/explode(var/mob/living/M) + triggered = 1 + visible_message("\The [src.name]'s light flashes rapidly as it 'explodes'.") + new src.mineitemtype(get_turf(src)) + spawn(0) + qdel(src) + +/obj/effect/mine/emp + mineitemtype = /obj/item/weapon/mine/emp + +/obj/effect/mine/emp/explode(var/mob/living/M) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() s.set_up(3, 1, src) s.start() - qdel(obj:client) + visible_message("\The [src.name] flashes violently before disintegrating!") + empulse(loc, 2, 4, 7, 10, 1) // As strong as an EMP grenade spawn(0) qdel(src) -/obj/effect/mine/proc/explode(obj) - explosion(loc, 0, 1, 2, 3) +/obj/effect/mine/incendiary + mineitemtype = /obj/item/weapon/mine/incendiary + +/obj/effect/mine/incendiary/explode(var/mob/living/M) + triggered = 1 + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() + s.set_up(3, 1, src) + s.start() + if(M) + M.adjust_fire_stacks(5) + M.fire_act() + visible_message("\The [src.name] bursts into flames!") spawn(0) qdel(src) -/obj/effect/mine/dnascramble - name = "Radiation Mine" +///////////////////////////////////////////// +// The held item version of the above mines +///////////////////////////////////////////// +/obj/item/weapon/mine + name = "mine" + desc = "A small explosive mine with 'HE' and a grenade symbol on the side." + icon = 'icons/obj/weapons.dmi' icon_state = "uglymine" - triggerproc = "triggerrad" + var/countdown = 10 + var/minetype = /obj/effect/mine //This MUST be an /obj/effect/mine type, or it'll runtime. -/obj/effect/mine/phoron - name = "Phoron Mine" - icon_state = "uglymine" - triggerproc = "triggerphoron" +/obj/item/weapon/mine/attack_self(mob/user as mob) // You do not want to move or throw a land mine while priming it... Explosives + Sudden Movement = Bad Times + add_fingerprint(user) + msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)") + user.visible_message("[user] starts priming \the [src.name].", "You start priming \the [src.name]. Hold still!") + if(do_after(user, 10 SECONDS)) + playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) + prime(user) + else + visible_message("[user] triggers \the [src.name]!", "You accidentally trigger \the [src.name]!") + prime(user, TRUE) + return -/obj/effect/mine/kick - name = "Kick Mine" - icon_state = "uglymine" - triggerproc = "triggerkick" +/obj/item/weapon/mine/proc/prime(mob/user as mob, var/explode_now = FALSE) + visible_message("\The [src.name] beeps as the priming sequence completes.") + var/obj/effect/mine/R = new minetype(get_turf(src)) + src.transfer_fingerprints_to(R) + R.add_fingerprint(user) + if(explode_now) + R.explode(user) + spawn(0) + qdel(src) -/obj/effect/mine/n2o - name = "N2O Mine" - icon_state = "uglymine" - triggerproc = "triggern2o" +/obj/item/weapon/mine/dnascramble + name = "radiation mine" + desc = "A small explosive mine with a radiation symbol on the side." + minetype = /obj/effect/mine/dnascramble -/obj/effect/mine/stun - name = "Stun Mine" - icon_state = "uglymine" - triggerproc = "triggerstun" +/obj/item/weapon/mine/phoron + name = "incendiary mine" + desc = "A small explosive mine with a fire symbol on the side." + minetype = /obj/effect/mine/phoron + +/obj/item/weapon/mine/kick + name = "kick mine" + desc = "Concentrated war crimes. Handle with care." + minetype = /obj/effect/mine/kick + +/obj/item/weapon/mine/n2o + name = "nitrous oxide mine" + desc = "A small explosive mine with three Z's on the side." + minetype = /obj/effect/mine/n2o + +/obj/item/weapon/mine/stun + name = "stun mine" + desc = "A small explosive mine with a lightning bolt symbol on the side." + minetype = /obj/effect/mine/stun + +/obj/item/weapon/mine/frag + name = "fragmentation mine" + desc = "A small explosive mine with 'FRAG' and a grenade symbol on the side." + minetype = /obj/effect/mine/frag + +/obj/item/weapon/mine/training + name = "training mine" + desc = "A mine with its payload removed, for EOD training and demonstrations." + minetype = /obj/effect/mine/training + +/obj/item/weapon/mine/emp + name = "emp mine" + desc = "A small explosive mine with a lightning bolt symbol on the side." + minetype = /obj/effect/mine/emp + +/obj/item/weapon/mine/incendiary + name = "incendiary mine" + desc = "A small explosive mine with a fire symbol on the side." + minetype = /obj/effect/mine/incendiary \ No newline at end of file diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index bf091e1180..c5840eaed2 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1,658 +1,681 @@ -/obj/item - name = "item" - icon = 'icons/obj/items.dmi' - w_class = ITEMSIZE_NORMAL - - var/image/blood_overlay = null //this saves our blood splatter overlay, which will be processed not to go over the edges of the sprite - var/abstract = 0 - var/r_speed = 1.0 - var/health = null - var/burn_point = null - var/burning = null - var/hitsound = null - var/usesound = null // Like hitsound, but for when used properly and not to kill someone. - var/storage_cost = null - var/slot_flags = 0 //This is used to determine on which slots an item can fit. - var/no_attack_log = 0 //If it's an item we don't want to log attack_logs with, set this to 1 - pass_flags = PASSTABLE - pressure_resistance = 5 -// causeerrorheresoifixthis - var/obj/item/master = null - var/list/origin_tech = null //Used by R&D to determine what research bonuses it grants. - var/list/attack_verb = list() //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]" - var/force = 0 - - var/heat_protection = 0 //flags which determine which body parts are protected from heat. Use the HEAD, UPPER_TORSO, LOWER_TORSO, etc. flags. See setup.dm - var/cold_protection = 0 //flags which determine which body parts are protected from cold. Use the HEAD, UPPER_TORSO, LOWER_TORSO, etc. flags. See setup.dm - var/max_heat_protection_temperature //Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. Keep at null to disable protection. Only protects areas set by heat_protection flags - var/min_cold_protection_temperature //Set this variable to determine down to which temperature (IN KELVIN) the item protects against cold damage. 0 is NOT an acceptable number due to if(varname) tests!! Keep at null to disable protection. Only protects areas set by cold_protection flags - - var/datum/action/item_action/action = null - var/action_button_name //It is also the text which gets displayed on the action button. If not set it defaults to 'Use [name]'. If it's not set, there'll be no button. - var/action_button_is_hands_free = 0 //If 1, bypass the restrained, lying, and stunned checks action buttons normally test for - - //This flag is used to determine when items in someone's inventory cover others. IE helmets making it so you can't see glasses, etc. - //It should be used purely for appearance. For gameplay effects caused by items covering body parts, use body_parts_covered. - var/flags_inv = 0 - var/body_parts_covered = 0 //see setup.dm for appropriate bit flags - - var/item_flags = 0 //Miscellaneous flags pertaining to equippable objects. - - //var/heat_transfer_coefficient = 1 //0 prevents all transfers, 1 is invisible - var/gas_transfer_coefficient = 1 // for leaking gas from turf to mask and vice-versa (for masks right now, but at some point, i'd like to include space helmets) - var/permeability_coefficient = 1 // for chemicals/diseases - var/siemens_coefficient = 1 // for electrical admittance/conductance (electrocution checks and shit) - var/slowdown = 0 // How much clothing is slowing you down. Negative values speeds you up - var/canremove = 1 //Mostly for Ninja code at this point but basically will not allow the item to be removed if set to 0. /N - var/list/armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - var/list/armorsoak = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - var/list/allowed = null //suit storage stuff. - var/obj/item/device/uplink/hidden/hidden_uplink = null // All items can have an uplink hidden inside, just remember to add the triggers. - var/zoomdevicename = null //name used for message when binoculars/scope is used - var/zoom = 0 //1 if item is actively being used to zoom. For scoped guns and binoculars. - - var/embed_chance = -1 //0 won't embed, and 100 will always embed - - var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc. - - //** These specify item/icon overrides for _slots_ - - var/list/item_state_slots = list() //overrides the default item_state for particular slots. - - // Used to specify the icon file to be used when the item is worn. If not set the default icon for that slot will be used. - // If icon_override or sprite_sheets are set they will take precendence over this, assuming they apply to the slot in question. - // Only slot_l_hand/slot_r_hand are implemented at the moment. Others to be implemented as needed. - var/list/item_icons = list() - - //** These specify item/icon overrides for _species_ - - /* Species-specific sprites, concept stolen from Paradise//vg/. - ex: - sprite_sheets = list( - "Tajara" = 'icons/cat/are/bad' - ) - If index term exists and icon_override is not set, this sprite sheet will be used. - */ - var/list/sprite_sheets = list() - - // Species-specific sprite sheets for inventory sprites - // Works similarly to worn sprite_sheets, except the alternate sprites are used when the clothing/refit_for_species() proc is called. - var/list/sprite_sheets_obj = list() - - var/toolspeed = 1.0 // This is a multipler on how 'fast' a tool works. e.g. setting this to 0.5 will make the tool work twice as fast. - var/attackspeed = DEFAULT_ATTACK_COOLDOWN // How long click delay will be when using this, in 1/10ths of a second. Checked in the user's get_attack_speed(). - var/reach = 1 // Length of tiles it can reach, 1 is adjacent. - var/addblends // Icon overlay for ADD highlights when applicable. - -/obj/item/New() - ..() - if(embed_chance < 0) - if(sharp) - embed_chance = max(5, round(force/w_class)) - else - embed_chance = max(5, round(force/(w_class*3))) - -/obj/item/equipped() - ..() - var/mob/living/M = loc - if(!istype(M)) - return - M.update_held_icons() - -/obj/item/Destroy() - if(ismob(loc)) - var/mob/m = loc - m.drop_from_inventory(src) - m.update_inv_r_hand() - m.update_inv_l_hand() - src.loc = null - return ..() - -/obj/item/device - icon = 'icons/obj/device.dmi' - -//Checks if the item is being held by a mob, and if so, updates the held icons -/obj/item/proc/update_held_icon() - if(isliving(src.loc)) - var/mob/living/M = src.loc - if(M.l_hand == src) - M.update_inv_l_hand() - else if(M.r_hand == src) - M.update_inv_r_hand() - -/obj/item/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(50)) - qdel(src) - return - if(3.0) - if (prob(5)) - qdel(src) - return - else - return - -//user: The mob that is suiciding -//damagetype: The type of damage the item will inflict on the user -//BRUTELOSS = 1 -//FIRELOSS = 2 -//TOXLOSS = 4 -//OXYLOSS = 8 -//Output a creative message and then return the damagetype done -/obj/item/proc/suicide_act(mob/user) - return - -/obj/item/verb/move_to_top() - set name = "Move To Top" - set category = "Object" - set src in oview(1) - - if(!istype(src.loc, /turf) || usr.stat || usr.restrained() ) - return - - var/turf/T = src.loc - - src.loc = null - - src.loc = T - -// See inventory_sizes.dm for the defines. -/obj/item/examine(mob/user, var/distance = -1) - var/size - switch(src.w_class) - if(ITEMSIZE_TINY) - size = "tiny" - if(ITEMSIZE_SMALL) - size = "small" - if(ITEMSIZE_NORMAL) - size = "normal-sized" - if(ITEMSIZE_LARGE) - size = "bulky" - if(ITEMSIZE_HUGE) - size = "huge" - return ..(user, distance, "", "It is a [size] item.") - -/obj/item/attack_hand(mob/living/user as mob) - if (!user) return - if (hasorgans(user)) - var/mob/living/carbon/human/H = user - var/obj/item/organ/external/temp = H.organs_by_name["r_hand"] - if (user.hand) - temp = H.organs_by_name["l_hand"] - if(temp && !temp.is_usable()) - user << "You try to move your [temp.name], but cannot!" - return - if(!temp) - user << "You try to use your hand, but realize it is no longer attached!" - return - src.pickup(user) - if (istype(src.loc, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/S = src.loc - S.remove_from_storage(src) - - src.throwing = 0 - if (src.loc == user) - if(!user.unEquip(src)) - return - else - if(isliving(src.loc)) - return - user.put_in_active_hand(src) - return - -/obj/item/attack_ai(mob/user as mob) - if (istype(src.loc, /obj/item/weapon/robot_module)) - //If the item is part of a cyborg module, equip it - if(!isrobot(user)) - return - var/mob/living/silicon/robot/R = user - R.activate_module(src) - R.hud_used.update_robot_modules_display() - -/obj/item/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/S = W - if(S.use_to_pickup) - if(S.collection_mode) //Mode is set to collect all items - if(isturf(src.loc)) - S.gather_all(src.loc, user) - - else if(S.can_be_inserted(src)) - S.handle_item_insertion(src) - return - -/obj/item/proc/talk_into(mob/M as mob, text) - return - -/obj/item/proc/moved(mob/user as mob, old_loc as turf) - return - -// apparently called whenever an item is removed from a slot, container, or anything else. -/obj/item/proc/dropped(mob/user as mob) - ..() - if(zoom) - zoom() //binoculars, scope, etc - appearance_flags &= ~NO_CLIENT_COLOR - -// called just as an item is picked up (loc is not yet changed) -/obj/item/proc/pickup(mob/user) - return - -// called when this item is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called. -/obj/item/proc/on_exit_storage(obj/item/weapon/storage/S as obj) - return - -// called when this item is added into a storage item, which is passed on as S. The loc variable is already set to the storage item. -/obj/item/proc/on_enter_storage(obj/item/weapon/storage/S as obj) - return - -// called when "found" in pockets and storage items. Returns 1 if the search should end. -/obj/item/proc/on_found(mob/finder as mob) - return - -// called after an item is placed in an equipment slot -// user is mob that equipped it -// slot uses the slot_X defines found in setup.dm -// for items that can be placed in multiple slots -// note this isn't called during the initial dressing of a player -/obj/item/proc/equipped(var/mob/user, var/slot) - hud_layerise() - if(user.client) user.client.screen |= src - if(user.pulling == src) user.stop_pulling() - return - -//Defines which slots correspond to which slot flags -var/list/global/slot_flags_enumeration = list( - "[slot_wear_mask]" = SLOT_MASK, - "[slot_back]" = SLOT_BACK, - "[slot_wear_suit]" = SLOT_OCLOTHING, - "[slot_gloves]" = SLOT_GLOVES, - "[slot_shoes]" = SLOT_FEET, - "[slot_belt]" = SLOT_BELT, - "[slot_glasses]" = SLOT_EYES, - "[slot_head]" = SLOT_HEAD, - "[slot_l_ear]" = SLOT_EARS|SLOT_TWOEARS, - "[slot_r_ear]" = SLOT_EARS|SLOT_TWOEARS, - "[slot_w_uniform]" = SLOT_ICLOTHING, - "[slot_wear_id]" = SLOT_ID, - "[slot_tie]" = SLOT_TIE, - ) - -//the mob M is attempting to equip this item into the slot passed through as 'slot'. Return 1 if it can do this and 0 if it can't. -//If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen. -//Set disable_warning to 1 if you wish it to not give you outputs. -//Should probably move the bulk of this into mob code some time, as most of it is related to the definition of slots and not item-specific -/obj/item/proc/mob_can_equip(M as mob, slot, disable_warning = 0) - if(!slot) return 0 - if(!M) return 0 - - if(!ishuman(M)) return 0 - - var/mob/living/carbon/human/H = M - var/list/mob_equip = list() - if(H.species.hud && H.species.hud.equip_slots) - mob_equip = H.species.hud.equip_slots - - if(H.species && !(slot in mob_equip)) - return 0 - - //First check if the item can be equipped to the desired slot. - if("[slot]" in slot_flags_enumeration) - var/req_flags = slot_flags_enumeration["[slot]"] - if(!(req_flags & slot_flags)) - return 0 - - //Next check that the slot is free - if(H.get_equipped_item(slot)) - return 0 - - //Next check if the slot is accessible. - var/mob/_user = disable_warning? null : H - if(!H.slot_is_accessible(slot, src, _user)) - return 0 - - //Lastly, check special rules for the desired slot. - switch(slot) - if(slot_l_ear, slot_r_ear) - var/slot_other_ear = (slot == slot_l_ear)? slot_r_ear : slot_l_ear - if( (w_class > ITEMSIZE_TINY) && !(slot_flags & SLOT_EARS) ) - return 0 - if( (slot_flags & SLOT_TWOEARS) && H.get_equipped_item(slot_other_ear) ) - return 0 - if(slot_wear_id) - if(!H.w_uniform && (slot_w_uniform in mob_equip)) - if(!disable_warning) - H << "You need a jumpsuit before you can attach this [name]." - return 0 - if(slot_l_store, slot_r_store) - if(!H.w_uniform && (slot_w_uniform in mob_equip)) - if(!disable_warning) - H << "You need a jumpsuit before you can attach this [name]." - return 0 - if(slot_flags & SLOT_DENYPOCKET) - return 0 - if( w_class > ITEMSIZE_SMALL && !(slot_flags & SLOT_POCKET) ) - return 0 - if(slot_s_store) - if(!H.wear_suit && (slot_wear_suit in mob_equip)) - if(!disable_warning) - H << "You need a suit before you can attach this [name]." - return 0 - if(!H.wear_suit.allowed) - if(!disable_warning) - usr << "You somehow have a suit with no defined allowed items for suit storage, stop that." - return 0 - if( !(istype(src, /obj/item/device/pda) || istype(src, /obj/item/weapon/pen) || is_type_in_list(src, H.wear_suit.allowed)) ) - return 0 - if(slot_legcuffed) //Going to put this check above the handcuff check because the survival of the universe depends on it. - if(!istype(src, /obj/item/weapon/handcuffs/legcuffs)) //Putting it here might actually do nothing. - return 0 - if(slot_handcuffed) - if(!istype(src, /obj/item/weapon/handcuffs) || istype(src, /obj/item/weapon/handcuffs/legcuffs)) //Legcuffs are a child of handcuffs, but we don't want to use legcuffs as handcuffs... - return 0 //In theory, this would never happen, but let's just do the legcuff check anyways. - if(slot_in_backpack) //used entirely for equipping spawned mobs or at round start - var/allow = 0 - if(H.back && istype(H.back, /obj/item/weapon/storage/backpack)) - var/obj/item/weapon/storage/backpack/B = H.back - if(B.can_be_inserted(src,1)) - allow = 1 - if(!allow) - return 0 - if(slot_tie) - if(!H.w_uniform && (slot_w_uniform in mob_equip)) - if(!disable_warning) - H << "You need a jumpsuit before you can attach this [name]." - return 0 - var/obj/item/clothing/under/uniform = H.w_uniform - if(uniform.accessories.len && !uniform.can_attach_accessory(src)) - if (!disable_warning) - H << "You already have an accessory of this type attached to your [uniform]." - return 0 - return 1 - -/obj/item/proc/mob_can_unequip(mob/M, slot, disable_warning = 0) - if(!slot) return 0 - if(!M) return 0 - - if(!canremove) - return 0 - if(!M.slot_is_accessible(slot, src, disable_warning? null : M)) - return 0 - return 1 - -/obj/item/verb/verb_pickup() - set src in oview(1) - set category = "Object" - set name = "Pick up" - - if(!(usr)) //BS12 EDIT - return - if(!usr.canmove || usr.stat || usr.restrained() || !Adjacent(usr)) - return - if((!istype(usr, /mob/living/carbon)) || (istype(usr, /mob/living/carbon/brain)))//Is humanoid, and is not a brain - usr << "You can't pick things up!" - return - var/mob/living/carbon/C = usr - if( usr.stat || usr.restrained() )//Is not asleep/dead and is not restrained - usr << "You can't pick things up!" - return - if(src.anchored) //Object isn't anchored - usr << "You can't pick that up!" - return - if(C.get_active_hand()) //Hand is not full - usr << "Your hand is full." - return - if(!istype(src.loc, /turf)) //Object is on a turf - usr << "You can't pick that up!" - return - //All checks are done, time to pick it up! - usr.UnarmedAttack(src) - return - - -//This proc is executed when someone clicks the on-screen UI button. To make the UI button show, set the 'icon_action_button' to the icon_state of the image of the button in screen1_action.dmi -//The default action is attack_self(). -//Checks before we get to here are: mob is alive, mob is not restrained, paralyzed, asleep, resting, laying, item is on the mob. -/obj/item/proc/ui_action_click() - attack_self(usr) - -//RETURN VALUES -//handle_shield should return a positive value to indicate that the attack is blocked and should be prevented. -//If a negative value is returned, it should be treated as a special return value for bullet_act() and handled appropriately. -//For non-projectile attacks this usually means the attack is blocked. -//Otherwise should return 0 to indicate that the attack is not affected in any way. -/obj/item/proc/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") - return 0 - -/obj/item/proc/get_loc_turf() - var/atom/L = loc - while(L && !istype(L, /turf/)) - L = L.loc - return loc - -/obj/item/proc/eyestab(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - - var/mob/living/carbon/human/H = M - var/mob/living/carbon/human/U = user - if(istype(H)) - for(var/obj/item/protection in list(H.head, H.wear_mask, H.glasses)) - if(protection && (protection.body_parts_covered & EYES)) - // you can't stab someone in the eyes wearing a mask! - user << "You're going to need to remove the eye covering first." - return - - if(!M.has_eyes()) - user << "You cannot locate any eyes on [M]!" - return - - if(U.get_accuracy_penalty(U)) //Should only trigger if they're not aiming well - var/hit_zone = get_zone_with_miss_chance(U.zone_sel.selecting, M, U.get_accuracy_penalty(U)) - if(!hit_zone) - U.do_attack_animation(M) - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[U] attempts to stab [M] in the eyes, but misses!") - return - - user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" - M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" - msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") //BS12 EDIT ALG - - user.setClickCooldown(user.get_attack_speed()) - user.do_attack_animation(M) - - src.add_fingerprint(user) - //if((CLUMSY in user.mutations) && prob(50)) - // M = user - /* - M << "You stab yourself in the eye." - M.sdisabilities |= BLIND - M.weakened += 4 - M.adjustBruteLoss(10) - */ - - if(istype(H)) - - var/obj/item/organ/internal/eyes/eyes = H.internal_organs_by_name[O_EYES] - - if(H != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("[M] has been stabbed in the eye with [src] by [user].", 1) - M << "[user] stabs you in the eye with [src]!" - user << "You stab [M] in the eye with [src]!" - else - user.visible_message( \ - "[user] has stabbed themself with [src]!", \ - "You stab yourself in the eyes with [src]!" \ - ) - - eyes.damage += rand(3,4) - if(eyes.damage >= eyes.min_bruised_damage) - if(M.stat != 2) - if(!(eyes.robotic >= ORGAN_ROBOT)) //robot eyes bleeding might be a bit silly - M << "Your eyes start to bleed profusely!" - if(prob(50)) - if(M.stat != 2) - M << "You drop what you're holding and clutch at your eyes!" - M.drop_item() - M.eye_blurry += 10 - M.Paralyse(1) - M.Weaken(4) - if (eyes.damage >= eyes.min_broken_damage) - if(M.stat != 2) - M << "You go blind!" - var/obj/item/organ/external/affecting = H.get_organ(BP_HEAD) - if(affecting.take_damage(7)) - M:UpdateDamageIcon() - else - M.take_organ_damage(7) - M.eye_blurry += rand(3,4) - return - -/obj/item/clean_blood() - . = ..() - if(blood_overlay) - overlays.Remove(blood_overlay) - if(istype(src, /obj/item/clothing/gloves)) - var/obj/item/clothing/gloves/G = src - G.transfer_blood = 0 - -/obj/item/reveal_blood() - if(was_bloodied && !fluorescent) - fluorescent = 1 - blood_color = COLOR_LUMINOL - blood_overlay.color = COLOR_LUMINOL - update_icon() - -/obj/item/add_blood(mob/living/carbon/human/M as mob) - if (!..()) - return 0 - - if(istype(src, /obj/item/weapon/melee/energy)) - return - - //if we haven't made our blood_overlay already - if( !blood_overlay ) - generate_blood_overlay() - - //apply the blood-splatter overlay if it isn't already in there - if(!blood_DNA.len) - blood_overlay.color = blood_color - overlays += blood_overlay - - //if this blood isn't already in the list, add it - if(istype(M)) - if(blood_DNA[M.dna.unique_enzymes]) - return 0 //already bloodied with this blood. Cannot add more. - blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - return 1 //we applied blood to the item - -/obj/item/proc/generate_blood_overlay() - if(blood_overlay) - return - - var/icon/I = new /icon(icon, icon_state) - I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD) //fills the icon_state with white (except where it's transparent) - I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY) //adds blood and the remaining white areas become transparant - - //not sure if this is worth it. It attaches the blood_overlay to every item of the same type if they don't have one already made. - for(var/obj/item/A in world) - if(A.type == type && !A.blood_overlay) - A.blood_overlay = image(I) - -/obj/item/proc/showoff(mob/user) - for (var/mob/M in view(user)) - M.show_message("[user] holds up [src]. Take a closer look.",1) - -/mob/living/carbon/verb/showoff() - set name = "Show Held Item" - set category = "Object" - - var/obj/item/I = get_active_hand() - if(I && !I.abstract) - I.showoff(src) - -/* -For zooming with scope or binoculars. This is called from -modules/mob/mob_movement.dm if you move you will be zoomed out -modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. -*/ -//Looking through a scope or binoculars should /not/ improve your periphereal vision. Still, increase viewsize a tiny bit so that sniping isn't as restricted to NSEW -/obj/item/proc/zoom(var/tileoffset = 14,var/viewsize = 9) //tileoffset is client view offset in the direction the user is facing. viewsize is how far out this thing zooms. 7 is normal view - - var/devicename - - if(zoomdevicename) - devicename = zoomdevicename - else - devicename = src.name - - var/cannotzoom - - if(usr.stat || !(istype(usr,/mob/living/carbon/human))) - usr << "You are unable to focus through the [devicename]" - cannotzoom = 1 - else if(!zoom && global_hud.darkMask[1] in usr.client.screen) - usr << "Your visor gets in the way of looking through the [devicename]" - cannotzoom = 1 - else if(!zoom && usr.get_active_hand() != src) - usr << "You are too distracted to look through the [devicename], perhaps if it was in your active hand this might work better" - cannotzoom = 1 - - if(!zoom && !cannotzoom) - if(usr.hud_used.hud_shown) - usr.toggle_zoom_hud() // If the user has already limited their HUD this avoids them having a HUD when they zoom in - usr.client.view = viewsize - zoom = 1 - - var/tilesize = 32 - var/viewoffset = tilesize * tileoffset - - switch(usr.dir) - if (NORTH) - usr.client.pixel_x = 0 - usr.client.pixel_y = viewoffset - if (SOUTH) - usr.client.pixel_x = 0 - usr.client.pixel_y = -viewoffset - if (EAST) - usr.client.pixel_x = viewoffset - usr.client.pixel_y = 0 - if (WEST) - usr.client.pixel_x = -viewoffset - usr.client.pixel_y = 0 - - usr.visible_message("[usr] peers through the [zoomdevicename ? "[zoomdevicename] of the [src.name]" : "[src.name]"].") - - else - usr.client.view = world.view - if(!usr.hud_used.hud_shown) - usr.toggle_zoom_hud() - zoom = 0 - - usr.client.pixel_x = 0 - usr.client.pixel_y = 0 - - if(!cannotzoom) - usr.visible_message("[zoomdevicename ? "[usr] looks up from the [src.name]" : "[usr] lowers the [src.name]"].") - - return - -/obj/item/proc/pwr_drain() - return 0 // Process Kill - -// Used for non-adjacent melee attacks with specific weapons capable of reaching more than one tile. -// This uses changeling range string A* but for this purpose its also applicable. -/obj/item/proc/attack_can_reach(var/atom/us, var/atom/them, var/range) - if(us.Adjacent(them)) - return TRUE // Already adjacent. - if(AStar(get_turf(us), get_turf(them), /turf/proc/AdjacentTurfsRangedSting, /turf/proc/Distance, max_nodes=25, max_node_depth=range)) - return TRUE - return FALSE - -// Check if an object should ignite others, like a lit lighter or candle. -/obj/item/proc/is_hot() - return FALSE \ No newline at end of file +/obj/item + name = "item" + icon = 'icons/obj/items.dmi' + w_class = ITEMSIZE_NORMAL + + var/image/blood_overlay = null //this saves our blood splatter overlay, which will be processed not to go over the edges of the sprite + var/abstract = 0 + var/r_speed = 1.0 + var/health = null + var/burn_point = null + var/burning = null + var/hitsound = null + var/usesound = null // Like hitsound, but for when used properly and not to kill someone. + var/storage_cost = null + var/slot_flags = 0 //This is used to determine on which slots an item can fit. + var/no_attack_log = 0 //If it's an item we don't want to log attack_logs with, set this to 1 + pass_flags = PASSTABLE + pressure_resistance = 5 +// causeerrorheresoifixthis + var/obj/item/master = null + var/list/origin_tech = null //Used by R&D to determine what research bonuses it grants. + var/list/attack_verb = list() //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]" + var/force = 0 + + var/heat_protection = 0 //flags which determine which body parts are protected from heat. Use the HEAD, UPPER_TORSO, LOWER_TORSO, etc. flags. See setup.dm + var/cold_protection = 0 //flags which determine which body parts are protected from cold. Use the HEAD, UPPER_TORSO, LOWER_TORSO, etc. flags. See setup.dm + var/max_heat_protection_temperature //Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. Keep at null to disable protection. Only protects areas set by heat_protection flags + var/min_cold_protection_temperature //Set this variable to determine down to which temperature (IN KELVIN) the item protects against cold damage. 0 is NOT an acceptable number due to if(varname) tests!! Keep at null to disable protection. Only protects areas set by cold_protection flags + + var/datum/action/item_action/action = null + var/action_button_name //It is also the text which gets displayed on the action button. If not set it defaults to 'Use [name]'. If it's not set, there'll be no button. + var/action_button_is_hands_free = 0 //If 1, bypass the restrained, lying, and stunned checks action buttons normally test for + + //This flag is used to determine when items in someone's inventory cover others. IE helmets making it so you can't see glasses, etc. + //It should be used purely for appearance. For gameplay effects caused by items covering body parts, use body_parts_covered. + var/flags_inv = 0 + var/body_parts_covered = 0 //see setup.dm for appropriate bit flags + + var/item_flags = 0 //Miscellaneous flags pertaining to equippable objects. + + //var/heat_transfer_coefficient = 1 //0 prevents all transfers, 1 is invisible + var/gas_transfer_coefficient = 1 // for leaking gas from turf to mask and vice-versa (for masks right now, but at some point, i'd like to include space helmets) + var/permeability_coefficient = 1 // for chemicals/diseases + var/siemens_coefficient = 1 // for electrical admittance/conductance (electrocution checks and shit) + var/slowdown = 0 // How much clothing is slowing you down. Negative values speeds you up + var/canremove = 1 //Mostly for Ninja code at this point but basically will not allow the item to be removed if set to 0. /N + var/list/armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + var/list/armorsoak = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + var/list/allowed = null //suit storage stuff. + var/obj/item/device/uplink/hidden/hidden_uplink = null // All items can have an uplink hidden inside, just remember to add the triggers. + var/zoomdevicename = null //name used for message when binoculars/scope is used + var/zoom = 0 //1 if item is actively being used to zoom. For scoped guns and binoculars. + + var/embed_chance = -1 //0 won't embed, and 100 will always embed + + var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc. + + //** These specify item/icon overrides for _slots_ + + var/list/item_state_slots = list() //overrides the default item_state for particular slots. + + // Used to specify the icon file to be used when the item is worn. If not set the default icon for that slot will be used. + // If icon_override or sprite_sheets are set they will take precendence over this, assuming they apply to the slot in question. + // Only slot_l_hand/slot_r_hand are implemented at the moment. Others to be implemented as needed. + var/list/item_icons = list() + + //** These specify item/icon overrides for _species_ + + /* Species-specific sprites, concept stolen from Paradise//vg/. + ex: + sprite_sheets = list( + "Tajara" = 'icons/cat/are/bad' + ) + If index term exists and icon_override is not set, this sprite sheet will be used. + */ + var/list/sprite_sheets = list() + + // Species-specific sprite sheets for inventory sprites + // Works similarly to worn sprite_sheets, except the alternate sprites are used when the clothing/refit_for_species() proc is called. + var/list/sprite_sheets_obj = list() + + var/toolspeed = 1.0 // This is a multipler on how 'fast' a tool works. e.g. setting this to 0.5 will make the tool work twice as fast. + var/attackspeed = DEFAULT_ATTACK_COOLDOWN // How long click delay will be when using this, in 1/10ths of a second. Checked in the user's get_attack_speed(). + var/reach = 1 // Length of tiles it can reach, 1 is adjacent. + var/addblends // Icon overlay for ADD highlights when applicable. + +/obj/item/New() + ..() + if(embed_chance < 0) + if(sharp) + embed_chance = max(5, round(force/w_class)) + else + embed_chance = max(5, round(force/(w_class*3))) + +/obj/item/equipped() + ..() + var/mob/living/M = loc + if(!istype(M)) + return + M.update_held_icons() + +/obj/item/Destroy() + if(ismob(loc)) + var/mob/m = loc + m.drop_from_inventory(src) + m.update_inv_r_hand() + m.update_inv_l_hand() + src.loc = null + return ..() + +/obj/item/proc/update_twohanding() + update_held_icon() + +/obj/item/proc/is_held_twohanded(mob/living/M) + var/check_hand + if(M.l_hand == src && !M.r_hand) + check_hand = BP_R_HAND //item in left hand, check right hand + else if(M.r_hand == src && !M.l_hand) + check_hand = BP_L_HAND //item in right hand, check left hand + else + return FALSE + + //would check is_broken() and is_malfunctioning() here too but is_malfunctioning() + //is probabilistic so we can't do that and it would be unfair to just check one. + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/hand = H.organs_by_name[check_hand] + if(istype(hand) && hand.is_usable()) + return TRUE + return FALSE + + +//Checks if the item is being held by a mob, and if so, updates the held icons +/obj/item/proc/update_held_icon() + if(isliving(src.loc)) + var/mob/living/M = src.loc + if(M.l_hand == src) + M.update_inv_l_hand() + else if(M.r_hand == src) + M.update_inv_r_hand() + +/obj/item/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(50)) + qdel(src) + return + if(3.0) + if (prob(5)) + qdel(src) + return + else + return + +//user: The mob that is suiciding +//damagetype: The type of damage the item will inflict on the user +//BRUTELOSS = 1 +//FIRELOSS = 2 +//TOXLOSS = 4 +//OXYLOSS = 8 +//Output a creative message and then return the damagetype done +/obj/item/proc/suicide_act(mob/user) + return + +/obj/item/verb/move_to_top() + set name = "Move To Top" + set category = "Object" + set src in oview(1) + + if(!istype(src.loc, /turf) || usr.stat || usr.restrained() ) + return + + var/turf/T = src.loc + + src.loc = null + + src.loc = T + +// See inventory_sizes.dm for the defines. +/obj/item/examine(mob/user, var/distance = -1) + var/size + switch(src.w_class) + if(ITEMSIZE_TINY) + size = "tiny" + if(ITEMSIZE_SMALL) + size = "small" + if(ITEMSIZE_NORMAL) + size = "normal-sized" + if(ITEMSIZE_LARGE) + size = "bulky" + if(ITEMSIZE_HUGE) + size = "huge" + return ..(user, distance, "", "It is a [size] item.") + +/obj/item/attack_hand(mob/living/user as mob) + if (!user) return + if (hasorgans(user)) + var/mob/living/carbon/human/H = user + var/obj/item/organ/external/temp = H.organs_by_name["r_hand"] + if (user.hand) + temp = H.organs_by_name["l_hand"] + if(temp && !temp.is_usable()) + user << "You try to move your [temp.name], but cannot!" + return + if(!temp) + user << "You try to use your hand, but realize it is no longer attached!" + return + src.pickup(user) + if (istype(src.loc, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/S = src.loc + S.remove_from_storage(src) + + src.throwing = 0 + if (src.loc == user) + if(!user.unEquip(src)) + return + else + if(isliving(src.loc)) + return + user.put_in_active_hand(src) + return + +/obj/item/attack_ai(mob/user as mob) + if (istype(src.loc, /obj/item/weapon/robot_module)) + //If the item is part of a cyborg module, equip it + if(!isrobot(user)) + return + var/mob/living/silicon/robot/R = user + R.activate_module(src) + R.hud_used.update_robot_modules_display() + +/obj/item/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/S = W + if(S.use_to_pickup) + if(S.collection_mode) //Mode is set to collect all items + if(isturf(src.loc)) + S.gather_all(src.loc, user) + + else if(S.can_be_inserted(src)) + S.handle_item_insertion(src) + return + +/obj/item/proc/talk_into(mob/M as mob, text) + return + +/obj/item/proc/moved(mob/user as mob, old_loc as turf) + return + +// apparently called whenever an item is removed from a slot, container, or anything else. +/obj/item/proc/dropped(mob/user as mob) + ..() + if(zoom) + zoom() //binoculars, scope, etc + appearance_flags &= ~NO_CLIENT_COLOR + +// called just as an item is picked up (loc is not yet changed) +/obj/item/proc/pickup(mob/user) + return + +// called when this item is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called. +/obj/item/proc/on_exit_storage(obj/item/weapon/storage/S as obj) + return + +// called when this item is added into a storage item, which is passed on as S. The loc variable is already set to the storage item. +/obj/item/proc/on_enter_storage(obj/item/weapon/storage/S as obj) + return + +// called when "found" in pockets and storage items. Returns 1 if the search should end. +/obj/item/proc/on_found(mob/finder as mob) + return + +// called after an item is placed in an equipment slot +// user is mob that equipped it +// slot uses the slot_X defines found in setup.dm +// for items that can be placed in multiple slots +// note this isn't called during the initial dressing of a player +/obj/item/proc/equipped(var/mob/user, var/slot) + hud_layerise() + if(user.client) user.client.screen |= src + if(user.pulling == src) user.stop_pulling() + return + +//Defines which slots correspond to which slot flags +var/list/global/slot_flags_enumeration = list( + "[slot_wear_mask]" = SLOT_MASK, + "[slot_back]" = SLOT_BACK, + "[slot_wear_suit]" = SLOT_OCLOTHING, + "[slot_gloves]" = SLOT_GLOVES, + "[slot_shoes]" = SLOT_FEET, + "[slot_belt]" = SLOT_BELT, + "[slot_glasses]" = SLOT_EYES, + "[slot_head]" = SLOT_HEAD, + "[slot_l_ear]" = SLOT_EARS|SLOT_TWOEARS, + "[slot_r_ear]" = SLOT_EARS|SLOT_TWOEARS, + "[slot_w_uniform]" = SLOT_ICLOTHING, + "[slot_wear_id]" = SLOT_ID, + "[slot_tie]" = SLOT_TIE, + ) + +//the mob M is attempting to equip this item into the slot passed through as 'slot'. Return 1 if it can do this and 0 if it can't. +//If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen. +//Set disable_warning to 1 if you wish it to not give you outputs. +//Should probably move the bulk of this into mob code some time, as most of it is related to the definition of slots and not item-specific +/obj/item/proc/mob_can_equip(M as mob, slot, disable_warning = 0) + if(!slot) return 0 + if(!M) return 0 + + if(!ishuman(M)) return 0 + + var/mob/living/carbon/human/H = M + var/list/mob_equip = list() + if(H.species.hud && H.species.hud.equip_slots) + mob_equip = H.species.hud.equip_slots + + if(H.species && !(slot in mob_equip)) + return 0 + + //First check if the item can be equipped to the desired slot. + if("[slot]" in slot_flags_enumeration) + var/req_flags = slot_flags_enumeration["[slot]"] + if(!(req_flags & slot_flags)) + return 0 + + //Next check that the slot is free + if(H.get_equipped_item(slot)) + return 0 + + //Next check if the slot is accessible. + var/mob/_user = disable_warning? null : H + if(!H.slot_is_accessible(slot, src, _user)) + return 0 + + //Lastly, check special rules for the desired slot. + switch(slot) + if(slot_l_ear, slot_r_ear) + var/slot_other_ear = (slot == slot_l_ear)? slot_r_ear : slot_l_ear + if( (w_class > ITEMSIZE_TINY) && !(slot_flags & SLOT_EARS) ) + return 0 + if( (slot_flags & SLOT_TWOEARS) && H.get_equipped_item(slot_other_ear) ) + return 0 + if(slot_wear_id) + if(!H.w_uniform && (slot_w_uniform in mob_equip)) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [name]." + return 0 + if(slot_l_store, slot_r_store) + if(!H.w_uniform && (slot_w_uniform in mob_equip)) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [name]." + return 0 + if(slot_flags & SLOT_DENYPOCKET) + return 0 + if( w_class > ITEMSIZE_SMALL && !(slot_flags & SLOT_POCKET) ) + return 0 + if(slot_s_store) + if(!H.wear_suit && (slot_wear_suit in mob_equip)) + if(!disable_warning) + H << "You need a suit before you can attach this [name]." + return 0 + if(!H.wear_suit.allowed) + if(!disable_warning) + usr << "You somehow have a suit with no defined allowed items for suit storage, stop that." + return 0 + if( !(istype(src, /obj/item/device/pda) || istype(src, /obj/item/weapon/pen) || is_type_in_list(src, H.wear_suit.allowed)) ) + return 0 + if(slot_legcuffed) //Going to put this check above the handcuff check because the survival of the universe depends on it. + if(!istype(src, /obj/item/weapon/handcuffs/legcuffs)) //Putting it here might actually do nothing. + return 0 + if(slot_handcuffed) + if(!istype(src, /obj/item/weapon/handcuffs) || istype(src, /obj/item/weapon/handcuffs/legcuffs)) //Legcuffs are a child of handcuffs, but we don't want to use legcuffs as handcuffs... + return 0 //In theory, this would never happen, but let's just do the legcuff check anyways. + if(slot_in_backpack) //used entirely for equipping spawned mobs or at round start + var/allow = 0 + if(H.back && istype(H.back, /obj/item/weapon/storage/backpack)) + var/obj/item/weapon/storage/backpack/B = H.back + if(B.can_be_inserted(src,1)) + allow = 1 + if(!allow) + return 0 + if(slot_tie) + if(!H.w_uniform && (slot_w_uniform in mob_equip)) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [name]." + return 0 + var/obj/item/clothing/under/uniform = H.w_uniform + if(uniform.accessories.len && !uniform.can_attach_accessory(src)) + if (!disable_warning) + H << "You already have an accessory of this type attached to your [uniform]." + return 0 + return 1 + +/obj/item/proc/mob_can_unequip(mob/M, slot, disable_warning = 0) + if(!slot) return 0 + if(!M) return 0 + + if(!canremove) + return 0 + if(!M.slot_is_accessible(slot, src, disable_warning? null : M)) + return 0 + return 1 + +/obj/item/verb/verb_pickup() + set src in oview(1) + set category = "Object" + set name = "Pick up" + + if(!(usr)) //BS12 EDIT + return + if(!usr.canmove || usr.stat || usr.restrained() || !Adjacent(usr)) + return + if((!istype(usr, /mob/living/carbon)) || (istype(usr, /mob/living/carbon/brain)))//Is humanoid, and is not a brain + usr << "You can't pick things up!" + return + var/mob/living/carbon/C = usr + if( usr.stat || usr.restrained() )//Is not asleep/dead and is not restrained + usr << "You can't pick things up!" + return + if(src.anchored) //Object isn't anchored + usr << "You can't pick that up!" + return + if(C.get_active_hand()) //Hand is not full + usr << "Your hand is full." + return + if(!istype(src.loc, /turf)) //Object is on a turf + usr << "You can't pick that up!" + return + //All checks are done, time to pick it up! + usr.UnarmedAttack(src) + return + + +//This proc is executed when someone clicks the on-screen UI button. To make the UI button show, set the 'icon_action_button' to the icon_state of the image of the button in screen1_action.dmi +//The default action is attack_self(). +//Checks before we get to here are: mob is alive, mob is not restrained, paralyzed, asleep, resting, laying, item is on the mob. +/obj/item/proc/ui_action_click() + attack_self(usr) + +//RETURN VALUES +//handle_shield should return a positive value to indicate that the attack is blocked and should be prevented. +//If a negative value is returned, it should be treated as a special return value for bullet_act() and handled appropriately. +//For non-projectile attacks this usually means the attack is blocked. +//Otherwise should return 0 to indicate that the attack is not affected in any way. +/obj/item/proc/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") + return 0 + +/obj/item/proc/get_loc_turf() + var/atom/L = loc + while(L && !istype(L, /turf/)) + L = L.loc + return loc + +/obj/item/proc/eyestab(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + + var/mob/living/carbon/human/H = M + var/mob/living/carbon/human/U = user + if(istype(H)) + for(var/obj/item/protection in list(H.head, H.wear_mask, H.glasses)) + if(protection && (protection.body_parts_covered & EYES)) + // you can't stab someone in the eyes wearing a mask! + user << "You're going to need to remove the eye covering first." + return + + if(!M.has_eyes()) + user << "You cannot locate any eyes on [M]!" + return + + if(U.get_accuracy_penalty(U)) //Should only trigger if they're not aiming well + var/hit_zone = get_zone_with_miss_chance(U.zone_sel.selecting, M, U.get_accuracy_penalty(U)) + if(!hit_zone) + U.do_attack_animation(M) + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[U] attempts to stab [M] in the eyes, but misses!") + return + + user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" + M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" + msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") //BS12 EDIT ALG + + user.setClickCooldown(user.get_attack_speed()) + user.do_attack_animation(M) + + src.add_fingerprint(user) + //if((CLUMSY in user.mutations) && prob(50)) + // M = user + /* + M << "You stab yourself in the eye." + M.sdisabilities |= BLIND + M.weakened += 4 + M.adjustBruteLoss(10) + */ + + if(istype(H)) + + var/obj/item/organ/internal/eyes/eyes = H.internal_organs_by_name[O_EYES] + + if(H != user) + for(var/mob/O in (viewers(M) - user - M)) + O.show_message("[M] has been stabbed in the eye with [src] by [user].", 1) + M << "[user] stabs you in the eye with [src]!" + user << "You stab [M] in the eye with [src]!" + else + user.visible_message( \ + "[user] has stabbed themself with [src]!", \ + "You stab yourself in the eyes with [src]!" \ + ) + + eyes.damage += rand(3,4) + if(eyes.damage >= eyes.min_bruised_damage) + if(M.stat != 2) + if(!(eyes.robotic >= ORGAN_ROBOT)) //robot eyes bleeding might be a bit silly + M << "Your eyes start to bleed profusely!" + if(prob(50)) + if(M.stat != 2) + M << "You drop what you're holding and clutch at your eyes!" + M.drop_item() + M.eye_blurry += 10 + M.Paralyse(1) + M.Weaken(4) + if (eyes.damage >= eyes.min_broken_damage) + if(M.stat != 2) + M << "You go blind!" + var/obj/item/organ/external/affecting = H.get_organ(BP_HEAD) + if(affecting.take_damage(7)) + M:UpdateDamageIcon() + else + M.take_organ_damage(7) + M.eye_blurry += rand(3,4) + return + +/obj/item/clean_blood() + . = ..() + if(blood_overlay) + overlays.Remove(blood_overlay) + if(istype(src, /obj/item/clothing/gloves)) + var/obj/item/clothing/gloves/G = src + G.transfer_blood = 0 + +/obj/item/reveal_blood() + if(was_bloodied && !fluorescent) + fluorescent = 1 + blood_color = COLOR_LUMINOL + blood_overlay.color = COLOR_LUMINOL + update_icon() + +/obj/item/add_blood(mob/living/carbon/human/M as mob) + if (!..()) + return 0 + + if(istype(src, /obj/item/weapon/melee/energy)) + return + + //if we haven't made our blood_overlay already + if( !blood_overlay ) + generate_blood_overlay() + + //apply the blood-splatter overlay if it isn't already in there + if(!blood_DNA.len) + blood_overlay.color = blood_color + overlays += blood_overlay + + //if this blood isn't already in the list, add it + if(istype(M)) + if(blood_DNA[M.dna.unique_enzymes]) + return 0 //already bloodied with this blood. Cannot add more. + blood_DNA[M.dna.unique_enzymes] = M.dna.b_type + return 1 //we applied blood to the item + +/obj/item/proc/generate_blood_overlay() + if(blood_overlay) + return + + var/icon/I = new /icon(icon, icon_state) + I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD) //fills the icon_state with white (except where it's transparent) + I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY) //adds blood and the remaining white areas become transparant + + //not sure if this is worth it. It attaches the blood_overlay to every item of the same type if they don't have one already made. + for(var/obj/item/A in world) + if(A.type == type && !A.blood_overlay) + A.blood_overlay = image(I) + +/obj/item/proc/showoff(mob/user) + for (var/mob/M in view(user)) + M.show_message("[user] holds up [src]. Take a closer look.",1) + +/mob/living/carbon/verb/showoff() + set name = "Show Held Item" + set category = "Object" + + var/obj/item/I = get_active_hand() + if(I && !I.abstract) + I.showoff(src) + +/* +For zooming with scope or binoculars. This is called from +modules/mob/mob_movement.dm if you move you will be zoomed out +modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. +*/ +//Looking through a scope or binoculars should /not/ improve your periphereal vision. Still, increase viewsize a tiny bit so that sniping isn't as restricted to NSEW +/obj/item/proc/zoom(var/tileoffset = 14,var/viewsize = 9) //tileoffset is client view offset in the direction the user is facing. viewsize is how far out this thing zooms. 7 is normal view + + var/devicename + + if(zoomdevicename) + devicename = zoomdevicename + else + devicename = src.name + + var/cannotzoom + + if(usr.stat || !(istype(usr,/mob/living/carbon/human))) + usr << "You are unable to focus through the [devicename]" + cannotzoom = 1 + else if(!zoom && global_hud.darkMask[1] in usr.client.screen) + usr << "Your visor gets in the way of looking through the [devicename]" + cannotzoom = 1 + else if(!zoom && usr.get_active_hand() != src) + usr << "You are too distracted to look through the [devicename], perhaps if it was in your active hand this might work better" + cannotzoom = 1 + + if(!zoom && !cannotzoom) + if(usr.hud_used.hud_shown) + usr.toggle_zoom_hud() // If the user has already limited their HUD this avoids them having a HUD when they zoom in + usr.client.view = viewsize + zoom = 1 + + var/tilesize = 32 + var/viewoffset = tilesize * tileoffset + + switch(usr.dir) + if (NORTH) + usr.client.pixel_x = 0 + usr.client.pixel_y = viewoffset + if (SOUTH) + usr.client.pixel_x = 0 + usr.client.pixel_y = -viewoffset + if (EAST) + usr.client.pixel_x = viewoffset + usr.client.pixel_y = 0 + if (WEST) + usr.client.pixel_x = -viewoffset + usr.client.pixel_y = 0 + + usr.visible_message("[usr] peers through the [zoomdevicename ? "[zoomdevicename] of the [src.name]" : "[src.name]"].") + + else + usr.client.view = world.view + if(!usr.hud_used.hud_shown) + usr.toggle_zoom_hud() + zoom = 0 + + usr.client.pixel_x = 0 + usr.client.pixel_y = 0 + + if(!cannotzoom) + usr.visible_message("[zoomdevicename ? "[usr] looks up from the [src.name]" : "[usr] lowers the [src.name]"].") + + return + +/obj/item/proc/pwr_drain() + return 0 // Process Kill + +// Used for non-adjacent melee attacks with specific weapons capable of reaching more than one tile. +// This uses changeling range string A* but for this purpose its also applicable. +/obj/item/proc/attack_can_reach(var/atom/us, var/atom/them, var/range) + if(us.Adjacent(them)) + return TRUE // Already adjacent. + if(AStar(get_turf(us), get_turf(them), /turf/proc/AdjacentTurfsRangedSting, /turf/proc/Distance, max_nodes=25, max_node_depth=range)) + return TRUE + return FALSE + +// Check if an object should ignite others, like a lit lighter or candle. +/obj/item/proc/is_hot() + return FALSE + +// My best guess as to why this is here would be that it does so little. Still, keep it under all the procs, for sanity's sake. +/obj/item/device + icon = 'icons/obj/device.dmi' \ No newline at end of file diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index 847ce58560..9eb4991f69 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -44,7 +44,7 @@ if(paddles && paddles.loc == src) //in case paddles got destroyed somehow. new_overlays += "[initial(icon_state)]-paddles" - if(bcell) + if(bcell && paddles) if(bcell.check_charge(paddles.chargecost)) if(paddles.combat) new_overlays += "[initial(icon_state)]-combat" diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm index e4932ff0d2..30d4195355 100644 --- a/code/game/objects/items/devices/gps.dm +++ b/code/game/objects/items/devices/gps.dm @@ -80,7 +80,7 @@ var/list/GPS_list = list() var/turf/curr = get_turf(src) var/area/my_area = get_area(src) - dat += "Current location: [my_area.name] ([curr.x], [curr.y], [curr.z])" + dat += "Current location: [my_area.name] ([curr.x], [curr.y], [using_map.get_zlevel_name(curr.z)])" dat += "[hide_signal ? "Tagged" : "Broadcasting"] as '[gps_tag]'. \[Change Tag\] \ \[Toggle Scan Range\] \ [can_hide_signal ? "\[Toggle Signal Visibility\]":""]" @@ -103,16 +103,17 @@ var/list/GPS_list = list() var/area_name = their_area.name if(istype(their_area, /area/submap)) area_name = "Unknown Area" // Avoid spoilers. - var/coord = "[T.x], [T.y], [T.z]" - var/degrees = round(Get_Angle(curr, T)) + var/Z_name = using_map.get_zlevel_name(T.z) var/direction = uppertext(dir2text(get_dir(curr, T))) var/distance = get_dist(curr, T) var/local = curr.z == T.z ? TRUE : FALSE if(!direction) direction = "CENTER" - degrees = "N/A" - signals += " [G.gps_tag]: [area_name] ([coord]) [local ? "Dist: [distance]m Dir: [degrees]° ([direction])":""]" + if(istype(T, /obj/item/device/gps/internal/poi)) + signals += " [G.gps_tag]: [area_name] [local ? "Dist: [round(distance, 10)]m [direction])" : "in \the [Z_name]"]" + else + signals += " [G.gps_tag]: [area_name] [local ? "Dist: [round(distance, 10)]m [direction])" : "in \the [Z_name]"]" if(signals.len) dat += "Detected signals;" @@ -179,15 +180,6 @@ var/list/GPS_list = list() /obj/item/device/gps/explorer/on tracking = TRUE -/obj/item/device/gps/syndie - icon_state = "gps-syndie" - gps_tag = "NULL" - desc = "A positioning system that has extended range and can detect other GPS device signals without revealing its own. How that works is best left a mystery. Alt+click to toggle power." - origin_tech = list(TECH_MATERIAL = 2, TECH_BLUESPACE = 3, TECH_MAGNET = 2, TECH_ILLEGAL = 2) - long_range = TRUE - hide_signal = TRUE - can_hide_signal = TRUE - /obj/item/device/gps/robot icon_state = "gps-b" gps_tag = "SYNTH0" @@ -207,6 +199,72 @@ var/list/GPS_list = list() gps_tag = "NT_BASE" desc = "A homing signal from NanoTrasen's outpost." -/obj/item/device/gps/internal/alien_vessel - gps_tag = "Mysterious Signal" - desc = "A signal that seems forboding." \ No newline at end of file +/obj/item/device/gps/internal/poi + gps_tag = "Unidentified Signal" + desc = "A signal that seems forboding." + +/obj/item/device/gps/syndie + icon_state = "gps-syndie" + gps_tag = "NULL" + desc = "A positioning system that has extended range and can detect other GPS device signals without revealing its own. How that works is best left a mystery. Alt+click to toggle power." + origin_tech = list(TECH_MATERIAL = 2, TECH_BLUESPACE = 3, TECH_MAGNET = 2, TECH_ILLEGAL = 2) + long_range = TRUE + hide_signal = TRUE + can_hide_signal = TRUE + +/obj/item/device/gps/syndie/display(mob/user) + if(!tracking) + to_chat(user, "The device is off. Alt-click it to turn it on.") + return + if(emped) + to_chat(user, "It's busted!") + return + + var/list/dat = list() + + var/turf/curr = get_turf(src) + var/area/my_area = get_area(src) + dat += "Current location: [my_area.name] ([curr.x], [curr.y], [using_map.get_zlevel_name(curr.z)])" + dat += "[hide_signal ? "Tagged" : "Broadcasting"] as '[gps_tag]'. \[Change Tag\] \ + \[Toggle Scan Range\] \ + [can_hide_signal ? "\[Toggle Signal Visibility\]":""]" + + var/list/signals = list() + + for(var/gps in GPS_list) + var/obj/item/device/gps/G = gps + if(G.emped || !G.tracking || G.hide_signal || G == src) // Their GPS isn't on or functional. + continue + var/turf/T = get_turf(G) + var/z_level_detection = using_map.get_map_levels(curr.z, long_range) + + if(local_mode && T.z != curr.z) // Only care about the current z-level. + continue + else if(!(T.z in z_level_detection)) // Too far away. + continue + + var/area/their_area = get_area(G) + var/area_name = their_area.name + if(istype(their_area, /area/submap)) + area_name = "Unknown Area" // Avoid spoilers. + var/Z_name = using_map.get_zlevel_name(T.z) + var/coord = "[T.x], [T.y], [Z_name]" + var/degrees = round(Get_Angle(curr, T)) + var/direction = uppertext(dir2text(get_dir(curr, T))) + var/distance = get_dist(curr, T) + var/local = curr.z == T.z ? TRUE : FALSE + if(!direction) + direction = "CENTER" + degrees = "N/A" + + signals += " [G.gps_tag]: [area_name] ([coord]) [local ? "Dist: [distance]m Dir: [degrees]° ([direction])":""]" + + if(signals.len) + dat += "Detected signals;" + for(var/line in signals) + dat += line + else + dat += "No other signals detected." + + var/result = dat.Join("
") + to_chat(user, result) diff --git a/code/game/objects/items/paintkit.dm b/code/game/objects/items/paintkit.dm index 61939b2325..87b7566b60 100644 --- a/code/game/objects/items/paintkit.dm +++ b/code/game/objects/items/paintkit.dm @@ -109,9 +109,9 @@ suit.icon_override = new_icon_override_file S.icon_override = new_icon_override_file to_chat(user, "You set about modifying the suit into [suit].") - var/mob/living/carbon/human/H = user - if(istype(H)) - suit.species_restricted = list(H.species.get_bodytype(H)) +// var/mob/living/carbon/human/H = user +// if(istype(H)) +// suit.species_restricted = list(H.species.get_bodytype(H)) Does not quite make sense for something usually very pliable. else var/obj/item/clothing/suit/space/void/suit = I suit.name = "[new_name] voidsuit" diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 16e9daf9cc..6c1afb2c83 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -54,6 +54,8 @@ /obj/item/borg/sight/material name = "\proper material scanner vision" sight_mode = BORGMATERIAL + icon_state = "material" + icon = 'icons/obj/clothing/glasses.dmi' /obj/item/borg/sight/hud name = "hud" diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 784eadd3b9..ff680ab468 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -36,7 +36,7 @@ icon_state = "rods" var/global/list/datum/stack_recipe/rods_recipes = list( \ - new/datum/stack_recipe("grille", /obj/structure/grille, 2, time = 10, one_per_turf = 1, on_floor = 1), + new/datum/stack_recipe("grille", /obj/structure/grille, 2, time = 10, one_per_turf = 1, on_floor = 0), new/datum/stack_recipe("catwalk", /obj/structure/catwalk, 2, time = 80, one_per_turf = 1, on_floor = 1)) /obj/item/stack/rods/attackby(obj/item/W as obj, mob/user as mob) @@ -44,7 +44,7 @@ var/global/list/datum/stack_recipe/rods_recipes = list( \ var/obj/item/weapon/weldingtool/WT = W if(get_amount() < 2) - user << "You need at least two rods to do this." + to_chat(user, "You need at least two rods to do this.") return if(WT.remove_fuel(0,user)) @@ -91,15 +91,15 @@ var/global/list/datum/stack_recipe/rods_recipes = list( \ else if(!in_use) if(get_amount() < 2) - user << "You need at least two rods to do this." + to_chat(user, "You need at least two rods to do this.") return - usr << "Assembling grille..." + to_chat(usr, "Assembling grille...") in_use = 1 if (!do_after(usr, 10)) in_use = 0 return var/obj/structure/grille/F = new /obj/structure/grille/ ( usr.loc ) - usr << "You assemble a grille" + to_chat(usr, "You assemble a grille") in_use = 0 F.add_fingerprint(usr) use(2) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 62f02816ed..c86993fa31 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -16,6 +16,7 @@ * Action figures * Plushies * Toy cult sword + * Bouquets */ @@ -872,6 +873,19 @@ w_class = ITEMSIZE_LARGE attack_verb = list("attacked", "slashed", "stabbed", "poked") +//Flowers fake & real + +/obj/item/toy/bouquet + name = "bouquet" + desc = "A lovely bouquet of flowers. Smells nice!" + icon = 'icons/obj/items.dmi' + icon_state = "bouquet" + w_class = ITEMSIZE_SMALL + +/obj/item/toy/bouquet/fake + name = "plastic bouquet" + desc = "A cheap plastic bouquet of flowers. Smells like cheap, toxic plastic." + /* NYET. /obj/item/weapon/toddler icon_state = "toddler" diff --git a/code/game/objects/items/weapons/bones.dm b/code/game/objects/items/weapons/bones.dm new file mode 100644 index 0000000000..617ddd9c1a --- /dev/null +++ b/code/game/objects/items/weapons/bones.dm @@ -0,0 +1,46 @@ +//These bone objects are mostly for mapping and decoration. They have no actual medical use, so maybe don't try to put them in anybody. +/obj/item/weapon/bone + name = "bone" + desc = "A non-descript bone. It's so old and worn you can barely tell which part of the body it's from." + icon = 'icons/obj/bones.dmi' + icon_state = "bone" + force = 5 + throwforce = 6 + item_state = "bone" + w_class = ITEMSIZE_SMALL + attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked", "bonked", "boned") + +/obj/item/weapon/bone/skull + name = "skull" + desc = "A skull. Judging by the shape and size, you'd guess that it might be human." + icon_state = "skull" + throwforce = 7 + +/obj/item/weapon/bone/skull/tajaran + desc = "A skull. Judging by the shape and size, you'd guess that it might be tajaran." + icon_state = "tajskull" + +/obj/item/weapon/bone/skull/unathi + desc = "A skull. Judging by the shape and size, you'd guess that it might be unathi." + icon_state = "unaskull" + +/obj/item/weapon/bone/skull/unknown + desc = "A skull. You're not sure what species it might be, though." + icon_state = "xenoskull" + +/obj/item/weapon/bone/arm + name = "arm bone" + desc = "Wielding this, you're armed and dangerous, no bones about it." + attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked", "bonked", "boned", "slapped", "punched") + icon_state = "arm" + +/obj/item/weapon/bone/leg + name = "leg bone" + desc = "Don't worry about getting into an argument with the owner of this. They don't have a leg to stand on." + attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked", "bonked", "boned", "kicked") + icon_state = "leg" + +/obj/item/weapon/bone/ribs + name = "ribcage" + desc = "If you had some mallets, you could probably use this as a makeshift xylophone." + icon_state = "ribs" diff --git a/code/game/objects/items/weapons/candle.dm b/code/game/objects/items/weapons/candle.dm index 5ea04c2dab..7bc0398b72 100644 --- a/code/game/objects/items/weapons/candle.dm +++ b/code/game/objects/items/weapons/candle.dm @@ -70,3 +70,41 @@ lit = 0 update_icon() set_light(0) + +/obj/item/weapon/flame/candle/candelabra + name = "candelabra" + desc = "a small gold candelabra. The cups that hold the candles save some of the wax from dripping off, allowing the candles to burn longer." + icon = 'icons/obj/candle.dmi' + icon_state = "candelabra" + w_class = ITEMSIZE_SMALL + wax = 20000 + +/obj/item/weapon/flame/candle/candelabra/update_icon() + if(wax == 0) + icon_state = "candelabra_melted" + else + icon_state = "candelabra[lit ? "_lit" : ""]" + +/obj/item/weapon/flame/candle/everburn + wax = 99999 + +/obj/item/weapon/flame/candle/everburn/New() + if(!src.lit) + src.lit = 1 + //src.damtype = "fire" + for(var/mob/O in viewers(usr, null)) + O.show_message("\The [name] mysteriously lights itself!.", 1) + set_light(CANDLE_LUM) + processing_objects.Add(src) + +/obj/item/weapon/flame/candle/candelabra/everburn + wax = 99999 + +/obj/item/weapon/flame/candle/candelabra/everburn/New() + if(!src.lit) + src.lit = 1 + //src.damtype = "fire" + for(var/mob/O in viewers(usr, null)) + O.show_message("\The [name] mysteriously lights itself!.", 1) + set_light(CANDLE_LUM) + processing_objects.Add(src) diff --git a/code/game/objects/items/weapons/circuitboards/machinery/power.dm b/code/game/objects/items/weapons/circuitboards/machinery/power.dm index 6242335bed..9bd5f98bad 100644 --- a/code/game/objects/items/weapons/circuitboards/machinery/power.dm +++ b/code/game/objects/items/weapons/circuitboards/machinery/power.dm @@ -9,6 +9,10 @@ origin_tech = list(TECH_POWER = 6, TECH_ENGINEERING = 4) req_components = list(/obj/item/weapon/smes_coil = 1, /obj/item/stack/cable_coil = 30) +/obj/item/weapon/circuitboard/smes/construct(var/obj/machinery/power/smes/buildable/S) + if(..(S)) + S.output_attempt = 0 //built SMES default to off + /obj/item/weapon/circuitboard/batteryrack name = T_BOARD("battery rack PSU") build_path = /obj/machinery/power/smes/batteryrack 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 4c1e4b9aaf..4ba2ed4fc1 100644 --- a/code/game/objects/items/weapons/id cards/station_ids.dm +++ b/code/game/objects/items/weapons/id cards/station_ids.dm @@ -112,15 +112,11 @@ usr << "The fingerprint hash on the card is [fingerprint_hash]." return -/obj/item/weapon/card/id/New() - ..() - var/datum/job/jobdatum - for(var/jobtype in typesof(/datum/job)) - var/datum/job/J = new jobtype - if(J.title == rank) - jobdatum = J - access = jobdatum.get_access() - return +/obj/item/weapon/card/id/initialize() + . = ..() + var/datum/job/J = job_master.GetJob(rank) + if(J) + access = J.get_access() /obj/item/weapon/card/id/silver name = "identification card" @@ -163,8 +159,8 @@ item_state = "tdgreen" assignment = "Synthetic" -/obj/item/weapon/card/id/synthetic/New() - ..() +/obj/item/weapon/card/id/synthetic/initialize() + . = ..() access = get_all_station_access() + access_synth /obj/item/weapon/card/id/centcom @@ -174,12 +170,12 @@ registered_name = "Central Command" assignment = "General" -/obj/item/weapon/card/id/centcom/New() +/obj/item/weapon/card/id/centcom/initialize() + . = ..() access = get_all_centcom_access() - ..() -/obj/item/weapon/card/id/centcom/station/New() - ..() +/obj/item/weapon/card/id/centcom/station/initialize() + . = ..() access |= get_all_station_access() /obj/item/weapon/card/id/centcom/ERT @@ -187,8 +183,8 @@ assignment = "Emergency Response Team" icon_state = "centcom" -/obj/item/weapon/card/id/centcom/ERT/New() - ..() +/obj/item/weapon/card/id/centcom/ERT/initialize() + . = ..() access |= get_all_station_access() // Department-flavor IDs 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 ce9e1c83a3..1cd5e9d712 100644 --- a/code/game/objects/items/weapons/id cards/syndicate_ids.dm +++ b/code/game/objects/items/weapons/id cards/syndicate_ids.dm @@ -6,12 +6,12 @@ var/electronic_warfare = 1 var/mob/registered_user = null -/obj/item/weapon/card/id/syndicate/New(mob/user as mob) - ..() +/obj/item/weapon/card/id/syndicate/initialize() + . = ..() access = syndicate_access.Copy() -/obj/item/weapon/card/id/syndicate/station_access/New() - ..() // Same as the normal Syndicate id, only already has all station access +/obj/item/weapon/card/id/syndicate/station_access/initialize() + . = ..() // Same as the normal Syndicate id, only already has all station access access |= get_all_station_access() /obj/item/weapon/card/id/syndicate/Destroy() diff --git a/code/game/objects/items/weapons/material/misc.dm b/code/game/objects/items/weapons/material/misc.dm index 1ab2e74730..97cf8b33db 100644 --- a/code/game/objects/items/weapons/material/misc.dm +++ b/code/game/objects/items/weapons/material/misc.dm @@ -8,17 +8,6 @@ force_divisor = 0.3 // 18 with hardness 60 (steel) attack_verb = list("jabbed","stabbed","ripped") -/obj/item/weapon/material/knuckledusters - name = "knuckle dusters" - desc = "A pair of brass knuckles. Generally used to enhance the user's punches." - icon_state = "knuckledusters" - gender = PLURAL - w_class = ITEMSIZE_SMALL - force_divisor = 0.63 - dulled_divisor = 0.75 //It's a heavy bit of metal - attack_verb = list("punched", "beaten", "struck") - applies_material_colour = 0 - /obj/item/weapon/material/knife/machete/hatchet name = "hatchet" desc = "A very sharp axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood." diff --git a/code/game/objects/items/weapons/material/twohanded.dm b/code/game/objects/items/weapons/material/twohanded.dm index 7aa29c7932..6631ec25fa 100644 --- a/code/game/objects/items/weapons/material/twohanded.dm +++ b/code/game/objects/items/weapons/material/twohanded.dm @@ -29,7 +29,7 @@ /obj/item/weapon/material/twohanded/update_held_icon() var/mob/living/M = loc - if(istype(M) && !issmall(M) && M.item_is_in_hands(src) && !M.hands_are_full()) + if(istype(M) && M.can_wield_item(src) && is_held_twohanded(M)) wielded = 1 force = force_wielded name = "[base_name] (wielded)" diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index 3df73b9793..8cc10444ef 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -10,6 +10,8 @@ * Candle Box * Crayon Box * Cigarette Box + * Vial Box + * Box of Chocolates */ /obj/item/weapon/storage/fancy/ @@ -313,3 +315,34 @@ /obj/item/weapon/storage/lockbox/vials/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() update_icon() + +/* + * Box of Chocolates/Heart Box + */ + +/obj/item/weapon/storage/fancy/heartbox + icon_state = "heartbox" + name = "box of chocolates" + var/startswith = 6 + max_storage_space = ITEMSIZE_COST_SMALL * 6 + can_hold = list( + /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece, + /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/white, + /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/truffle + ) + +/obj/item/weapon/storage/fancy/heartbox/New() + ..() + new /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece(src) + new /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece(src) + new /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece(src) + new /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/white(src) + new /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/white(src) + new /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/truffle(src) + update_icon() + return + +/obj/item/weapon/storage/fancy/heartbox/update_icon(var/itemremoved = 0) + if (contents.len == 0) + icon_state = "heartbox_empty" + return \ No newline at end of file diff --git a/code/game/objects/items/weapons/tape.dm b/code/game/objects/items/weapons/tape.dm index 04e5aa909b..30257a2b84 100644 --- a/code/game/objects/items/weapons/tape.dm +++ b/code/game/objects/items/weapons/tape.dm @@ -87,7 +87,7 @@ if(!can_place) return - if(!H || !src || !H.organs_by_name[BP_HEAD] || !H.has_eyes() || H.glasses || (H.head && (H.head.body_parts_covered & FACE))) + if(!H || !src || !H.organs_by_name[BP_HEAD] || !H.check_has_mouth() || (H.head && (H.head.body_parts_covered & FACE))) return user.visible_message("\The [user] has taped up \the [H]'s mouth!") diff --git a/code/game/objects/random/random.dm b/code/game/objects/random/random.dm index bffd520d32..6686950735 100644 --- a/code/game/objects/random/random.dm +++ b/code/game/objects/random/random.dm @@ -216,7 +216,7 @@ //prob(6);/obj/item/weapon/material/butterflyhandle, //prob(6);/obj/item/weapon/material/wirerod, prob(2);/obj/item/weapon/material/butterfly/switchblade, - prob(2);/obj/item/weapon/material/knuckledusters, + prob(2);/obj/item/clothing/gloves/knuckledusters, prob(1);/obj/item/weapon/material/knife/tacknife, prob(1);/obj/item/clothing/suit/storage/vest/heavy/merc, prob(1);/obj/item/weapon/beartrap, @@ -1133,4 +1133,18 @@ var/list/multi_point_spawns /obj/item/clothing/suit/space/void/mining/alt, /obj/item/clothing/head/helmet/space/void/mining/alt ) - ) \ No newline at end of file + ) + +/obj/random/landmine + name = "Random Land Mine" + desc = "This is a random land mine." + icon = 'icons/obj/weapons.dmi' + icon_state = "uglymine" + spawn_nothing_percentage = 25 + +/obj/random/landmine/item_to_spawn() + return pick(prob(30);/obj/effect/mine, + prob(25);/obj/effect/mine/frag, + prob(25);/obj/effect/mine/emp, + prob(10);/obj/effect/mine/stun, + prob(10);/obj/effect/mine/incendiary,) \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/l3closet.dm b/code/game/objects/structures/crates_lockers/closets/l3closet.dm index 7c54614aa7..4074230d8d 100644 --- a/code/game/objects/structures/crates_lockers/closets/l3closet.dm +++ b/code/game/objects/structures/crates_lockers/closets/l3closet.dm @@ -38,7 +38,7 @@ ..() new /obj/item/clothing/suit/bio_suit/security(src) new /obj/item/clothing/head/bio_hood/security(src) - + new /obj/item/weapon/gun/energy/taser/xeno/sec(src) /obj/structure/closet/l3closet/janitor icon_state = "bio_janitor" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index 02c53ad460..96a1b39477 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -10,7 +10,7 @@ req_access = list(access_medical) - New() +/obj/structure/closet/secure_closet/medical1/New() ..() new /obj/item/weapon/storage/box/autoinjectors(src) new /obj/item/weapon/storage/box/syringes(src) @@ -38,7 +38,7 @@ req_access = list(access_surgery) - New() +/obj/structure/closet/secure_closet/medical2/New() ..() new /obj/item/weapon/tank/anesthetic(src) new /obj/item/weapon/tank/anesthetic(src) @@ -60,63 +60,63 @@ icon_broken = "securemedbroken" icon_off = "securemedoff" - New() - ..() - if(prob(50)) - new /obj/item/weapon/storage/backpack/medic(src) - else - new /obj/item/weapon/storage/backpack/satchel/med(src) - if(prob(50)) - new /obj/item/weapon/storage/backpack/dufflebag/med(src) - new /obj/item/clothing/under/rank/nursesuit (src) - new /obj/item/clothing/head/nursehat (src) - switch(pick("blue", "green", "purple", "black", "navyblue")) - if ("blue") - new /obj/item/clothing/under/rank/medical/scrubs(src) - new /obj/item/clothing/head/surgery/blue(src) - if ("green") - new /obj/item/clothing/under/rank/medical/scrubs/green(src) - new /obj/item/clothing/head/surgery/green(src) - if ("purple") - new /obj/item/clothing/under/rank/medical/scrubs/purple(src) - new /obj/item/clothing/head/surgery/purple(src) - if ("black") - new /obj/item/clothing/under/rank/medical/scrubs/black(src) - new /obj/item/clothing/head/surgery/black(src) - if ("navyblue") - new /obj/item/clothing/under/rank/medical/scrubs/navyblue(src) - new /obj/item/clothing/head/surgery/navyblue(src) - switch(pick("blue", "green", "purple", "black", "navyblue")) - if ("blue") - new /obj/item/clothing/under/rank/medical/scrubs(src) - new /obj/item/clothing/head/surgery/blue(src) - if ("green") - new /obj/item/clothing/under/rank/medical/scrubs/green(src) - new /obj/item/clothing/head/surgery/green(src) - if ("purple") - new /obj/item/clothing/under/rank/medical/scrubs/purple(src) - new /obj/item/clothing/head/surgery/purple(src) - if ("black") - new /obj/item/clothing/under/rank/medical/scrubs/black(src) - new /obj/item/clothing/head/surgery/black(src) - if ("navyblue") - new /obj/item/clothing/under/rank/medical/scrubs/navyblue(src) - new /obj/item/clothing/head/surgery/navyblue(src) - new /obj/item/clothing/under/rank/medical(src) - new /obj/item/clothing/under/rank/nurse(src) - new /obj/item/clothing/under/rank/orderly(src) - new /obj/item/clothing/suit/storage/toggle/labcoat(src) - new /obj/item/clothing/suit/storage/toggle/fr_jacket(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/weapon/cartridge/medical(src) - new /obj/item/device/radio/headset/headset_med(src) - new /obj/item/device/radio/headset/headset_med/alt(src) - new /obj/item/clothing/suit/storage/hooded/wintercoat/medical(src) - new /obj/item/clothing/shoes/boots/winter/medical(src) - new /obj/item/weapon/storage/box/freezer(src) - new /obj/item/weapon/storage/box/freezer(src) - new /obj/item/weapon/storage/box/freezer(src) - return +/obj/structure/closet/secure_closet/medical3/New() + ..() + if(prob(50)) + new /obj/item/weapon/storage/backpack/medic(src) + else + new /obj/item/weapon/storage/backpack/satchel/med(src) + if(prob(50)) + new /obj/item/weapon/storage/backpack/dufflebag/med(src) + new /obj/item/clothing/under/rank/nursesuit (src) + new /obj/item/clothing/head/nursehat (src) + switch(pick("blue", "green", "purple", "black", "navyblue")) + if ("blue") + new /obj/item/clothing/under/rank/medical/scrubs(src) + new /obj/item/clothing/head/surgery/blue(src) + if ("green") + new /obj/item/clothing/under/rank/medical/scrubs/green(src) + new /obj/item/clothing/head/surgery/green(src) + if ("purple") + new /obj/item/clothing/under/rank/medical/scrubs/purple(src) + new /obj/item/clothing/head/surgery/purple(src) + if ("black") + new /obj/item/clothing/under/rank/medical/scrubs/black(src) + new /obj/item/clothing/head/surgery/black(src) + if ("navyblue") + new /obj/item/clothing/under/rank/medical/scrubs/navyblue(src) + new /obj/item/clothing/head/surgery/navyblue(src) + switch(pick("blue", "green", "purple", "black", "navyblue")) + if ("blue") + new /obj/item/clothing/under/rank/medical/scrubs(src) + new /obj/item/clothing/head/surgery/blue(src) + if ("green") + new /obj/item/clothing/under/rank/medical/scrubs/green(src) + new /obj/item/clothing/head/surgery/green(src) + if ("purple") + new /obj/item/clothing/under/rank/medical/scrubs/purple(src) + new /obj/item/clothing/head/surgery/purple(src) + if ("black") + new /obj/item/clothing/under/rank/medical/scrubs/black(src) + new /obj/item/clothing/head/surgery/black(src) + if ("navyblue") + new /obj/item/clothing/under/rank/medical/scrubs/navyblue(src) + new /obj/item/clothing/head/surgery/navyblue(src) + new /obj/item/clothing/under/rank/medical(src) + new /obj/item/clothing/under/rank/nurse(src) + new /obj/item/clothing/under/rank/orderly(src) + new /obj/item/clothing/suit/storage/toggle/labcoat(src) + new /obj/item/clothing/suit/storage/toggle/fr_jacket(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/weapon/cartridge/medical(src) + new /obj/item/device/radio/headset/headset_med(src) + new /obj/item/device/radio/headset/headset_med/alt(src) + new /obj/item/clothing/suit/storage/hooded/wintercoat/medical(src) + new /obj/item/clothing/shoes/boots/winter/medical(src) + new /obj/item/weapon/storage/box/freezer(src) + new /obj/item/weapon/storage/box/freezer(src) + new /obj/item/weapon/storage/box/freezer(src) + return /obj/structure/closet/secure_closet/paramedic name = "paramedic locker" @@ -130,7 +130,7 @@ req_access = list(access_medical_equip) - New() +/obj/structure/closet/secure_closet/paramedic/New() ..() new /obj/item/weapon/storage/backpack/dufflebag/emt(src) new /obj/item/weapon/storage/box/autoinjectors(src) @@ -167,51 +167,51 @@ icon_broken = "cmosecurebroken" icon_off = "cmosecureoff" - New() - ..() - if(prob(50)) - new /obj/item/weapon/storage/backpack/medic(src) - else - new /obj/item/weapon/storage/backpack/satchel/med(src) - if(prob(50)) - new /obj/item/weapon/storage/backpack/dufflebag/med(src) - new /obj/item/clothing/suit/bio_suit/cmo(src) - new /obj/item/clothing/head/bio_hood/cmo(src) - new /obj/item/clothing/shoes/white(src) - switch(pick("blue", "green", "purple", "black", "navyblue")) - if ("blue") - new /obj/item/clothing/under/rank/medical/scrubs(src) - new /obj/item/clothing/head/surgery/blue(src) - if ("green") - new /obj/item/clothing/under/rank/medical/scrubs/green(src) - new /obj/item/clothing/head/surgery/green(src) - if ("purple") - new /obj/item/clothing/under/rank/medical/scrubs/purple(src) - new /obj/item/clothing/head/surgery/purple(src) - if ("black") - new /obj/item/clothing/under/rank/medical/scrubs/black(src) - new /obj/item/clothing/head/surgery/black(src) - if ("navyblue") - new /obj/item/clothing/under/rank/medical/scrubs/navyblue(src) - new /obj/item/clothing/head/surgery/navyblue(src) - new /obj/item/clothing/under/rank/chief_medical_officer(src) - new /obj/item/clothing/under/rank/chief_medical_officer/skirt(src) - new /obj/item/clothing/suit/storage/toggle/labcoat/cmo(src) - new /obj/item/clothing/suit/storage/toggle/labcoat/cmoalt(src) - new /obj/item/weapon/cartridge/cmo(src) - new /obj/item/clothing/gloves/sterile/latex(src) - new /obj/item/clothing/shoes/brown (src) - new /obj/item/device/radio/headset/heads/cmo(src) - new /obj/item/device/radio/headset/heads/cmo/alt(src) - new /obj/item/device/flash(src) - new /obj/item/weapon/reagent_containers/hypospray/vial(src) - new /obj/item/weapon/reagent_containers/glass/beaker/vial(src) //VOREStation Edit - An extra vial for the hypo - new /obj/item/clothing/suit/storage/hooded/wintercoat/medical(src) - new /obj/item/clothing/shoes/boots/winter/medical(src) - new /obj/item/weapon/storage/box/freezer(src) - new /obj/item/clothing/mask/gas(src) - new /obj/item/taperoll/medical(src) - return +/obj/structure/closet/secure_closet/CMO/New() + ..() + if(prob(50)) + new /obj/item/weapon/storage/backpack/medic(src) + else + new /obj/item/weapon/storage/backpack/satchel/med(src) + if(prob(50)) + new /obj/item/weapon/storage/backpack/dufflebag/med(src) + new /obj/item/clothing/suit/bio_suit/cmo(src) + new /obj/item/clothing/head/bio_hood/cmo(src) + new /obj/item/clothing/shoes/white(src) + switch(pick("blue", "green", "purple", "black", "navyblue")) + if ("blue") + new /obj/item/clothing/under/rank/medical/scrubs(src) + new /obj/item/clothing/head/surgery/blue(src) + if ("green") + new /obj/item/clothing/under/rank/medical/scrubs/green(src) + new /obj/item/clothing/head/surgery/green(src) + if ("purple") + new /obj/item/clothing/under/rank/medical/scrubs/purple(src) + new /obj/item/clothing/head/surgery/purple(src) + if ("black") + new /obj/item/clothing/under/rank/medical/scrubs/black(src) + new /obj/item/clothing/head/surgery/black(src) + if ("navyblue") + new /obj/item/clothing/under/rank/medical/scrubs/navyblue(src) + new /obj/item/clothing/head/surgery/navyblue(src) + new /obj/item/clothing/under/rank/chief_medical_officer(src) + new /obj/item/clothing/under/rank/chief_medical_officer/skirt(src) + new /obj/item/clothing/suit/storage/toggle/labcoat/cmo(src) + new /obj/item/clothing/suit/storage/toggle/labcoat/cmoalt(src) + new /obj/item/weapon/cartridge/cmo(src) + new /obj/item/clothing/gloves/sterile/latex(src) + new /obj/item/clothing/shoes/brown (src) + new /obj/item/device/radio/headset/heads/cmo(src) + new /obj/item/device/radio/headset/heads/cmo/alt(src) + new /obj/item/device/flash(src) + new /obj/item/weapon/reagent_containers/hypospray/vial(src) + new /obj/item/weapon/reagent_containers/glass/beaker/vial(src) //VOREStation Edit - An extra vial for the hypo + new /obj/item/clothing/suit/storage/hooded/wintercoat/medical(src) + new /obj/item/clothing/shoes/boots/winter/medical(src) + new /obj/item/weapon/storage/box/freezer(src) + new /obj/item/clothing/mask/gas(src) + new /obj/item/taperoll/medical(src) + return @@ -220,7 +220,7 @@ req_access = list(access_surgery) - New() +/obj/structure/closet/secure_closet/animal/New() ..() new /obj/item/device/assembly/signaler(src) new /obj/item/device/radio/electropack(src) @@ -242,7 +242,7 @@ req_access = list(access_chemistry) - New() +/obj/structure/closet/secure_closet/chemical/New() ..() new /obj/item/clothing/under/rank/psych(src) new /obj/item/clothing/under/rank/psych/turtleneck(src) @@ -285,7 +285,7 @@ req_access = list(access_psychiatrist) - New() +/obj/structure/closet/secure_closet/psych/New() ..() new /obj/item/clothing/under/rank/psych(src) new /obj/item/clothing/under/rank/psych/turtleneck(src) @@ -333,9 +333,25 @@ /obj/structure/closet/secure_closet/medical_wall/pills name = "pill cabinet" - New() +/obj/structure/closet/secure_closet/medical_wall/pills/New() ..() new /obj/item/weapon/storage/pill_bottle/tramadol(src) new /obj/item/weapon/storage/pill_bottle/antitox(src) new /obj/item/weapon/storage/pill_bottle/carbon(src) - new /obj/random/medical/pillbottle(src) \ No newline at end of file + new /obj/random/medical/pillbottle(src) + return + +/obj/structure/closet/secure_closet/medical_wall/anesthetics + name = "anesthetics wall closet" + desc = "Used to knock people out." + req_access = list(access_surgery) + +/obj/structure/closet/secure_closet/medical_wall/anesthetics/New() + ..() + new /obj/item/weapon/tank/anesthetic(src) + new /obj/item/weapon/tank/anesthetic(src) + new /obj/item/weapon/tank/anesthetic(src) + new /obj/item/clothing/mask/breath/medical(src) + new /obj/item/clothing/mask/breath/medical(src) + new /obj/item/clothing/mask/breath/medical(src) + return \ No newline at end of file diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index f63290c010..87957b4d4d 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -320,3 +320,10 @@ if(2) name = "near finished " name += "[glass == 1 ? "window " : ""][istext(glass) ? "[glass] airlock" : base_name] assembly ([created_name])" + +// Airlock frames are indestructable, so bullets hitting them would always be stopped. +// To fix this, airlock assemblies will sometimes let bullets pass through, since generally the sprite shows them partially open. +/obj/structure/door_assembly/bullet_act(var/obj/item/projectile/P) + if(prob(40)) // Chance for the frame to let the bullet keep going. + return PROJECTILE_CONTINUE + return ..() diff --git a/code/game/objects/structures/flora/trees.dm b/code/game/objects/structures/flora/trees.dm index 872eea47d5..0c50bf189d 100644 --- a/code/game/objects/structures/flora/trees.dm +++ b/code/game/objects/structures/flora/trees.dm @@ -47,13 +47,19 @@ animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING) // Used when the tree gets hurt. -/obj/structure/flora/tree/proc/adjust_health(var/amount) +/obj/structure/flora/tree/proc/adjust_health(var/amount, var/is_ranged = FALSE) if(is_stump) return + // Bullets and lasers ruin some of the wood + if(is_ranged && product_amount > 0) + var/wood = initial(product_amount) + product_amount -= round(wood * (abs(amount)/max_health)) + health = between(0, health + amount, max_health) if(health <= 0) die() + return // Called when the tree loses all health, for whatever reason. /obj/structure/flora/tree/proc/die() @@ -81,6 +87,9 @@ /obj/structure/flora/tree/ex_act(var/severity) adjust_health(-(max_health / severity)) +/obj/structure/flora/tree/bullet_act(var/obj/item/projectile/Proj) + if(Proj.get_structure_damage()) + adjust_health(-Proj.get_structure_damage(), TRUE) /obj/structure/flora/tree/get_description_interaction() var/list/results = list() diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 50adbe393d..1c7beea412 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -104,7 +104,7 @@ playsound(src, W.usesound, 100, 1) anchored = !anchored user.visible_message("[user] [anchored ? "fastens" : "unfastens"] the grille.", \ - "You have [anchored ? "fastened the grille to" : "unfastened the grill from"] the floor.") + "You have [anchored ? "fastened the grille to" : "unfastened the grille from"] the floor.") return //window placing begin //TODO CONVERT PROPERLY TO MATERIAL DATUM diff --git a/code/game/objects/structures/loot_piles.dm b/code/game/objects/structures/loot_piles.dm index 5a655b6673..c9565dc90a 100644 --- a/code/game/objects/structures/loot_piles.dm +++ b/code/game/objects/structures/loot_piles.dm @@ -522,3 +522,50 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh /obj/item/clothing/suit/armor/alien/tank, /obj/item/clothing/head/helmet/alien/tank, ) + +/obj/structure/loot_pile/surface/bones + name = "bone pile" + desc = "A pile of various dusty bones. Your graverobbing instincts tell you there might be valuables here." + icon = 'icons/obj/bones.dmi' + icon_state = "bonepile" + delete_on_depletion = TRUE + + common_loot = list( + /obj/item/weapon/bone, + /obj/item/weapon/bone/skull, + /obj/item/weapon/bone/skull/tajaran, + /obj/item/weapon/bone/skull/unathi, + /obj/item/weapon/bone/skull/unknown, + /obj/item/weapon/bone/leg, + /obj/item/weapon/bone/arm, + /obj/item/weapon/bone/ribs, + ) + uncommon_loot = list( + /obj/item/weapon/coin/gold, + /obj/item/weapon/coin/silver, + /obj/item/weapon/deck/tarot, + /obj/item/weapon/flame/lighter/zippo/gold, + /obj/item/weapon/flame/lighter/zippo/black, + /obj/item/weapon/material/knife/tacknife/survival, + /obj/item/weapon/material/knife/tacknife/combatknife, + /obj/item/weapon/material/knife/machete/hatchet, + /obj/item/weapon/material/knife/butch, + /obj/item/weapon/storage/wallet/random, + /obj/item/clothing/accessory/bracelet/material/gold, + /obj/item/clothing/accessory/bracelet/material/silver, + /obj/item/clothing/accessory/locket, + /obj/item/clothing/accessory/poncho/blue, + /obj/item/clothing/shoes/boots/cowboy, + /obj/item/clothing/suit/storage/toggle/bomber, + /obj/item/clothing/under/frontier, + /obj/item/clothing/under/overalls, + /obj/item/clothing/under/pants/classicjeans/ripped, + /obj/item/clothing/under/sl_suit + ) + rare_loot = list( + /obj/item/weapon/storage/belt/utility/alien/full, + /obj/item/weapon/gun/projectile/revolver, + /obj/item/weapon/gun/projectile/sec, + /obj/item/weapon/gun/launcher/crossbow + ) + diff --git a/code/game/objects/structures/snowman.dm b/code/game/objects/structures/snowman.dm new file mode 100644 index 0000000000..b3947621b9 --- /dev/null +++ b/code/game/objects/structures/snowman.dm @@ -0,0 +1,24 @@ +/obj/structure/snowman + name = "snowman" + icon = 'icons/obj/snowman.dmi' + icon_state = "snowman" + desc = "A happy little snowman smiles back at you!" + anchored = 1 + +/obj/structure/snowman/attack_hand(mob/user as mob) + if(user.a_intent == I_HURT) + user << "In one hit, [src] easily crumples into a pile of snow. You monster." + var/turf/simulated/floor/F = get_turf(src) + if (istype(F)) + new /obj/item/stack/material/snow(F) + qdel(src) + +/obj/structure/snowman/borg + name = "snowborg" + icon_state = "snowborg" + desc = "A snowy little robot. It even has a monitor for a head." + +/obj/structure/snowman/spider + name = "snow spider" + icon_state = "snowspider" + desc = "An impressively crafted snow spider. Not nearly as creepy as the real thing." \ No newline at end of file diff --git a/code/game/turfs/simulated/wall_types.dm b/code/game/turfs/simulated/wall_types.dm index b3b1ec8c8b..d6eb1578b7 100644 --- a/code/game/turfs/simulated/wall_types.dm +++ b/code/game/turfs/simulated/wall_types.dm @@ -23,6 +23,10 @@ ..(newloc,"gold") /turf/simulated/wall/silver/New(var/newloc) ..(newloc,"silver") +/turf/simulated/wall/lead/New(var/newloc) + ..(newloc,"lead") +/turf/simulated/wall/r_lead/New(var/newloc) + ..(newloc,"lead", "lead") /turf/simulated/wall/phoron/New(var/newloc) ..(newloc,"phoron") /turf/simulated/wall/sandstone/New(var/newloc) @@ -35,6 +39,8 @@ ..(newloc,"silver","gold") /turf/simulated/wall/sandstonediamond/New(var/newloc) ..(newloc,"sandstone","diamond") +/turf/simulated/wall/snowbrick/New(var/newloc) + ..(newloc,"packed snow") // Kind of wondering if this is going to bite me in the butt. /turf/simulated/wall/skipjack/New(var/newloc) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 4293fe224b..d9c4efae46 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -60,7 +60,6 @@ var/list/admin_verbs_admin = list( /client/proc/check_antagonists, /client/proc/admin_memo, //admin memo system. show/delete/write. +SERVER needed to delete admin memos of others, /client/proc/dsay, //talk in deadchat using our ckey/fakekey, - /client/proc/ghost_view, //let us see ghosts WHENEVERRRR // /client/proc/toggle_hear_deadcast, //toggles whether we hear deadchat, /client/proc/investigate_show, //various admintools for investigation. Such as a singulo grief-log, /client/proc/secrets, @@ -217,7 +216,6 @@ var/list/admin_verbs_debug = list( /client/proc/jumptomob, /client/proc/jumptocoord, /client/proc/dsay, - /client/proc/ghost_view, /client/proc/toggle_debug_logs, /client/proc/admin_ghost, //allows us to ghost/reenter body at will, /datum/admins/proc/view_runtimes, @@ -332,7 +330,6 @@ var/list/admin_verbs_mod = list( /datum/admins/proc/show_player_info, /client/proc/player_panel_new, /client/proc/dsay, - /client/proc/ghost_view, /datum/admins/proc/show_skills, /datum/admins/proc/show_player_panel, /client/proc/check_antagonists, @@ -357,7 +354,6 @@ var/list/admin_verbs_event_manager = list( /client/proc/admin_ghost, /datum/admins/proc/show_player_info, /client/proc/dsay, - /client/proc/ghost_view, /client/proc/cmd_admin_subtle_message, /client/proc/debug_variables, /client/proc/check_antagonists, @@ -497,26 +493,6 @@ var/list/admin_verbs_event_manager = list( body.key = "@[key]" //Haaaaaaaack. But the people have spoken. If it breaks; blame adminbus feedback_add_details("admin_verb","O") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/ghost_view() - set category = "Admin" - set name = "Ghost View" - set desc = "Toggles ability to see ghosts, even while in a mob." - if(!holder) return - if(!mob.plane_holder) return - - var/choice = alert(src,"Do you want to see ghosts, or not?","Ghost viewing","Show 'em!","Cancel","Hide 'em!") - if(choice == "Cancel") - return - - if(choice == "Show 'em!" && mob.plane_holder) - mob.plane_holder.set_vis(VIS_GHOSTS,TRUE) - usr.see_invisible = SEE_INVISIBLE_CULT - to_chat(src,"Ghosts are now visible (while in this mob).") - else if(mob.plane_holder) - mob.plane_holder.set_vis(VIS_GHOSTS,FALSE) - usr.see_invisible = initial(mob.see_invisible) - to_chat(src,"Ghosts are now hidden (while in this mob).") - /client/proc/invisimin() set name = "Invisimin" set category = "Admin" diff --git a/code/modules/alarm/alarm.dm b/code/modules/alarm/alarm.dm index d0a6a8be4c..26ffdade04 100644 --- a/code/modules/alarm/alarm.dm +++ b/code/modules/alarm/alarm.dm @@ -23,12 +23,13 @@ var/area/last_name //The last acquired name, used should origin be lost var/area/last_camera_area //The last area in which cameras where fetched, used to see if the camera list should be updated. var/end_time //Used to set when this alarm should clear, in case the origin is lost. + var/hidden = FALSE //If this alarm can be seen from consoles or other things. -/datum/alarm/New(var/atom/origin, var/atom/source, var/duration, var/severity) +/datum/alarm/New(var/atom/origin, var/atom/source, var/duration, var/severity, var/hidden) src.origin = origin cameras() // Sets up both cameras and last alarm area. - set_source_data(source, duration, severity) + set_source_data(source, duration, severity, hidden) /datum/alarm/proc/process() // Has origin gone missing? @@ -43,17 +44,19 @@ AS.duration = 0 AS.end_time = world.time + ALARM_RESET_DELAY -/datum/alarm/proc/set_source_data(var/atom/source, var/duration, var/severity) +/datum/alarm/proc/set_source_data(var/atom/source, var/duration, var/severity, var/hidden) var/datum/alarm_source/AS = sources_assoc[source] if(!AS) AS = new/datum/alarm_source(source) sources += AS sources_assoc[source] = AS + src.hidden = hidden // Currently only non-0 durations can be altered (normal alarms VS EMP blasts) if(AS.duration) duration = SecondsToTicks(duration) AS.duration = duration AS.severity = severity + src.hidden = min(src.hidden, hidden) /datum/alarm/proc/clear(var/source) var/datum/alarm_source/AS = sources_assoc[source] diff --git a/code/modules/alarm/alarm_handler.dm b/code/modules/alarm/alarm_handler.dm index afa45d7649..a07ca8bd3b 100644 --- a/code/modules/alarm/alarm_handler.dm +++ b/code/modules/alarm/alarm_handler.dm @@ -12,7 +12,7 @@ A.process() check_alarm_cleared(A) -/datum/alarm_handler/proc/triggerAlarm(var/atom/origin, var/atom/source, var/duration = 0, var/severity = 1) +/datum/alarm_handler/proc/triggerAlarm(var/atom/origin, var/atom/source, var/duration = 0, var/severity = 1, var/hidden = 0) var/new_alarm //Proper origin and source mandatory if(!(origin && source)) @@ -23,9 +23,9 @@ //see if there is already an alarm of this origin var/datum/alarm/existing = alarms_assoc[origin] if(existing) - existing.set_source_data(source, duration, severity) + existing.set_source_data(source, duration, severity, hidden) else - existing = new/datum/alarm(origin, source, duration, severity) + existing = new/datum/alarm(origin, source, duration, severity, hidden) new_alarm = 1 alarms |= existing @@ -48,10 +48,10 @@ return check_alarm_cleared(existing) /datum/alarm_handler/proc/major_alarms() - return alarms + return visible_alarms() /datum/alarm_handler/proc/minor_alarms() - return alarms + return visible_alarms() /datum/alarm_handler/proc/check_alarm_cleared(var/datum/alarm/alarm) if ((alarm.end_time && world.time > alarm.end_time) || !alarm.sources.len) @@ -63,7 +63,7 @@ /datum/alarm_handler/proc/on_alarm_change(var/datum/alarm/alarm, var/was_raised) for(var/obj/machinery/camera/C in alarm.cameras()) - if(was_raised) + if(was_raised && !alarm.hidden) C.add_network(category) else C.remove_network(category) @@ -95,3 +95,10 @@ /datum/alarm_handler/proc/notify_listeners(var/alarm, var/was_raised) for(var/listener in listeners) call(listener, listeners[listener])(src, alarm, was_raised) + +/datum/alarm_handler/proc/visible_alarms() + var/list/visible_alarms = new() + for(var/datum/alarm/A in alarms) + if(!A.hidden) + visible_alarms.Add(A) + return visible_alarms \ No newline at end of file diff --git a/code/modules/alarm/atmosphere_alarm.dm b/code/modules/alarm/atmosphere_alarm.dm index 04403ab4a7..fc0fe92ee4 100644 --- a/code/modules/alarm/atmosphere_alarm.dm +++ b/code/modules/alarm/atmosphere_alarm.dm @@ -1,19 +1,16 @@ /datum/alarm_handler/atmosphere category = "Atmosphere Alarms" -/datum/alarm_handler/atmosphere/triggerAlarm(var/atom/origin, var/atom/source, var/duration = 0, var/severity = 1) - ..() - /datum/alarm_handler/atmosphere/major_alarms() var/list/major_alarms = new() - for(var/datum/alarm/A in alarms) + for(var/datum/alarm/A in visible_alarms()) if(A.max_severity() > 1) major_alarms.Add(A) return major_alarms /datum/alarm_handler/atmosphere/minor_alarms() var/list/minor_alarms = new() - for(var/datum/alarm/A in alarms) + for(var/datum/alarm/A in visible_alarms()) if(A.max_severity() == 1) minor_alarms.Add(A) return minor_alarms diff --git a/code/modules/client/preference_setup/loadout/loadout_suit.dm b/code/modules/client/preference_setup/loadout/loadout_suit.dm index 0208c234d4..76bbebcc3f 100644 --- a/code/modules/client/preference_setup/loadout/loadout_suit.dm +++ b/code/modules/client/preference_setup/loadout/loadout_suit.dm @@ -181,27 +181,22 @@ /datum/gear/suit/roles/poncho/security display_name = "poncho, security" path = /obj/item/clothing/accessory/poncho/roles/security - allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer") /datum/gear/suit/roles/poncho/medical display_name = "poncho, medical" path = /obj/item/clothing/accessory/poncho/roles/medical - allowed_roles = list("Medical Doctor","Chief Medical Officer","Chemist","Paramedic","Geneticist", "Psychiatrist") /datum/gear/suit/roles/poncho/engineering display_name = "poncho, engineering" path = /obj/item/clothing/accessory/poncho/roles/engineering - allowed_roles = list("Chief Engineer","Atmospheric Technician", "Station Engineer") /datum/gear/suit/roles/poncho/science display_name = "poncho, science" path = /obj/item/clothing/accessory/poncho/roles/science - allowed_roles = list("Research Director","Scientist", "Roboticist", "Xenobiologist") /datum/gear/suit/roles/poncho/cargo display_name = "poncho, cargo" path = /obj/item/clothing/accessory/poncho/roles/cargo - allowed_roles = list("Quartermaster","Cargo Technician") /datum/gear/suit/roles/poncho/cloak/hos display_name = "cloak, head of security" diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm index b86471bf84..b0fe0ae096 100644 --- a/code/modules/clothing/chameleon.dm +++ b/code/modules/clothing/chameleon.dm @@ -430,6 +430,7 @@ P.icon = initial(copy_projectile.icon) P.icon_state = initial(copy_projectile.icon_state) P.pass_flags = initial(copy_projectile.pass_flags) + P.fire_sound = initial(copy_projectile.fire_sound) P.hitscan = initial(copy_projectile.hitscan) P.step_delay = initial(copy_projectile.step_delay) P.muzzle_type = initial(copy_projectile.muzzle_type) @@ -451,12 +452,15 @@ var/obj/item/weapon/gun/copy = ..() flags_inv = copy.flags_inv - fire_sound = copy.fire_sound + if(copy.fire_sound) + fire_sound = copy.fire_sound + else + fire_sound = null fire_sound_text = copy.fire_sound_text - var/obj/item/weapon/gun/energy/E = copy - if(istype(E)) - copy_projectile = E.projectile_type + var/obj/item/weapon/gun/G = copy + if(istype(G)) + copy_projectile = G.projectile_type //charge_meter = E.charge_meter //does not work very well with icon_state changes, ATM else copy_projectile = null diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 538bc56299..d03a5330b6 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -66,10 +66,10 @@ if(H.species) if(exclusive) - if(!(H.species.get_bodytype(H) in species_restricted)) //Vorestation edit + if(!(H.species.get_bodytype(H) in species_restricted)) wearable = 1 else - if(H.species.get_bodytype(H) in species_restricted) //Vorestation edit + if(H.species.get_bodytype(H) in species_restricted) wearable = 1 if(!wearable && !(slot in list(slot_l_store, slot_r_store, slot_s_store))) @@ -202,8 +202,10 @@ var/fingerprint_chance = 0 //How likely the glove is to let fingerprints through var/obj/item/clothing/gloves/ring = null //Covered ring var/mob/living/carbon/human/wearer = null //Used for covered rings when dropping - var/glove_level = 2 //What "layer" the glove is on - var/overgloves = 0 //Used by gauntlets and arm_guards + var/glove_level = 2 //What "layer" the glove is on + var/overgloves = 0 //Used by gauntlets and arm_guards + var/punch_force = 0 //How much damage do these gloves add to a punch? + var/punch_damtype = BRUTE //What type of damage does this make fists be? body_parts_covered = HANDS slot_flags = SLOT_GLOVES attack_verb = list("challenged") @@ -251,7 +253,7 @@ var/mob/living/carbon/human/H = user if(slot && slot == slot_gloves) - if(istype(H.gloves, /obj/item/clothing/gloves/ring)) + if(H.gloves) ring = H.gloves if(ring.glove_level >= src.glove_level) to_chat(user, "You are unable to wear \the [src] as \the [H.gloves] are in the way.") @@ -261,6 +263,8 @@ H.drop_from_inventory(ring) //Remove the ring (or other under-glove item in the hand slot?) so you can put on the gloves. ring.forceMove(src) to_chat(user, "You slip \the [src] on over \the [src.ring].") + if(!(flags & THICKMATERIAL)) + punch_force += ring.punch_force else ring = null @@ -268,6 +272,7 @@ if(ring) //Put the ring back on if the check fails. if(H.equip_to_slot_if_possible(ring, slot_gloves)) src.ring = null + punch_force = initial(punch_force) return 0 wearer = H //TODO clean this when magboots are cleaned @@ -284,6 +289,7 @@ if(!H.equip_to_slot_if_possible(ring, slot_gloves)) ring.forceMove(get_turf(src)) src.ring = null + punch_force = initial(punch_force) wearer = null ///////////////////////////////////////////////////////////////////// @@ -298,6 +304,7 @@ siemens_coefficient = 1 glove_level = 1 fingerprint_chance = 100 + punch_force = 2 /////////////////////////////////////////////////////////////////////// //Head diff --git a/code/modules/clothing/gloves/arm_guards.dm b/code/modules/clothing/gloves/arm_guards.dm index 80a5cfd735..84f364e4d5 100644 --- a/code/modules/clothing/gloves/arm_guards.dm +++ b/code/modules/clothing/gloves/arm_guards.dm @@ -3,6 +3,7 @@ desc = "These arm guards will protect your hands and arms." body_parts_covered = HANDS|ARMS overgloves = 1 + punch_force = 3 w_class = ITEMSIZE_NORMAL /obj/item/clothing/gloves/arm_guard/mob_can_equip(var/mob/living/carbon/human/H, slot) diff --git a/code/modules/clothing/gloves/gauntlets.dm b/code/modules/clothing/gloves/gauntlets.dm index bc65252d38..b65884d3f9 100644 --- a/code/modules/clothing/gloves/gauntlets.dm +++ b/code/modules/clothing/gloves/gauntlets.dm @@ -11,6 +11,7 @@ desc = "These gloves go over regular gloves." glove_level = 3 overgloves = 1 + punch_force = 5 var/obj/item/clothing/gloves/gloves = null //Undergloves /obj/item/clothing/gloves/gauntlets/mob_can_equip(mob/user) diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm index 27db4424d7..7546d81651 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -95,6 +95,7 @@ icon_state = "work" item_state = "wgloves" force = 5 + punch_force = 3 siemens_coefficient = 0.75 permeability_coefficient = 0.05 armor = list(melee = 30, bullet = 10, laser = 10, energy = 15, bomb = 20, bio = 0, rad = 0) @@ -114,3 +115,15 @@ min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE + +/obj/item/clothing/gloves/knuckledusters + name = "knuckle dusters" + desc = "A pair of brass knuckles. Generally used to enhance the user's punches." + icon_state = "knuckledusters" + attack_verb = list("punched", "beaten", "struck") + flags = THICKMATERIAL // Stops rings from increasing hit strength + siemens_coefficient = 1 + fingerprint_chance = 100 + overgloves = 1 + force = 5 + punch_force = 5 diff --git a/code/modules/clothing/spacesuits/void/station.dm b/code/modules/clothing/spacesuits/void/station.dm index 57df9d7c0a..0fb184ad49 100644 --- a/code/modules/clothing/spacesuits/void/station.dm +++ b/code/modules/clothing/spacesuits/void/station.dm @@ -155,15 +155,15 @@ name = "streamlined medical voidsuit helmet" desc = "A trendy, lightly radiation-shielded voidsuit helmet trimmed in a sleek blue." icon_state = "rig0-medicalalt" - armor = list(melee = 30, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 80) + armor = list(melee = 20, bullet = 5, laser = 20,energy = 5, bomb = 15, bio = 100, rad = 30) light_overlay = "helmet_light_dual_blue" /obj/item/clothing/suit/space/void/medical/alt icon_state = "rig-medicalalt" name = "streamlined medical voidsuit" - desc = "A more recent model of Vey-Med voidsuit, featuring the latest in radiation shielding technology, without sacrificing comfort or style." + desc = "A more recent model of Vey-Med voidsuit, exchanging physical protection for fully unencumbered movement and a complete range of motion." slowdown = 0 - armor = list(melee = 30, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 80) + armor = list(melee = 20, bullet = 5, laser = 20,energy = 5, bomb = 15, bio = 100, rad = 30) //Security /obj/item/clothing/head/helmet/space/void/security @@ -243,4 +243,4 @@ icon_state = "rig-atmosalt" name = "heavy duty atmos voidsuit" armor = list(melee = 20, bullet = 5, laser = 20,energy = 15, bomb = 45, bio = 100, rad = 50) - max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE \ No newline at end of file + max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 5ecef18d7d..5a3483f9c7 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -798,9 +798,6 @@ obj/item/clothing/suit/storage/toggle/peacoat name = "explorer hood" desc = "An armoured hood for exploring harsh environments." icon_state = "explorer" - brightness_on = 3 - light_overlay = "hood_light" - action_button_name = "Toggle Head-light" body_parts_covered = HEAD cold_protection = HEAD flags = THICKMATERIAL diff --git a/code/modules/clothing/under/solgov.dm b/code/modules/clothing/under/solgov.dm index 5f5cdb52f0..39109c480a 100644 --- a/code/modules/clothing/under/solgov.dm +++ b/code/modules/clothing/under/solgov.dm @@ -36,6 +36,7 @@ desc = "A comfortable turtleneck and black utility trousers." icon_state = "blackutility" worn_state = "blackutility" + rolled_sleeves = 0 armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) siemens_coefficient = 0.9 diff --git a/code/modules/lore_codex/codex.dm b/code/modules/lore_codex/codex.dm index 3abaf58fec..42987628ae 100644 --- a/code/modules/lore_codex/codex.dm +++ b/code/modules/lore_codex/codex.dm @@ -29,6 +29,7 @@ name = "Daedalus Pocket Newscaster" desc = "A regularly-updating compendium of articles on current events. Essential for new arrivals in the Vir system and anyone interested in politics." icon_state = "newscodex" + w_class = ITEMSIZE_SMALL root_type = /datum/lore/codex/category/main_news /* //VORESTATION REMOVAL @@ -40,4 +41,4 @@ icon_state = "corp_regs" root_type = /datum/lore/codex/category/main_corp_regs throwforce = 5 // Throw the book at 'em. -*/ \ No newline at end of file +*/ diff --git a/code/modules/lore_codex/news_data/main.dm b/code/modules/lore_codex/news_data/main.dm index fec4ae7c3e..f4634bdfd5 100644 --- a/code/modules/lore_codex/news_data/main.dm +++ b/code/modules/lore_codex/news_data/main.dm @@ -6,6 +6,7 @@ children = list( /datum/lore/codex/page/article1, /datum/lore/codex/page/article2, + /datum/lore/codex/page/article3, /datum/lore/codex/page/about_news, ) @@ -46,3 +47,11 @@ incident \"shocking, if the allegations are to be believed\" and has assured shareholders that Nanotrasen will respond to the \ incident with as much force as it warrents.

Requests for a statement directed to the Board of Trustees or Dr. Harper were \ not responded to. Free Traders are recommended to stay clear of the region until the situation resolves itself." + +/datum/lore/codex/page/article3 + name = "2/10/62-- Aetolian Partisans Declare Independence" + data = "Breaking their week-long silence, the leaders of the Aetolian Coup, and their spokesperson and presumed leader Naomi Harper issued an address earlier today, delivered to the Oculum Broadcast office on Pearl by drone courier. Quote Dr. Harper: \"Our previous silence was a necessity, while we consolidated our forces and dealt with corporatists both internally and in Vounna's former Grayson outposts.\". In Harper's hour-long address, she berates the failure of SolGov to provide adequate protections for Prometheans. \"We will not let the Promethean be another positronic brain; they will not labor under a century of slavery, deprived of a state to call their own. The Luddites of the Friends and of the Icarus Front will not be permitted to decide the fate of a nascent race before it begins.\"\ +

\ + Harper proceeded to unilaterally declare Vounna's independence from SolGov, claiming sovereignty over the system as the first Chairperson of the \"Aetolian Council\". Speaker of the Shadow Coalition ISA-5 has urged their government to treat the developing situation with caution but decried Harper's rhetoric, stating in a press release, \"While I know well the injustices visited on myself and my people by misguided forbearers, it is important to treat any emerging technology with respect. Current policies regarding the Prometheans are designed to limit risk during sociological trials on Aetolus and beyond. As for myself, I doubt the sincerity of this human who claims to speak for the Prometheans, when the Prometheans are perfectly equipped to speak for themselves.\"\ +

\ + NanoTrasen is expected to redouble their Promethean research programs in the Vir system until stability is restored to Vounna." diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index 6a10383f76..bb5a4674f4 100644 --- a/code/modules/materials/material_recipes.dm +++ b/code/modules/materials/material_recipes.dm @@ -167,4 +167,19 @@ /material/snow/generate_recipes() recipes = list() - recipes += new/datum/stack_recipe("snowball", /obj/item/weapon/material/snow/snowball, 1, time = 10) \ No newline at end of file + recipes += new/datum/stack_recipe("snowball", /obj/item/weapon/material/snow/snowball, 1, time = 10) + recipes += new/datum/stack_recipe("snow brick", /obj/item/stack/material/snowbrick, 2, time = 10) + recipes += new/datum/stack_recipe("snowman", /obj/structure/snowman, 2, time = 15) + recipes += new/datum/stack_recipe("snow robot", /obj/structure/snowman/borg, 2, time = 10) + recipes += new/datum/stack_recipe("snow spider", /obj/structure/snowman/spider, 3, time = 20) + +/material/snowbrick/generate_recipes() + recipes = list() + recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") + recipes += new/datum/stack_recipe("[display_name] barricade", /obj/structure/barricade, 5, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") + recipes += new/datum/stack_recipe("[display_name] stool", /obj/item/weapon/stool, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") + recipes += new/datum/stack_recipe("[display_name] chair", /obj/structure/bed/chair, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") + recipes += new/datum/stack_recipe("[display_name] bed", /obj/structure/bed, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") + recipes += new/datum/stack_recipe("[display_name] double bed", /obj/structure/bed/double, 4, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") + recipes += new/datum/stack_recipe("[display_name] wall girders", /obj/structure/girder, 2, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") + recipes += new/datum/stack_recipe("[display_name] ashtray", /obj/item/weapon/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") \ No newline at end of file diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm index d212851071..54d56fd773 100644 --- a/code/modules/materials/material_sheets.dm +++ b/code/modules/materials/material_sheets.dm @@ -269,10 +269,16 @@ /obj/item/stack/material/snow name = "snow" - desc = "The temptation to build a snowfort rises." + desc = "The temptation to build a snowman rises." icon_state = "sheet-snow" default_type = "snow" +/obj/item/stack/material/snowbrick + name = "snow brick" + desc = "For all of your igloo building needs." + icon_state = "sheet-snowbrick" + default_type = "packed snow" + /obj/item/stack/material/leather name = "leather" desc = "The by-product of mob grinding." diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index 2fa2b1dbbe..9137fb416c 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -99,7 +99,7 @@ var/list/name_to_material var/conductivity = null // How conductive the material is. Iron acts as the baseline, at 10. var/list/composite_material // If set, object matter var will be a list containing these values. var/luminescence - var/radiation_resistance = 20 // Radiation resistance, used in calculating how much radiation a material absorbs. Equivlent to weight, but does not affect weaponry. + var/radiation_resistance = 0 // Radiation resistance, which is added on top of a material's weight for blocking radiation. Needed to make lead special without superrobust weapons. // Placeholder vars for the time being, todo properly integrate windows/light tiles/rods. var/created_window @@ -237,7 +237,6 @@ var/list/name_to_material weight = 22 stack_origin_tech = list(TECH_MATERIAL = 5) door_icon_base = "stone" - radiation_resistance = 80 //dense, so it's okay-ish as rad shielding. /material/diamond name = "diamond" @@ -263,7 +262,6 @@ var/list/name_to_material stack_origin_tech = list(TECH_MATERIAL = 4) sheet_singular_name = "ingot" sheet_plural_name = "ingots" - radiation_resistance = 120 //gold is dense. /material/gold/bronze //placeholder for ashtrays name = "bronze" @@ -279,7 +277,7 @@ var/list/name_to_material stack_origin_tech = list(TECH_MATERIAL = 3) sheet_singular_name = "ingot" sheet_plural_name = "ingots" - radiation_resistance = 22 + //R-UST port /material/supermatter name = "supermatter" @@ -340,7 +338,6 @@ var/list/name_to_material door_icon_base = "stone" sheet_singular_name = "brick" sheet_plural_name = "bricks" - radiation_resistance = 22 /material/stone/marble name = "marble" @@ -349,7 +346,7 @@ var/list/name_to_material hardness = 100 integrity = 201 //hack to stop kitchen benches being flippable, todo: refactor into weight system stack_type = /obj/item/stack/material/marble - radiation_resistance = 26 + /material/steel name = DEFAULT_WALL_MATERIAL @@ -396,7 +393,7 @@ var/list/name_to_material conductivity = 13 // For the purposes of balance. stack_origin_tech = list(TECH_MATERIAL = 2) composite_material = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT, "platinum" = SHEET_MATERIAL_AMOUNT) //todo - radiation_resistance = 60 //Plasteel is presumably dense and is the dominant material used in the engine. Still not great. + // Very rare alloy that is reflective, should be used sparingly. /material/durasteel @@ -414,7 +411,6 @@ var/list/name_to_material reflectivity = 0.7 // Not a perfect mirror, but close. stack_origin_tech = list(TECH_MATERIAL = 8) composite_material = list("plasteel" = SHEET_MATERIAL_AMOUNT, "diamond" = SHEET_MATERIAL_AMOUNT) //shrug - radiation_resistance = 120 //it reflects XRAY LASERS. /material/plasteel/titanium name = "titanium" @@ -443,7 +439,6 @@ var/list/name_to_material window_options = list("One Direction" = 1, "Full Window" = 4, "Windoor" = 2) created_window = /obj/structure/window/basic rod_product = /obj/item/stack/material/glass/reinforced - radiation_resistance = 15 /material/glass/build_windows(var/mob/living/user, var/obj/item/stack/used_stack) @@ -535,7 +530,6 @@ var/list/name_to_material created_window = /obj/structure/window/reinforced wire_product = null rod_product = null - radiation_resistance = 30 /material/glass/phoron name = "borosilicate glass" @@ -563,7 +557,6 @@ var/list/name_to_material stack_origin_tech = list(TECH_MATERIAL = 2) composite_material = list() //todo rod_product = null - radiation_resistance = 30 /material/plastic name = "plastic" @@ -578,7 +571,6 @@ var/list/name_to_material conductivity = 2 // For the sake of material armor diversity, we're gonna pretend this plastic is a good insulator. melting_point = T0C+371 //assuming heat resistant plastic stack_origin_tech = list(TECH_MATERIAL = 3) - radiation_resistance = 12 /material/plastic/holographic name = "holoplastic" @@ -629,7 +621,6 @@ var/list/name_to_material stack_origin_tech = list(TECH_MATERIAL = 2) sheet_singular_name = "ingot" sheet_plural_name = "ingots" - radiation_resistance = 27 /material/iron name = "iron" @@ -639,17 +630,16 @@ var/list/name_to_material conductivity = 10 sheet_singular_name = "ingot" sheet_plural_name = "ingots" - radiation_resistance = 22 /material/lead name = "lead" stack_type = /obj/item/stack/material/lead icon_colour = "#273956" - weight = 35 + weight = 23 // Lead is a bit more dense than silver IRL, and silver has 22 ingame. conductivity = 10 sheet_singular_name = "ingot" sheet_plural_name = "ingots" - radiation_resistance = 350 //actual radiation shielding, yay... + radiation_resistance = 25 // Lead is Special and so gets to block more radiation than it normally would with just weight, totalling in 48 protection. // Adminspawn only, do not let anyone get this. /material/alienalloy @@ -663,7 +653,6 @@ var/list/name_to_material hardness = 500 weight = 500 protectiveness = 80 // 80% - radiation_resistance = 500 // Likewise. /material/alienalloy/elevatorium @@ -721,7 +710,6 @@ var/list/name_to_material destruction_desc = "splinters" sheet_singular_name = "plank" sheet_plural_name = "planks" - radiation_resistance = 18 /material/wood/log name = MAT_LOG @@ -765,6 +753,7 @@ var/list/name_to_material door_icon_base = "wood" destruction_desc = "crumples" radiation_resistance = 1 + /material/snow name = MAT_SNOW stack_type = /obj/item/stack/material/snow @@ -782,6 +771,25 @@ var/list/name_to_material sheet_singular_name = "pile" sheet_plural_name = "pile" //Just a bigger pile radiation_resistance = 1 + +/material/snowbrick //only slightly stronger than snow, used to make igloos mostly + name = "packed snow" + flags = MATERIAL_BRITTLE + stack_type = /obj/item/stack/material/snowbrick + icon_base = "stone" + icon_reinf = "reinf_stone" + icon_colour = "#D8FDFF" + integrity = 50 + weight = 2 + hardness = 2 + protectiveness = 0 // 0% + stack_origin_tech = list(TECH_MATERIAL = 1) + melting_point = T0C+1 + destruction_desc = "crumbles" + sheet_singular_name = "brick" + sheet_plural_name = "bricks" + radiation_resistance = 1 + /material/cloth //todo name = "cloth" stack_origin_tech = list(TECH_MATERIAL = 2) diff --git a/code/modules/mob/_modifiers/cloning.dm b/code/modules/mob/_modifiers/cloning.dm index a5e8e5e2ba..c3f8827f7b 100644 --- a/code/modules/mob/_modifiers/cloning.dm +++ b/code/modules/mob/_modifiers/cloning.dm @@ -15,7 +15,7 @@ outgoing_melee_damage_percent = 0.7 // 30% less melee damage. disable_duration_percent = 1.25 // Stuns last 25% longer. slowdown = 1 // Slower. - evasion = -1 // 15% easier to hit. + evasion = -15 // 15% easier to hit. // Tracks number of deaths, one modifier added per cloning /datum/modifier/cloned diff --git a/code/modules/mob/_modifiers/modifiers.dm b/code/modules/mob/_modifiers/modifiers.dm index 7c005838d1..71b337b1b3 100644 --- a/code/modules/mob/_modifiers/modifiers.dm +++ b/code/modules/mob/_modifiers/modifiers.dm @@ -37,9 +37,9 @@ var/outgoing_melee_damage_percent // Adjusts melee damage inflicted by holder by a percentage. Affects attacks by melee weapons and hand-to-hand. var/slowdown // Negative numbers speed up, positive numbers slow down movement. var/haste // If set to 1, the mob will be 'hasted', which makes it ignore slowdown and go really fast. - var/evasion // Positive numbers reduce the odds of being hit by 15% each. Negative numbers increase the odds. + var/evasion // Positive numbers reduce the odds of being hit. Negative numbers increase the odds. var/bleeding_rate_percent // Adjusts amount of blood lost when bleeding. - var/accuracy // Positive numbers makes hitting things with guns easier, negatives make it harder. Each point makes it 15% easier or harder, just like evasion. + var/accuracy // Positive numbers makes hitting things with guns easier, negatives make it harder. Every 15% is equal to one tile easier or harder, just like evasion. var/accuracy_dispersion // Positive numbers make gun firing cover a wider tile range, and therefore more inaccurate. Negatives help negate dispersion penalties. var/metabolism_percent // Adjusts the mob's metabolic rate, which affects reagent processing. Won't affect mobs without reagent processing. var/icon_scale_percent // Makes the holder's icon get scaled up or down. diff --git a/code/modules/mob/_modifiers/traits.dm b/code/modules/mob/_modifiers/traits.dm index eac919b106..453c17f321 100644 --- a/code/modules/mob/_modifiers/traits.dm +++ b/code/modules/mob/_modifiers/traits.dm @@ -43,7 +43,7 @@ desc = "You're rather inexperienced with guns, you've never used one in your life, or you're just really rusty. \ Regardless, you find it quite difficult to land shots where you wanted them to go." - accuracy = -1 + accuracy = -15 accuracy_dispersion = 1 /datum/modifier/trait/high_metabolism diff --git a/code/modules/mob/_modifiers/traits_phobias.dm b/code/modules/mob/_modifiers/traits_phobias.dm index c96c6890e6..0fbe099c22 100644 --- a/code/modules/mob/_modifiers/traits_phobias.dm +++ b/code/modules/mob/_modifiers/traits_phobias.dm @@ -204,6 +204,9 @@ if(istype(thing, /obj/item/toy/plushie/spider)) // Plushies are spooky so people can be assholes with them. fear_amount += 1 + if(istype(thing, /obj/structure/snowman/spider)) //Snow spiders are also spooky so people can be assholes with those too. + fear_amount += 1 + if(istype(thing, /mob/living/simple_animal/hostile/giant_spider)) // Actual giant spiders are the scariest of them all. var/mob/living/simple_animal/hostile/giant_spider/S = thing if(S.stat == DEAD) // Dead giant spiders are less scary than alive ones. @@ -437,7 +440,7 @@ fear_amount += 1 if(istype(S.species, /datum/species/shapeshifter/promethean)) fear_amount += 4 - + return fear_amount /datum/modifier/trait/phobia/trypanophobe diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 2fd8f4170f..72290c49f3 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -2,20 +2,23 @@ name = "unknown" real_name = "unknown" voice_name = "unknown" - icon = 'icons/effects/effects.dmi' //We have an ultra-complex update icons that overlays everything, don't load some stupid random male human + icon = 'icons/effects/effects.dmi' //We have an ultra-complex update icons that overlays everything, don't load some stupid random male human icon_state = "nothing" var/list/hud_list[TOTAL_HUDS] - var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. + var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. var/obj/item/weapon/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call. - var/last_push_time //For human_attackhand.dm, keeps track of the last use of disarm + var/last_push_time //For human_attackhand.dm, keeps track of the last use of disarm - var/spitting = 0 //Spitting and spitting related things. Any human based ranged attacks, be it innate or added abilities. - var/spit_projectile = null //Projectile type. - var/spit_name = null //String - var/last_spit = 0 //Timestamp. + var/spitting = 0 //Spitting and spitting related things. Any human based ranged attacks, be it innate or added abilities. + var/spit_projectile = null //Projectile type. + var/spit_name = null //String + var/last_spit = 0 //Timestamp. - var/can_defib = 1 //Horrible damage (like beheadings) will prevent defibbing organics. + var/can_defib = 1 //Horrible damage (like beheadings) will prevent defibbing organics. + var/hiding = 0 // If the mob is hiding or not. Makes them appear under tables and the like. + var/active_regen = FALSE //Used for the regenerate proc in human_powers.dm + var/active_regen_delay = 300 /mob/living/carbon/human/New(var/new_loc, var/new_species = null) @@ -1095,7 +1098,7 @@ var/self = 0 if(usr.stat || usr.restrained() || !isliving(usr)) return - + var/datum/gender/TU = gender_datums[usr.get_visible_gender()] var/datum/gender/T = gender_datums[get_visible_gender()] @@ -1358,7 +1361,13 @@ return 0 /mob/living/carbon/human/slip(var/slipped_on, stun_duration=8) - if((species.flags & NO_SLIP) || (shoes && (shoes.item_flags & NOSLIP))) + var/list/equipment = list(src.w_uniform,src.wear_suit,src.shoes) + var/footcoverage_check = FALSE + for(var/obj/item/clothing/C in equipment) + if(C.body_parts_covered & FEET) + footcoverage_check = TRUE + break + if((species.flags & NO_SLIP && !footcoverage_check) || (shoes && (shoes.item_flags & NOSLIP))) //Footwear negates a species' natural traction. return 0 if(..(slipped_on,stun_duration)) return 1 @@ -1554,3 +1563,12 @@ var/obj/item/clothing/accessory/permit/drone/permit = new(T) permit.set_name(real_name) equip_to_appropriate_slot(permit) // If for some reason it can't find room, it'll still be on the floor. + +/mob/living/carbon/human/proc/update_icon_special() //For things such as teshari hiding and whatnot. + if(hiding) // Hiding? Carry on. + if(stat == DEAD || paralysis || weakened || stunned) //stunned/knocked down by something that isn't the rest verb? Note: This was tried with INCAPACITATION_STUNNED, but that refused to work. + hiding = 0 //No hiding for you. Mob layer should be updated naturally, but it actually doesn't. + else + layer = 2.45 + else //Replace this else with other variables if added in the future. Alternatively, could make other things effect this hiding variable. + return diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 7d15678bb1..8f082d4fb7 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -259,7 +259,14 @@ return 0 var/real_damage = rand_damage + var/hit_dam_type = attack.damage_type real_damage += attack.get_unarmed_damage(H) + if(H.gloves && istype(H.gloves, /obj/item/clothing/gloves)) + var/obj/item/clothing/gloves/G = H.gloves + real_damage += G.punch_force + hit_dam_type = G.punch_damtype + if(H.pulling_punches) //SO IT IS DECREED: PULLING PUNCHES WILL PREVENT THE ACTUAL DAMAGE FROM RINGS AND KNUCKLES, BUT NOT THE ADDED PAIN + hit_dam_type = AGONY real_damage *= damage_multiplier rand_damage *= damage_multiplier if(HULK in H.mutations) @@ -273,7 +280,7 @@ attack.apply_effects(H, src, armour, rand_damage, hit_zone) // Finally, apply damage to target - apply_damage(real_damage, (attack.deal_halloss ? HALLOSS : BRUTE), hit_zone, armour, soaked, sharp=attack.sharp, edge=attack.edge) + apply_damage(real_damage, hit_dam_type, hit_zone, armour, soaked, sharp=attack.sharp, edge=attack.edge) if(I_DISARM) M.attack_log += text("\[[time_stamp()]\] Disarmed [src.name] ([src.ckey])") diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 87246e3fe4..e5647682fa 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -197,12 +197,6 @@ emp_act if(.) return return 0 -/mob/living/carbon/human/emp_act(severity) - for(var/obj/O in src) - if(!O) continue - O.emp_act(severity) - ..() - /mob/living/carbon/human/proc/get_accuracy_penalty(mob/living/user) // Certain statuses make it harder to score a hit. These are the same as gun accuracy, however melee doesn't use multiples of 15. var/accuracy_penalty = 0 diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index 909b2776d7..445d06a802 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -235,33 +235,64 @@ /mob/living/carbon/human/proc/regenerate() set name = "Regenerate" - set desc = "Allows you to regrow limbs and heal organs." + set desc = "Allows you to regrow limbs and heal organs after a period of rest." set category = "Abilities" if(nutrition < 250) - to_chat(src, "You lack the biomass regrow anything!") + to_chat(src, "You lack the biomass to begin regeneration!") return - nutrition -= 200 + if(active_regen) + to_chat(src, "You are already regenerating tissue!") + return + else + active_regen = TRUE + src.visible_message("[src]'s flesh begins to mend...") - for(var/obj/item/organ/I in internal_organs) - if(I.damage > 0) - I.damage = 0 - to_chat(src, "You feel a soothing sensation within your [I.name]...") + var/delay_length = round(active_regen_delay * species.active_regen_mult) + if(do_after(src,delay_length)) + nutrition -= 200 - // 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.") - update_icons_all() + for(var/obj/item/organ/I in internal_organs) + if(I.damage > 0) + I.damage = max(I.damage - 30, 0) //Repair functionally half of a dead internal organ. + 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.") + update_icons_all() + active_regen = FALSE + else + to_chat(src, "Your regeneration is interrupted!") + nutrition -= 75 + active_regen = FALSE + +/mob/living/carbon/human/proc/hide_humanoid() + set name = "Hide" + set desc = "Allows to hide beneath tables or certain items. Toggled on or off." + set category = "Abilities" + + if(stat == DEAD || paralysis || weakened || stunned) // No hiding if you're stunned! + return + + if (!hiding) + layer = 2.45 //Just above cables with their 2.44 + hiding = 1 + to_chat(src, "You are now hiding.") + else + layer = MOB_LAYER + hiding = 0 + to_chat(src, "You have stopped hiding.") diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 187ddcac7e..5c269c7ce2 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -164,12 +164,14 @@ This saves us from having to call add_fingerprint() any time something is put in else if (W == r_hand) r_hand = null if(l_hand) + l_hand.update_twohanding() l_hand.update_held_icon() update_inv_l_hand() update_inv_r_hand() else if (W == l_hand) l_hand = null if(r_hand) + r_hand.update_twohanding() r_hand.update_held_icon() update_inv_l_hand() update_inv_l_hand() diff --git a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm index 58a967c809..672840117e 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm @@ -15,6 +15,8 @@ blood_color = "#CCCCCC" flesh_color = "#AAAAAA" + virus_immune = 1 + remains_type = /obj/effect/decal/cleanable/ash death_message = "dissolves into ash..." diff --git a/code/modules/mob/living/carbon/human/species/outsider/skeleton.dm b/code/modules/mob/living/carbon/human/species/outsider/skeleton.dm index d6c5d030a5..d3b9f5d9b9 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/skeleton.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/skeleton.dm @@ -22,7 +22,7 @@ hunger_factor = 0 metabolic_rate = 0 - virus_immune = 1 + virus_immune = 1 brute_mod = 1 burn_mod = 0 diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index f3749983ac..6075cf788c 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -42,6 +42,7 @@ var/blood_volume = 560 // Initial blood volume. var/bloodloss_rate = 1 // Multiplier for how fast a species bleeds out. Higher = Faster var/hunger_factor = 0.05 // Multiplier for hunger. + var/active_regen_mult = 1 // Multiplier for 'Regenerate' power speed, in human_powers.dm var/taste_sensitivity = TASTE_NORMAL // How sensitive the species is to minute tastes. diff --git a/code/modules/mob/living/carbon/human/species/station/golem.dm b/code/modules/mob/living/carbon/human/species/station/golem.dm index bccafdde14..171af12d12 100644 --- a/code/modules/mob/living/carbon/human/species/station/golem.dm +++ b/code/modules/mob/living/carbon/human/species/station/golem.dm @@ -17,6 +17,8 @@ blood_color = "#515573" flesh_color = "#137E8F" + virus_immune = 1 + has_organ = list( "brain" = /obj/item/organ/internal/brain/golem ) diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans.dm b/code/modules/mob/living/carbon/human/species/station/prometheans.dm index 8bc24d9924..776d18ea67 100644 --- a/code/modules/mob/living/carbon/human/species/station/prometheans.dm +++ b/code/modules/mob/living/carbon/human/species/station/prometheans.dm @@ -39,7 +39,7 @@ var/datum/species/shapeshifter/promethean/prometheans virus_immune = 1 blood_volume = 560 min_age = 1 - max_age = 5 + max_age = 10 brute_mod = 0.75 burn_mod = 2 oxy_mod = 0 @@ -56,7 +56,7 @@ var/datum/species/shapeshifter/promethean/prometheans body_temperature = 310.15 - siemens_coefficient = 0.3 + siemens_coefficient = 0.4 rarity_value = 5 genders = list(MALE, FEMALE, NEUTER, PLURAL) diff --git a/code/modules/mob/living/carbon/human/species/station/seromi.dm b/code/modules/mob/living/carbon/human/species/station/seromi.dm index 17305be9e8..2e83d47fbe 100644 --- a/code/modules/mob/living/carbon/human/species/station/seromi.dm +++ b/code/modules/mob/living/carbon/human/species/station/seromi.dm @@ -114,7 +114,7 @@ inherent_verbs = list( /mob/living/carbon/human/proc/sonar_ping, - /mob/living/proc/hide + /mob/living/carbon/human/proc/hide_humanoid ) /datum/species/teshari/equip_survival_gear(var/mob/living/carbon/human/H) diff --git a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm index aed54a6b9c..f19eb0e1ea 100644 --- a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm +++ b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm @@ -38,6 +38,8 @@ speech_sounds = list('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg') speech_chance = 100 + virus_immune = 1 + breath_type = null poison_type = null diff --git a/code/modules/mob/living/carbon/human/unarmed_attack.dm b/code/modules/mob/living/carbon/human/unarmed_attack.dm index 1c54a4258f..a7f80fb8f1 100644 --- a/code/modules/mob/living/carbon/human/unarmed_attack.dm +++ b/code/modules/mob/living/carbon/human/unarmed_attack.dm @@ -11,7 +11,7 @@ var/global/list/sparring_attack_cache = list() var/sharp = 0 var/edge = 0 - var/deal_halloss + var/damage_type = BRUTE var/sparring_variant_type = /datum/unarmed_attack/light_strike var/eye_attack_text @@ -131,7 +131,7 @@ var/global/list/sparring_attack_cache = list() /datum/unarmed_attack/punch/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage) var/obj/item/organ/external/affecting = target.get_organ(zone) var/organ = affecting.name - + var/datum/gender/TU = gender_datums[user.get_visible_gender()] var/datum/gender/TT = gender_datums[target.get_visible_gender()] @@ -258,10 +258,10 @@ var/global/list/sparring_attack_cache = list() if(5) user.visible_message("[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed [TU.his] [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/ /datum/unarmed_attack/light_strike - deal_halloss = 3 attack_noun = list("tap","light strike") attack_verb = list("tapped", "lightly struck") - damage = 2 + damage = 3 + damage_type = AGONY shredding = 0 damage = 0 sharp = 0 diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index e6c8ed1b96..10d599593a 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -179,6 +179,9 @@ Please contact me on #coderbus IRC. ~Carn x //5: Set appearance once appearance = ma_compiled + //6: Do any species specific layering updates, such as when hiding. + update_icon_special() + /mob/living/carbon/human/update_transform(var/mutable_appearance/passed_ma) if(QDESTROYING(src)) return @@ -216,6 +219,7 @@ Please contact me on #coderbus IRC. ~Carn x M.Translate(0, 16*(desired_scale-1)) ma.transform = M ma.layer = MOB_LAYER // Fix for a byond bug where turf entry order no longer matters + update_icon_special() //Adjust their layer, like when they are hiding. if(!passed_ma) appearance = ma @@ -252,6 +256,25 @@ Please contact me on #coderbus IRC. ~Carn x list_huds = hud_list.Copy() list_huds += backplane // Required to mask HUDs in context menus: http://www.byond.com/forum/?post=2336679 +//TYPING INDICATOR CODE. + if(client && !stat) //They have a client & aren't dead/KO'd? Continue on! + if(typing_indicator && hud_typing) //They already have the indicator and are still typing + overlays += typing_indicator //This might not be needed? It works, so I'm leaving it. + list_huds += typing_indicator + typing_indicator.invisibility = invisibility + + else if(!typing_indicator && hud_typing) //Are they in their body, NOT dead, have hud_typing, do NOT have a typing indicator. and have it enabled? + typing_indicator = new + typing_indicator.icon = 'icons/mob/talk.dmi' + typing_indicator.icon_state = "[speech_bubble_appearance()]_typing" + overlays += typing_indicator + list_huds += typing_indicator + + else if(typing_indicator && !hud_typing) //Did they stop typing? + overlays -= typing_indicator + typing = 0 + hud_typing = 0 + if(update_icons) update_icons() diff --git a/code/modules/mob/living/carbon/viruses.dm b/code/modules/mob/living/carbon/viruses.dm index b4d8297697..2f52dcd1cb 100644 --- a/code/modules/mob/living/carbon/viruses.dm +++ b/code/modules/mob/living/carbon/viruses.dm @@ -23,6 +23,13 @@ var/datum/disease2/disease/V = M.virus2[ID] infect_virus2(src,V) + else if(istype(O,/obj/effect/decal/cleanable/vomit)) + var/obj/effect/decal/cleanable/vomit/Vom = O + if(Vom.virus2.len) + for (var/ID in Vom.virus2) + var/datum/disease2/disease/V = Vom.virus2[ID] + infect_virus2(src,V) + if(virus2.len) for (var/ID in virus2) var/datum/disease2/disease/V = virus2[ID] diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index ed3a38b0d2..b36cd29d21 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -45,7 +45,7 @@ var/failed_last_breath = 0 //This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks. var/lastpuke = 0 - var/evasion = 0 // Makes attacks harder to land. Each number equals 15% more likely to miss. Negative numbers increase hit chance. + var/evasion = 0 // Makes attacks harder to land. Negative numbers increase hit chance. var/force_max_speed = 0 // If 1, the mob runs extremely fast and cannot be slowed. var/image/dsoverlay = null //Overlay used for darksight eye adjustments diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index 6d34c4a969..b0b325f08d 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -445,6 +445,11 @@ toggle(mob/living/silicon/pai/user) user.secHUD = !user.secHUD + user.plane_holder.set_vis(VIS_CH_ID, user.secHUD) + user.plane_holder.set_vis(VIS_CH_WANTED, user.secHUD) + user.plane_holder.set_vis(VIS_CH_IMPTRACK, user.secHUD) + user.plane_holder.set_vis(VIS_CH_IMPLOYAL, user.secHUD) + user.plane_holder.set_vis(VIS_CH_IMPCHEM, user.secHUD) is_active(mob/living/silicon/pai/user) return user.secHUD @@ -456,6 +461,8 @@ toggle(mob/living/silicon/pai/user) user.medHUD = !user.medHUD + user.plane_holder.set_vis(VIS_CH_STATUS, user.medHUD) + user.plane_holder.set_vis(VIS_CH_HEALTH, user.medHUD) is_active(mob/living/silicon/pai/user) return user.medHUD diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm index b370787ede..e8d3e0ad2c 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm @@ -58,7 +58,8 @@ /obj/item/weapon/reagent_containers/glass, /obj/item/weapon/storage/pill_bottle, /obj/item/weapon/reagent_containers/pill, - /obj/item/weapon/reagent_containers/blood + /obj/item/weapon/reagent_containers/blood, + /obj/item/stack/material/phoron ) /obj/item/weapon/gripper/research //A general usage gripper, used for toxins/robotics/xenobio/etc diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 464ea514b7..aa1cf2d271 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -152,7 +152,7 @@ return 1 /mob/living/silicon/robot/handle_regular_hud_updates() - + var/fullbright = FALSE if (src.stat == 2 || (XRAY in mutations) || (src.sight_mode & BORGXRAY)) src.sight |= SEE_TURFS src.sight |= SEE_MOBS @@ -164,18 +164,22 @@ src.sight |= SEE_MOBS src.see_in_dark = 8 see_invisible = SEE_INVISIBLE_MINIMUM + fullbright = TRUE else if (src.sight_mode & BORGMESON) src.sight |= SEE_TURFS src.see_in_dark = 8 see_invisible = SEE_INVISIBLE_MINIMUM + fullbright = TRUE else if (src.sight_mode & BORGMATERIAL) src.sight |= SEE_OBJS src.see_in_dark = 8 see_invisible = SEE_INVISIBLE_MINIMUM + fullbright = TRUE else if (src.sight_mode & BORGTHERM) src.sight |= SEE_MOBS src.see_in_dark = 8 src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + fullbright = TRUE else if (!seedarkness) src.sight &= ~SEE_MOBS src.sight &= ~SEE_TURFS @@ -189,7 +193,7 @@ src.see_in_dark = 8 // see_in_dark means you can FAINTLY see in the dark, humans have a range of 3 or so, tajaran have it at 8 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) ..() if (src.healths) 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 970d99448c..1b98786f04 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm @@ -246,10 +246,19 @@ var/global/list/robot_modules = list( src.modules += N src.modules += B -/obj/item/weapon/robot_module/medical/robot/surgeon/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) +/obj/item/weapon/robot_module/robot/medical/surgeon/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) + + var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules + if(S.mode == 2) + S.reagents.clear_reagents() + S.mode = initial(S.mode) + S.desc = initial(S.desc) + S.update_icon() + if(src.emag) var/obj/item/weapon/reagent_containers/spray/PS = src.emag PS.reagents.add_reagent("pacid", 2 * amount) + ..() /obj/item/weapon/robot_module/robot/medical/crisis @@ -503,6 +512,7 @@ var/global/list/robot_modules = list( src.modules += new /obj/item/weapon/handcuffs/cyborg(src) src.modules += new /obj/item/weapon/melee/baton/robot(src) src.modules += new /obj/item/weapon/gun/energy/taser/mounted/cyborg(src) + src.modules += new /obj/item/weapon/gun/energy/taser/xeno/sec/robot(src) src.modules += new /obj/item/taperoll/police(src) src.modules += new /obj/item/weapon/reagent_containers/spray/pepper(src) src.emag = new /obj/item/weapon/gun/energy/laser/mounted(src) @@ -750,6 +760,18 @@ var/global/list/robot_modules = list( C.synths = list(wire) src.modules += C +/obj/item/weapon/robot_module/robot/research/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) + + var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules + if(S.mode == 2) + S.reagents.clear_reagents() + S.mode = initial(S.mode) + S.desc = initial(S.desc) + S.update_icon() + + ..() + + /obj/item/weapon/robot_module/robot/security/combat name = "combat robot module" hide_on_manifest = 1 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 9967fa67dc..b3b88074b0 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm @@ -182,3 +182,13 @@ src.modules += O src.modules += B src.modules += S + +/obj/item/weapon/robot_module/robot/syndicate/combat_medic/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) + + var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules + if(S.mode == 2) + S.reagents.clear_reagents() + S.mode = initial(S.mode) + S.desc = initial(S.desc) + S.update_icon() + ..() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 689d27dce8..09321af981 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -322,6 +322,8 @@ /mob/living/silicon/proc/receive_alarm(var/datum/alarm_handler/alarm_handler, var/datum/alarm/alarm, was_raised) if(!next_alarm_notice) next_alarm_notice = world.time + SecondsToTicks(10) + if(alarm.hidden) + return var/list/alarms = queued_alarms[alarm_handler] if(was_raised) diff --git a/code/modules/mob/living/simple_animal/aliens/alien.dm b/code/modules/mob/living/simple_animal/aliens/alien.dm index 1ec1419db1..0f7cc35c77 100644 --- a/code/modules/mob/living/simple_animal/aliens/alien.dm +++ b/code/modules/mob/living/simple_animal/aliens/alien.dm @@ -137,106 +137,4 @@ /mob/living/simple_animal/hostile/alien/death() ..() visible_message("[src] lets out a waning guttural screech, green blood bubbling from its maw...") - playsound(src, 'sound/voice/hiss6.ogg', 100, 1) - -// Xenoarch aliens. -/mob/living/simple_animal/hostile/samak - name = "samak" - desc = "A fast, armoured predator accustomed to hiding and ambushing in cold terrain." - faction = "samak" - icon_state = "samak" - icon_living = "samak" - icon_dead = "samak_dead" - icon = 'icons/jungle.dmi' - - faction = "samak" - - maxHealth = 125 - health = 125 - speed = 2 - move_to_delay = 2 - - melee_damage_lower = 5 - melee_damage_upper = 15 - - attacktext = list("mauled") - cold_damage_per_tick = 0 - - speak_chance = 5 - speak = list("Hruuugh!","Hrunnph") - emote_see = list("paws the ground","shakes its mane","stomps") - emote_hear = list("snuffles") - -/mob/living/simple_animal/hostile/diyaab - name = "diyaab" - desc = "A small pack animal. Although omnivorous, it will hunt meat on occasion." - faction = "diyaab" - icon_state = "diyaab" - icon_living = "diyaab" - icon_dead = "diyaab_dead" - icon = 'icons/jungle.dmi' - - faction = "diyaab" - cooperative = 1 - - maxHealth = 25 - health = 25 - speed = 1 - move_to_delay = 1 - - melee_damage_lower = 1 - melee_damage_upper = 8 - - attacktext = list("gouged") - cold_damage_per_tick = 0 - - speak_chance = 5 - speak = list("Awrr?","Aowrl!","Worrl") - emote_see = list("sniffs the air cautiously","looks around") - emote_hear = list("snuffles") - -/mob/living/simple_animal/hostile/shantak - name = "shantak" - desc = "A piglike creature with a bright iridiscent mane that sparkles as though lit by an inner light. Don't be fooled by its beauty though." - faction = "shantak" - icon_state = "shantak" - icon_living = "shantak" - icon_dead = "shantak_dead" - icon = 'icons/jungle.dmi' - - faction = "shantak" - - maxHealth = 75 - health = 75 - speed = 1 - move_to_delay = 1 - - melee_damage_lower = 3 - melee_damage_upper = 12 - - attacktext = list("gouged") - cold_damage_per_tick = 0 - - speak_chance = 5 - speak = list("Shuhn","Shrunnph?","Shunpf") - emote_see = list("scratches the ground","shakes out its mane","clinks gently as it moves") - -/mob/living/simple_animal/yithian - name = "yithian" - desc = "A friendly creature vaguely resembling an oversized snail without a shell." - icon_state = "yithian" - icon_living = "yithian" - icon_dead = "yithian_dead" - icon = 'icons/jungle.dmi' - - faction = "yithian" - -/mob/living/simple_animal/tindalos - name = "tindalos" - desc = "It looks like a large, flightless grasshopper." - icon_state = "tindalos" - icon_living = "tindalos" - icon_dead = "tindalos_dead" - icon = 'icons/jungle.dmi' - - faction = "tindalos" + playsound(src, 'sound/voice/hiss6.ogg', 100, 1) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/aliens/drone.dm b/code/modules/mob/living/simple_animal/aliens/drone.dm index 81532ef62d..35e09030dd 100644 --- a/code/modules/mob/living/simple_animal/aliens/drone.dm +++ b/code/modules/mob/living/simple_animal/aliens/drone.dm @@ -25,6 +25,7 @@ projectiletype = /obj/item/projectile/beam/drone projectilesound = 'sound/weapons/laser3.ogg' destroy_surroundings = 0 + hovering = TRUE //Drones aren't affected by atmos. min_oxy = 0 @@ -275,3 +276,10 @@ /obj/item/projectile/beam/pulse/drone damage = 10 + +// A slightly easier drone, for POIs. +// Difference is that it should not be faster than you. +/mob/living/simple_animal/hostile/malf_drone/lesser + desc = "An automated combat drone with an aged apperance." + returns_home = TRUE + move_to_delay = 6 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/animals/carp.dm b/code/modules/mob/living/simple_animal/animals/carp.dm index 400fb540db..4dc4daffda 100644 --- a/code/modules/mob/living/simple_animal/animals/carp.dm +++ b/code/modules/mob/living/simple_animal/animals/carp.dm @@ -8,6 +8,7 @@ faction = "carp" intelligence_level = SA_ANIMAL + hovering = TRUE maxHealth = 25 health = 25 speed = 4 diff --git a/code/modules/mob/living/simple_animal/animals/crab.dm b/code/modules/mob/living/simple_animal/animals/crab.dm index 35089275e5..0d485d859d 100644 --- a/code/modules/mob/living/simple_animal/animals/crab.dm +++ b/code/modules/mob/living/simple_animal/animals/crab.dm @@ -49,7 +49,7 @@ //Sif Crabs /mob/living/simple_animal/giant_crab - name = "Giant Crab" + name = "giant crab" desc = "A large, hard-shelled crustacean. This one is mostly grey." icon_state = "sif_crab" icon_living = "sif_crab" diff --git a/code/modules/mob/living/simple_animal/animals/miscellaneous.dm b/code/modules/mob/living/simple_animal/animals/miscellaneous.dm new file mode 100644 index 0000000000..57fe09727b --- /dev/null +++ b/code/modules/mob/living/simple_animal/animals/miscellaneous.dm @@ -0,0 +1,19 @@ +/mob/living/simple_animal/yithian + name = "yithian" + desc = "A friendly creature vaguely resembling an oversized snail without a shell." + icon_state = "yithian" + icon_living = "yithian" + icon_dead = "yithian_dead" + icon = 'icons/jungle.dmi' + + faction = "yithian" + +/mob/living/simple_animal/tindalos + name = "tindalos" + desc = "It looks like a large, flightless grasshopper." + icon_state = "tindalos" + icon_living = "tindalos" + icon_dead = "tindalos_dead" + icon = 'icons/jungle.dmi' + + faction = "tindalos" \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/animals/sif_wildlife/diyaab.dm b/code/modules/mob/living/simple_animal/animals/sif_wildlife/diyaab.dm new file mode 100644 index 0000000000..5e21308410 --- /dev/null +++ b/code/modules/mob/living/simple_animal/animals/sif_wildlife/diyaab.dm @@ -0,0 +1,27 @@ +/mob/living/simple_animal/retaliate/diyaab + name = "diyaab" + desc = "A small pack animal. Although omnivorous, it will hunt meat on occasion." + faction = "diyaab" + icon_state = "diyaab" + icon_living = "diyaab" + icon_dead = "diyaab_dead" + icon = 'icons/jungle.dmi' + + faction = "diyaab" + cooperative = 1 + + maxHealth = 25 + health = 25 + speed = 1 + move_to_delay = 1 + + melee_damage_lower = 1 + melee_damage_upper = 8 + + attacktext = "gouged" + cold_damage_per_tick = 0 + + speak_chance = 5 + speak = list("Awrr?","Aowrl!","Worrl") + emote_see = list("sniffs the air cautiously","looks around") + emote_hear = list("snuffles") \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/animals/sif_wildlife/savik.dm b/code/modules/mob/living/simple_animal/animals/sif_wildlife/savik.dm new file mode 100644 index 0000000000..c8b6bd7570 --- /dev/null +++ b/code/modules/mob/living/simple_animal/animals/sif_wildlife/savik.dm @@ -0,0 +1,32 @@ +/mob/living/simple_animal/hostile/savik + name = "savik" + desc = "A fast, armoured predator accustomed to hiding and ambushing in cold terrain." + faction = "savik" + icon_state = "savik" + icon_living = "savik" + icon_dead = "savik_dead" + icon = 'icons/jungle.dmi' + + faction = "savik" + + maxHealth = 125 + health = 125 + speed = 2 + move_to_delay = 2 + + melee_damage_lower = 15 + melee_damage_upper = 25 + + attacktext = "mauled" + cold_damage_per_tick = 0 + + speak_chance = 5 + speak = list("Hruuugh!","Hrunnph") + emote_see = list("paws the ground","shakes its mane","stomps") + emote_hear = list("snuffles") + +/mob/living/simple_animal/hostile/savik/handle_stance(var/new_stance) + ..(new_stance) + if(stance == STANCE_ATTACK || stance == STANCE_ATTACKING) + if((health / maxHealth) <= 0.5) // At half health, and fighting someone currently. + add_modifier(/datum/modifier/berserk, 30 SECONDS) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/animals/sif_wildlife/shantak.dm b/code/modules/mob/living/simple_animal/animals/sif_wildlife/shantak.dm new file mode 100644 index 0000000000..fe3865e4ea --- /dev/null +++ b/code/modules/mob/living/simple_animal/animals/sif_wildlife/shantak.dm @@ -0,0 +1,25 @@ +/mob/living/simple_animal/hostile/shantak + name = "shantak" + desc = "A piglike creature with a bright iridiscent mane that sparkles as though lit by an inner light. Don't be fooled by its beauty though." + faction = "shantak" + icon_state = "shantak" + icon_living = "shantak" + icon_dead = "shantak_dead" + icon = 'icons/jungle.dmi' + + faction = "shantak" + + maxHealth = 75 + health = 75 + speed = 1 + move_to_delay = 1 + + melee_damage_lower = 3 + melee_damage_upper = 12 + + attacktext = "gouged" + cold_damage_per_tick = 0 + + speak_chance = 5 + speak = list("Shuhn","Shrunnph?","Shunpf") + emote_see = list("scratches the ground","shakes out its mane","clinks gently as it moves") \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/constructs/constructs.dm b/code/modules/mob/living/simple_animal/constructs/constructs.dm index ccf0cf1b8a..c0034b1908 100644 --- a/code/modules/mob/living/simple_animal/constructs/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs/constructs.dm @@ -8,6 +8,7 @@ response_disarm = "flailed at" response_harm = "punched" intelligence_level = SA_HUMANOID // Player controlled. + hovering = TRUE icon_dead = "shade_dead" speed = -1 a_intent = I_HURT diff --git a/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm b/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm index fd26fe3339..c7645d2352 100644 --- a/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm +++ b/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm @@ -1,5 +1,5 @@ /mob/living/simple_animal/hostile/mecha - name = "syndicate gygax" + name = "mercenary gygax" desc = "Well that's forboding." icon = 'icons/mecha/mecha.dmi' icon_state = "darkgygax" @@ -96,6 +96,8 @@ /mob/living/simple_animal/hostile/mecha/malf_drone + name = "autonomous mechanized drone" + desc = "It appears to be an exosuit, piloted by a drone intelligence. It looks scary." intelligence_level = SA_ROBOTIC faction = "malf_drone" speak_chance = 1 @@ -110,6 +112,7 @@ say_cannot = list("Denied.", "Negative.") say_maybe_target = list("Possible threat detected. Investigating.", "Motion detected.", "Investigating.") say_got_target = list("Threat detected.", "New task: Remove threat.", "Threat removal engaged.", "Engaging target.") + returns_home = TRUE /mob/living/simple_animal/hostile/mecha/malf_drone/isSynthetic() return TRUE diff --git a/code/modules/mob/living/simple_animal/humanoids/syndicate.dm b/code/modules/mob/living/simple_animal/humanoids/syndicate.dm index 5b9d6ca0ab..e7f9d6d64d 100644 --- a/code/modules/mob/living/simple_animal/humanoids/syndicate.dm +++ b/code/modules/mob/living/simple_animal/humanoids/syndicate.dm @@ -133,7 +133,7 @@ ranged = 1 rapid = 1 projectiletype = /obj/item/projectile/bullet/pistol/medium - casingtype = /obj/item/ammo_casing/spent +// casingtype = /obj/item/ammo_casing/spent //Makes infinite stacks of bullets when put in PoIs. projectilesound = 'sound/weapons/Gunshot_light.ogg' loot_list = list(/obj/item/weapon/gun/projectile/automatic/c20r = 100) @@ -168,6 +168,7 @@ icon_state = "viscerator_attack" icon_living = "viscerator_attack" intelligence_level = SA_ROBOTIC + hovering = TRUE faction = "syndicate" maxHealth = 15 diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 43d77065bf..a7e7ceb9aa 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -584,6 +584,12 @@ /mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj) ai_log("bullet_act() I was shot by: [Proj.firer]",2) + /* VOREStation Edit - Ace doesn't like bonus SA damage. + //Projectiles with bonus SA damage + if(!Proj.nodamage) + if(!Proj.SA_vulnerability || Proj.SA_vulnerability == intelligence_level) + Proj.damage += Proj.SA_bonus_damage + */ // VOREStation Edit End . = ..() if(Proj.firer) @@ -1292,6 +1298,7 @@ if(A.attack_generic(src, damage_to_do, pick(attacktext)) && attack_sound) playsound(src, attack_sound, 75, 1) + return TRUE //The actual top-level ranged attack proc diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index df5955f946..70ee856b15 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -51,6 +51,7 @@ if(!plane_holder) //Lazy plane_holder = new(src) //Not a location, it takes it and saves it. + if(!vis_enabled) vis_enabled = list() client.screen += plane_holder.plane_masters recalculate_vis() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 72cfec9453..1fa44ca148 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -145,7 +145,6 @@ /mob/proc/Life() // if(organStructure) // organStructure.ProcessOrgans() - //handle_typing_indicator() //You said the typing indicator would be fine. The test determined that was a lie. return #define UNBUCKLED 0 diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 665ae7b3ec..4ea8d44404 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -220,10 +220,15 @@ var/get_rig_stats = 0 //Moved from computer.dm + + var/hud_typing = 0 //Typing indicator stuff. + var/typing //Simple mobs use this variable. + var/obj/effect/decal/typing_indicator + var/low_priority = FALSE //Skip processing life() if there's just no players on this Z-level var/default_pixel_x = 0 //For offsetting mobs var/default_pixel_y = 0 var/attack_icon //Icon to use when attacking w/o anything in-hand - var/attack_icon_state //State for above \ No newline at end of file + var/attack_icon_state //State for above diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index a990e5ae40..4b625e15f1 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -15,6 +15,11 @@ /proc/mob_size_difference(var/mob_size_A, var/mob_size_B) return round(log(2, mob_size_A/mob_size_B), 1) +/mob/proc/can_wield_item(obj/item/W) + if(W.w_class >= ITEMSIZE_LARGE && issmall(src)) + return FALSE //M is too small to wield this + return TRUE + /proc/istiny(A) if(A && istype(A, /mob/living)) var/mob/living/L = A diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm index 8faf86b5d8..486841b2fd 100644 --- a/code/modules/mob/typing_indicator.dm +++ b/code/modules/mob/typing_indicator.dm @@ -1,13 +1,4 @@ -#define TYPING_INDICATOR_LIFETIME 30 * 10 //grace period after which typing indicator disappears regardless of text in chatbar - -mob/var/hud_typing = 0 //set when typing in an input window instead of chatline -mob/var/typing -mob/var/last_typed -mob/var/last_typed_time - -mob/var/obj/effect/decal/typing_indicator - -/mob/proc/set_typing_indicator(var/state) +/mob/proc/set_typing_indicator(var/state) //Leaving this here for mobs. if(!typing_indicator) typing_indicator = new @@ -35,11 +26,17 @@ mob/var/obj/effect/decal/typing_indicator set name = ".Say" set hidden = 1 - set_typing_indicator(1) - hud_typing = 1 + if(!ishuman(src)) //If they're a mob, use the old code. + set_typing_indicator(1) + if(is_preference_enabled(/datum/client_preference/show_typing_indicator)) + hud_typing = 1 + update_icons_huds() var/message = input("","say (text)") as text - hud_typing = 0 - set_typing_indicator(0) + if(is_preference_enabled(/datum/client_preference/show_typing_indicator)) + hud_typing = 0 + update_icons_huds() + if(!ishuman(src)) //If they're a mob, use the old code. + set_typing_indicator(0) if(message) say_verb(message) @@ -47,29 +44,16 @@ mob/var/obj/effect/decal/typing_indicator set name = ".Me" set hidden = 1 - set_typing_indicator(1) - hud_typing = 1 + if(!ishuman(src)) //If they're a mob, use the old code. + set_typing_indicator(1) + if(is_preference_enabled(/datum/client_preference/show_typing_indicator)) + hud_typing = 1 + update_icons_huds() var/message = input("","me (text)") as text - hud_typing = 0 - set_typing_indicator(0) + if(is_preference_enabled(/datum/client_preference/show_typing_indicator)) + hud_typing = 0 + update_icons_huds() + if(!ishuman(src)) //If they're a mob, use the old code. + set_typing_indicator(0) if(message) me_verb(message) - -/mob/proc/handle_typing_indicator() - if(is_preference_enabled(/datum/client_preference/show_typing_indicator) && !hud_typing) - var/temp = winget(client, "input", "text") - - if (temp != last_typed) - last_typed = temp - last_typed_time = world.time - - if (world.time > last_typed_time + TYPING_INDICATOR_LIFETIME) - set_typing_indicator(0) - return - if(length(temp) > 5 && findtext(temp, "Say \"", 1, 7)) - set_typing_indicator(1) - else if(length(temp) > 3 && findtext(temp, "Me ", 1, 5)) - set_typing_indicator(1) - - else - set_typing_indicator(0) \ No newline at end of file diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm index b92ec2144a..84e7a9174a 100644 --- a/code/modules/multiz/movement.dm +++ b/code/modules/multiz/movement.dm @@ -377,6 +377,13 @@ /turf/simulated/open/check_impact(var/atom/movable/falling_atom) return FALSE +// Or actual space. +/turf/space/CheckFall(var/atom/movable/falling_atom) + return FALSE + +/turf/space/check_impact(var/atom/movable/falling_atom) + return FALSE + // We return 1 without calling fall_impact in order to provide a soft landing. So nice. // Note this really should never even get this far /obj/structure/stairs/CheckFall(var/atom/movable/falling_atom) @@ -407,7 +414,7 @@ A.fall_impact(hit_atom, damage_min, damage_max, silent = TRUE) // Take damage from falling and hitting the ground -/mob/living/fall_impact(var/atom/hit_atom, var/damage_min = 0, var/damage_max = 10, var/silent = FALSE, var/planetary = FALSE) +/mob/living/fall_impact(var/atom/hit_atom, var/damage_min = 0, var/damage_max = 5, var/silent = FALSE, var/planetary = FALSE) var/turf/landing = get_turf(hit_atom) if(planetary && src.CanParachute()) if(!silent) @@ -532,14 +539,12 @@ "You hear something slam into \the [landing].") playsound(loc, "punch", 25, 1, -1) - // Now to hurt everything in the mech (if the fall is planetary, the mech blows up, so we do this first) - for(var/atom/movable/A in src.contents) - A.fall_impact(hit_atom, damage_min, damage_max, silent = TRUE) - // And now the Mech - + // And now to hurt the mech. if(!planetary) take_damage(rand(damage_min, damage_max)) else + for(var/atom/movable/A in src.contents) + A.fall_impact(hit_atom, damage_min, damage_max, silent = TRUE) qdel(src) // And hurt the floor. diff --git a/code/modules/nano/modules/alarm_monitor.dm b/code/modules/nano/modules/alarm_monitor.dm index f3fca46d43..264fdee9cc 100644 --- a/code/modules/nano/modules/alarm_monitor.dm +++ b/code/modules/nano/modules/alarm_monitor.dm @@ -26,7 +26,7 @@ /datum/nano_module/alarm_monitor/proc/all_alarms() var/list/all_alarms = new() for(var/datum/alarm_handler/AH in alarm_handlers) - all_alarms += AH.alarms + all_alarms += AH.visible_alarms() return all_alarms diff --git a/code/modules/nano/modules/atmos_control.dm b/code/modules/nano/modules/atmos_control.dm index 742696396b..b1dd3ab759 100644 --- a/code/modules/nano/modules/atmos_control.dm +++ b/code/modules/nano/modules/atmos_control.dm @@ -36,6 +36,8 @@ // TODO: Move these to a cache, similar to cameras for(var/obj/machinery/alarm/alarm in (monitored_alarms.len ? monitored_alarms : machines)) + if(!monitored_alarms.len && alarm.alarms_hidden) + continue alarms[++alarms.len] = list( "name" = sanitize(alarm.name), "ref"= "\ref[alarm]", diff --git a/code/modules/organs/internal/eyes.dm b/code/modules/organs/internal/eyes.dm index 07d70bc6e2..77350a73db 100644 --- a/code/modules/organs/internal/eyes.dm +++ b/code/modules/organs/internal/eyes.dm @@ -93,3 +93,7 @@ /obj/item/organ/internal/eyes/proc/additional_flash_effects(var/intensity) return -1 + +/obj/item/organ/internal/eyes/emp_act(severity) + ..() //Returns if the organ isn't robotic + owner.eye_blurry += (4/severity) \ No newline at end of file diff --git a/code/modules/organs/subtypes/machine.dm b/code/modules/organs/subtypes/machine.dm index db01fe0580..32c0e4b2b9 100644 --- a/code/modules/organs/subtypes/machine.dm +++ b/code/modules/organs/subtypes/machine.dm @@ -17,6 +17,9 @@ owner.stat = 0 owner.visible_message("\The [owner] twitches visibly!") +/obj/item/organ/internal/cell/emp_act(severity) + ..() + owner.nutrition = max(0, owner.nutrition - rand(10/severity, 50/severity)) // Used for an MMI or posibrain being installed into a human. /obj/item/organ/internal/mmi_holder @@ -84,6 +87,10 @@ holder_mob.drop_from_inventory(src) qdel(src) +/obj/item/organ/internal/mmi_holder/emp_act(severity) + ..() + owner.adjustToxLoss(rand(6/severity, 12/severity)) + /obj/item/organ/internal/mmi_holder/posibrain name = "positronic brain interface" brain_type = /obj/item/device/mmi/digital/posibrain diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index b708e58253..4fd94901cc 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -35,6 +35,50 @@ var/const/signfont = "Times New Roman" var/const/crayonfont = "Comic Sans MS" +/obj/item/weapon/paper/card + name = "blank card" + desc = "A gift card with space to write on the cover." + icon_state = "greetingcard" + slot_flags = null //no fun allowed!!!! + +/obj/item/weapon/paper/card/AltClick() //No fun allowed + return + +/obj/item/weapon/paper/card/update_icon() + return + +/obj/item/weapon/paper/card/smile + name = "happy card" + desc = "A gift card with a smiley face on the cover." + icon_state = "greetingcard_smile" + +/obj/item/weapon/paper/card/cat + name = "cat card" + desc = "A gift card with a cat on the cover." + icon_state = "greetingcard_cat" + +/obj/item/weapon/paper/card/flower + name = "flower card" + desc = "A gift card with a flower on the cover." + icon_state = "greetingcard_flower" + +/obj/item/weapon/paper/card/heart + name = "heart card" + desc = "A gift card with a heart on the cover." + icon_state = "greetingcard_heart" + +/obj/item/weapon/paper/card/New() + ..() + pixel_y = rand(-8, 8) + pixel_x = rand(-9, 9) + stamps = null + + if(info != initial(info)) + info = html_encode(info) + info = replacetext(info, "\n", "
") + info = parsepencode(info) + return + /obj/item/weapon/paper/alien name = "alien tablet" desc = "It looks highly advanced" @@ -319,7 +363,7 @@ if(P.lit && !user.restrained()) if(istype(P, /obj/item/weapon/flame/lighter/zippo)) class = "rose" - + user.visible_message("[user] holds \the [P] up to \the [src], it looks like [TU.hes] trying to burn it!", \ "You hold \the [P] up to \the [src], burning it slowly.") diff --git a/code/modules/planet/sif.dm b/code/modules/planet/sif.dm index 3d3a2a0073..e50c584a13 100644 --- a/code/modules/planet/sif.dm +++ b/code/modules/planet/sif.dm @@ -174,7 +174,7 @@ datum/weather/sif temp_high = T0C // 0c temp_low = 243.15 // -30c light_modifier = 0.5 - flight_falure_modifier = 5 + flight_failure_modifier = 5 transition_chances = list( WEATHER_LIGHT_SNOW = 20, WEATHER_SNOW = 50, @@ -198,7 +198,7 @@ datum/weather/sif temp_high = 243.15 // -30c temp_low = 233.15 // -40c light_modifier = 0.3 - flight_falure_modifier = 10 + flight_failure_modifier = 10 transition_chances = list( WEATHER_SNOW = 45, WEATHER_BLIZZARD = 40, @@ -232,7 +232,7 @@ datum/weather/sif if(L.z in holder.our_planet.expected_z_levels) var/turf/T = get_turf(L) if(!T.outdoors) - return // They're indoors, so no need to rain on them. + continue // They're indoors, so no need to rain on them. L.water_act(1) to_chat(L, "Rain falls on you.") @@ -243,7 +243,7 @@ datum/weather/sif temp_high = 243.15 // -30c temp_low = 233.15 // -40c light_modifier = 0.3 - flight_falure_modifier = 10 + flight_failure_modifier = 10 transition_chances = list( WEATHER_RAIN = 45, WEATHER_STORM = 40, @@ -256,7 +256,7 @@ datum/weather/sif if(L.z in holder.our_planet.expected_z_levels) var/turf/T = get_turf(L) if(!T.outdoors) - return // They're indoors, so no need to rain on them. + continue // They're indoors, so no need to rain on them. L.water_act(2) to_chat(L, "Rain falls on you, drenching you in water.") @@ -267,7 +267,7 @@ datum/weather/sif temp_high = T0C // 0c temp_low = 243.15 // -30c light_modifier = 0.3 - flight_falure_modifier = 15 + flight_failure_modifier = 15 transition_chances = list( WEATHER_RAIN = 45, WEATHER_STORM = 10, @@ -280,17 +280,17 @@ datum/weather/sif if(L.z in holder.our_planet.expected_z_levels) var/turf/T = get_turf(L) if(!T.outdoors) - return // They're indoors, so no need to pelt them with ice. + continue // They're indoors, so no need to pelt them with ice. var/target_zone = pick(BP_ALL) var/amount_blocked = L.run_armor_check(target_zone, "melee") var/amount_soaked = L.get_armor_soak(target_zone, "melee") if(amount_blocked >= 100) - return // No need to apply damage. + continue // No need to apply damage. if(amount_soaked >= 10) - return // No need to apply damage. + continue // No need to apply damage. L.apply_damage(rand(5, 10), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail") to_chat(L, "The hail raining down on you [L.can_feel_pain() ? "hurts" : "damages you"]!") @@ -299,7 +299,7 @@ datum/weather/sif name = "blood moon" light_modifier = 0.5 light_color = "#FF0000" - flight_falure_modifier = 25 + flight_failure_modifier = 25 transition_chances = list( WEATHER_BLOODMOON = 100 - ) \ No newline at end of file + ) diff --git a/code/modules/planet/weather.dm b/code/modules/planet/weather.dm index 57995f7f75..512981d44e 100644 --- a/code/modules/planet/weather.dm +++ b/code/modules/planet/weather.dm @@ -59,7 +59,7 @@ var/temp_low = T0C var/light_modifier = 1.0 // Lower numbers means more darkness. var/light_color = null // If set, changes how the day/night light looks. - var/flight_falure_modifier = 0 // Some types of weather make flying harder, and therefore make crashes more likely. + var/flight_failure_modifier = 0 // Some types of weather make flying harder, and therefore make crashes more likely. var/transition_chances = list() // Assoc list var/datum/weather_holder/holder = null diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 09233d166c..a5666d2795 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -56,6 +56,9 @@ /obj/machinery/power/apc/hyper cell_type = /obj/item/weapon/cell/hyper +/obj/machinery/power/apc/alarms_hidden + alarms_hidden = TRUE + /obj/machinery/power/apc name = "area power controller" desc = "A control terminal for the area electrical systems." @@ -112,6 +115,7 @@ var/global/list/status_overlays_equipment var/global/list/status_overlays_lighting var/global/list/status_overlays_environ + var/alarms_hidden = FALSE //If power alarms from this APC are visible on consoles /obj/machinery/power/apc/updateDialog() if (stat & (BROKEN|MAINT)) @@ -223,6 +227,10 @@ src.area = get_area_name(areastring) name = "\improper [area.name] APC" area.apc = src + + if(istype(area, /area/submap)) + alarms_hidden = TRUE + update_icon() make_terminal() @@ -1108,7 +1116,7 @@ equipment = autoset(equipment, 0) lighting = autoset(lighting, 0) environ = autoset(environ, 0) - power_alarm.triggerAlarm(loc, src) + power_alarm.triggerAlarm(loc, src, hidden=alarms_hidden) autoflag = 0 // update icon & area power if anything changed @@ -1138,21 +1146,21 @@ equipment = autoset(equipment, 2) lighting = autoset(lighting, 1) environ = autoset(environ, 1) - power_alarm.triggerAlarm(loc, src) + power_alarm.triggerAlarm(loc, src, hidden=alarms_hidden) autoflag = 2 else if(cell.percent() <= 15) // <15%, turn off lighting & equipment if((autoflag > 1 && longtermpower < 0) || (autoflag > 1 && longtermpower >= 0)) equipment = autoset(equipment, 2) lighting = autoset(lighting, 2) environ = autoset(environ, 1) - power_alarm.triggerAlarm(loc, src) + power_alarm.triggerAlarm(loc, src, hidden=alarms_hidden) autoflag = 1 else // zero charge, turn all off if(autoflag != 0) equipment = autoset(equipment, 0) lighting = autoset(lighting, 0) environ = autoset(environ, 0) - power_alarm.triggerAlarm(loc, src) + power_alarm.triggerAlarm(loc, src, hidden=alarms_hidden) autoflag = 0 // val 0=off, 1=off(auto) 2=on 3=on(auto) diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index f2b763c9bc..d1189f25fb 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -214,6 +214,7 @@ terminal = new /obj/machinery/power/terminal(tempLoc) terminal.set_dir(tempDir) terminal.master = src + terminal.connect_to_network() return 0 return 1 @@ -265,7 +266,6 @@ user.visible_message(\ "[user.name] has added cables to the [src].",\ "You added cables to the [src].") - terminal.connect_to_network() stat = 0 return 0 diff --git a/code/modules/power/smes_construction.dm b/code/modules/power/smes_construction.dm index 2e8102de81..6a4aa9c276 100644 --- a/code/modules/power/smes_construction.dm +++ b/code/modules/power/smes_construction.dm @@ -1,6 +1,6 @@ // BUILDABLE SMES(Superconducting Magnetic Energy Storage) UNIT // -// Last Change 1.26.2018 by Neerti. Also signing this is dumb. +// Last Change 2.8.2018 by Neerti. Also signing this is still dumb. // // This is subtype of SMES that should be normally used. It can be constructed, deconstructed and hacked. // It also supports RCON System which allows you to operate it remotely, if properly set. @@ -8,7 +8,7 @@ //MAGNETIC COILS - These things actually store and transmit power within the SMES. Different types have different /obj/item/weapon/smes_coil name = "superconductive magnetic coil" - desc = "Standard superconductive magnetic coil with average capacity and I/O rating." + desc = "The standard superconductive magnetic coil, with average capacity and I/O rating." icon = 'icons/obj/stock_parts.dmi' icon_state = "smes_coil" // Just few icons patched together. If someone wants to make better icon, feel free to do so! w_class = ITEMSIZE_LARGE // It's LARGE (backpack size) @@ -18,21 +18,21 @@ // 20% Charge Capacity, 60% I/O Capacity. Used for substation/outpost SMESs. /obj/item/weapon/smes_coil/weak name = "basic superconductive magnetic coil" - desc = "Cheaper model of standard superconductive magnetic coil. It's capacity and I/O rating are considerably lower." + desc = "A cheaper model of superconductive magnetic coil. Its capacity and I/O rating are considerably lower." ChargeCapacity = 1200000 // 20 kWh IOCapacity = 150000 // 150 kW // 1000% Charge Capacity, 20% I/O Capacity /obj/item/weapon/smes_coil/super_capacity name = "superconductive capacitance coil" - desc = "Specialised version of standard superconductive magnetic coil. This one has significantly stronger containment field, allowing for significantly larger power storage. It's IO rating is much lower, however." + desc = "A specialised type of superconductive magnetic coil with a significantly stronger containment field, allowing for larger power storage. Its IO rating is much lower, however." ChargeCapacity = 60000000 // 1000 kWh IOCapacity = 50000 // 50 kW // 10% Charge Capacity, 400% I/O Capacity. Technically turns SMES into large super capacitor.Ideal for shields. /obj/item/weapon/smes_coil/super_io name = "superconductive transmission coil" - desc = "Specialised version of standard superconductive magnetic coil. While this one won't store almost any power, it rapidly transfers power, making it useful in systems which require large throughput." + desc = "A specialised type of superconductive magnetic coil with reduced storage capabilites but vastly improved power transmission capabilities, making it useful in systems which require large throughput." ChargeCapacity = 600000 // 10 kWh IOCapacity = 1000000 // 1000 kW @@ -58,7 +58,11 @@ // Pre-installed and pre-charged SMES hidden from the station, for use in submaps. /obj/machinery/power/smes/buildable/point_of_interest/New() ..(1) - charge = 1e6 // Should be enough for an individual POI. + charge = 1e7 // Should be enough for an individual POI. + RCon = FALSE + input_level = input_level_max + output_level = output_level_max + input_attempt = TRUE @@ -106,7 +110,7 @@ if(RCon) ..() else // RCON wire cut - usr << "Connection error: Destination Unreachable." + to_chat(usr, "Connection error: Destination Unreachable.") // Cyborgs standing next to the SMES can play with the wiring. if(istype(usr, /mob/living/silicon/robot) && Adjacent(usr) && open_hatch) @@ -118,7 +122,7 @@ /obj/machinery/power/smes/buildable/New(var/install_coils = 1) component_parts = list() component_parts += new /obj/item/stack/cable_coil(src,30) - src.wires = new /datum/wires/smes(src) + wires = new /datum/wires/smes(src) // Allows for mapped-in SMESs with larger capacity/IO if(install_coils) @@ -149,13 +153,12 @@ output_level_max += C.IOCapacity charge = between(0, charge, capacity) return 1 - else - return 0 + return 0 // Proc: total_system_failure() // Parameters: 2 (intensity - how strong the failure is, user - person which caused the failure) // Description: Checks the sensors for alerts. If change (alerts cleared or detected) occurs, calls for icon update. -/obj/machinery/power/smes/buildable/proc/total_system_failure(var/intensity = 0, var/mob/user as mob) +/obj/machinery/power/smes/buildable/proc/total_system_failure(var/intensity = 0, var/mob/user) // SMESs store very large amount of power. If someone screws up (ie: Disables safeties and attempts to modify the SMES) very bad things happen. // Bad things are based on charge percentage. // Possible effects: @@ -169,11 +172,9 @@ if (!intensity) return - var/mob/living/carbon/human/h_user = null - if (!istype(user, /mob/living/carbon/human)) + var/mob/living/carbon/human/h_user = user + if (!istype(h_user)) return - else - h_user = user // Preparations @@ -187,97 +188,92 @@ log_game("SMES FAILURE: [src.x]X [src.y]Y [src.z]Z User: [usr.ckey], Intensity: [intensity]/100") message_admins("SMES FAILURE: [src.x]X [src.y]Y [src.z]Z User: [usr.ckey], Intensity: [intensity]/100 - JMP") + var/used_hand = h_user.hand?"l_hand":"r_hand" switch (intensity) if (0 to 15) // Small overcharge // Sparks, Weak shock s.set_up(2, 1, src) - s.start() if (user_protected && prob(80)) - h_user << "Small electrical arc almost burns your hand. Luckily you had your gloves on!" + to_chat(h_user, "A small electrical arc almost burns your hand. Luckily you had your gloves on!") else - h_user << "Small electrical arc sparks and burns your hand as you touch the [src]!" - h_user.adjustFireLoss(rand(5,10)) - h_user.Paralyse(2) - charge = 0 + to_chat(h_user, "A small electrical arc sparks and burns your hand as you touch the [src]!") + h_user.adjustFireLossByPart(rand(5,10), used_hand) + h_user.Weaken(2) if (16 to 35) // Medium overcharge // Sparks, Medium shock, Weak EMP s.set_up(4,1,src) - s.start() if (user_protected && prob(25)) - h_user << "Medium electrical arc sparks and almost burns your hand. Luckily you had your gloves on!" + to_chat(h_user, "A medium electrical arc sparks and almost burns your hand. Luckily you had your gloves on!") else - h_user << "Medium electrical sparks as you touch the [src], severely burning your hand!" - h_user.adjustFireLoss(rand(10,25)) - h_user.Paralyse(5) - spawn(0) - empulse(src.loc, 1, 2, 3, 4) - charge = 0 + to_chat(h_user, "A medium electrical arc sparks as you touch the [src], severely burning your hand!") + h_user.adjustFireLossByPart(rand(10,25), used_hand) + h_user.Weaken(5) + spawn() + empulse(get_turf(src), 1, 2, 3, 4) if (36 to 60) // Strong overcharge // Sparks, Strong shock, Strong EMP, 10% light overload. 1% APC failure s.set_up(7,1,src) - s.start() if (user_protected) - h_user << "Strong electrical arc sparks between you and [src], ignoring your gloves and burning your hand!" - h_user.adjustFireLoss(rand(25,60)) - h_user.Paralyse(8) + to_chat(h_user, "A strong electrical arc sparks between you and [src], ignoring your gloves and burning your hand!") + h_user.adjustFireLossByPart(rand(25,60), used_hand) + h_user.Weaken(8) else - h_user << "Strong electrical arc sparks between you and [src], knocking you out for a while!" - h_user.adjustFireLoss(rand(35,75)) - h_user.Paralyse(12) - spawn(0) - empulse(src.loc, 6, 8, 12, 16) - charge = 0 + to_chat(h_user, "A strong electrical arc sparks between you and [src], knocking you out for a while!") + h_user.electrocute_act(rand(35,75), src, def_zone = BP_TORSO) + spawn() + empulse(get_turf(src), 6, 8, 12, 16) apcs_overload(1, 10) - src.ping("Caution. Output regulators malfunction. Uncontrolled discharge detected.") + ping("Caution. Output regulator malfunction. Uncontrolled discharge detected.") if (61 to INFINITY) // Massive overcharge // Sparks, Near - instantkill shock, Strong EMP, 25% light overload, 5% APC failure. 50% of SMES explosion. This is bad. s.set_up(10,1,src) - s.start() - h_user << "Massive electrical arc sparks between you and [src]. Last thing you can think about is \"Oh shit...\"" + to_chat(h_user, "A massive electrical arc sparks between you and [src]. The last thing you can think about is \"Oh shit...\"") // Remember, we have few gigajoules of electricity here.. Turn them into crispy toast. - h_user.adjustFireLoss(rand(150,195)) - h_user.Paralyse(25) - spawn(0) - empulse(src.loc, 32, 64) - charge = 0 + h_user.electrocute_act(rand(150,195), src, def_zone = BP_TORSO) + spawn() + empulse(get_turf(src), 32, 64) apcs_overload(5, 25) - src.ping("Caution. Output regulators malfunction. Significant uncontrolled discharge detected.") + ping("Caution. Output regulator malfunction. Significant uncontrolled discharge detected.") if (prob(50)) // Added admin-notifications so they can stop it when griffed. log_game("SMES explosion imminent.") message_admins("SMES explosion imminent.") - src.ping("DANGER! Magnetic containment field unstable! Containment field failure imminent!") + ping("DANGER! Magnetic containment field unstable! Containment field failure imminent!") failing = 1 + update_icon() // 30 - 60 seconds and then BAM! spawn(rand(300,600)) if(!failing) // Admin can manually set this var back to 0 to stop overload, for use when griffed. update_icon() - src.ping("Magnetic containment stabilised.") + ping("Magnetic containment stabilised.") return - src.ping("DANGER! Magnetic containment field failure in 3 ... 2 ... 1 ...") - explosion(src.loc,1,2,4,8) + ping("DANGER! Magnetic containment field failure in 3 ... 2 ... 1 ...") + explosion(get_turf(src),1,2,4,8) // Not sure if this is necessary, but just in case the SMES *somehow* survived.. qdel(src) + s.start() + charge = 0 + // Proc: apcs_overload() // Parameters: 2 (failure_chance - chance to actually break the APC, overload_chance - Chance of breaking lights) // Description: Damages output powernet by power surge. Destroys few APCs and lights, depending on parameters. /obj/machinery/power/smes/buildable/proc/apcs_overload(var/failure_chance, var/overload_chance) - if (!src.powernet) + if (!powernet) return - for(var/obj/machinery/power/terminal/T in src.powernet.nodes) + for(var/obj/machinery/power/terminal/T in powernet.nodes) if(istype(T.master, /obj/machinery/power/apc)) var/obj/machinery/power/apc/A = T.master if (prob(overload_chance)) @@ -301,7 +297,7 @@ /obj/machinery/power/smes/buildable/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) // No more disassembling of overloaded SMESs. You broke it, now enjoy the consequences. if (failing) - user << "The [src]'s screen is flashing with alerts. It seems to be overloaded! Touching it now is probably not a good idea." + to_chat(user, "The [src]'s indicator lights are flashing wildly. It seems to be overloaded! Touching it now is probably not a good idea.") return // If parent returned 1: // - Hatch is open, so we can modify the SMES @@ -313,15 +309,15 @@ var/newtag = input(user, "Enter new RCON tag. Use \"NO_TAG\" to disable RCON or leave empty to cancel.", "SMES RCON system") as text if(newtag) RCon_tag = newtag - user << "You changed the RCON tag to: [newtag]" + to_chat(user, "You changed the RCON tag to: [newtag]") return // Charged above 1% and safeties are enabled. if((charge > (capacity/100)) && safeties_enabled) - user << "Safety circuit of [src] is preventing modifications while it's charged!" + to_chat(user, "The safety circuit of [src] is preventing modifications while there is charge stored!") return if (output_attempt || input_attempt) - user << "Turn off the [src] first!" + to_chat(user, "Turn off the [src] first!") return // Probability of failure if safety circuit is disabled (in %) @@ -334,29 +330,19 @@ // Crowbar - Disassemble the SMES. if(istype(W, /obj/item/weapon/crowbar)) if (terminal) - user << "You have to disassemble the terminal first!" + to_chat(user, "You have to disassemble the terminal first!") return playsound(get_turf(src), W.usesound, 50, 1) - user << "You begin to disassemble the [src]!" + to_chat(user, "You begin to disassemble the [src]!") if (do_after(usr, (100 * cur_coils) * W.toolspeed)) // More coils = takes longer to disassemble. It's complex so largest one with 5 coils will take 50s with a normal crowbar if (failure_probability && prob(failure_probability)) total_system_failure(failure_probability, user) return - usr << "You have disassembled the SMES cell!" - var/obj/structure/frame/M = new /obj/structure/frame(src.loc) - M.frame_type = new /datum/frame/frame_types/machine - M.anchored = 1 - var/obj/item/weapon/circuitboard/C = new /obj/item/weapon/circuitboard/smes - M.circuit = C - M.state = 2 - M.icon_state = "machine_1" - for(var/obj/I in component_parts) - I.loc = src.loc - component_parts -= I - qdel(src) + to_chat(user, "You have disassembled the SMES cell!") + dismantle() return // Superconducting Magnetic Coil - Upgrade the SMES @@ -367,14 +353,14 @@ total_system_failure(failure_probability, user) return - usr << "You install the coil into the SMES unit!" + to_chat(user, "You install the coil into the SMES unit!") user.drop_item() cur_coils ++ component_parts += W W.loc = src recalc_coils() else - usr << "You can't insert more coils to this SMES unit!" + to_chat(user, "You can't insert more coils into this SMES unit!") // Proc: toggle_input() // Parameters: None diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 460fac8239..47fe3d2eaf 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -18,7 +18,7 @@ if(propname == "mode_name") name = propvalue - if(isnull(propvalue)) + else if(isnull(propvalue)) settings[propname] = gun.vars[propname] //better than initial() as it handles list vars like burst_accuracy else settings[propname] = propvalue @@ -61,13 +61,14 @@ var/recoil = 0 //screen shake var/silenced = 0 var/muzzle_flash = 3 - var/accuracy = 0 //accuracy is measured in tiles. +1 accuracy means that everything is effectively one tile closer for the purpose of miss chance, -1 means the opposite. launchers are not supported, at the moment. + var/accuracy = 0 //Accuracy is measured in percents. +15 accuracy means that everything is effectively one tile closer for the purpose of miss chance, -15 means the opposite. launchers are not supported, at the moment. var/scoped_accuracy = null var/list/burst_accuracy = list(0) //allows for different accuracies for each shot in a burst. Applied on top of accuracy var/list/dispersion = list(0) var/mode_name = null - var/requires_two_hands - var/wielded_icon = "gun_wielded" + var/projectile_type = /obj/item/projectile //On ballistics, only used to check for the cham gun + + var/wielded_item_state var/one_handed_penalty = 0 // Penalty applied if someone fires a two-handed gun with one hand. var/obj/screen/auto_target/auto_target var/shooting = 0 @@ -135,19 +136,32 @@ verbs -= /obj/item/weapon/gun/verb/give_dna verbs -= /obj/item/weapon/gun/verb/allow_dna -/obj/item/weapon/gun/update_held_icon() - if(requires_two_hands) +/obj/item/weapon/gun/update_twohanding() + if(one_handed_penalty) var/mob/living/M = loc if(istype(M)) - if(M.item_is_in_hands(src) && !M.hands_are_full()) + if(M.can_wield_item(src) && src.is_held_twohanded(M)) name = "[initial(name)] (wielded)" - item_state = wielded_icon else name = initial(name) - item_state = initial(item_state) - update_icon(ignore_inhands=1) // In case item_state is set somewhere else. + else + name = initial(name) + update_icon() // In case item_state is set somewhere else. ..() +/obj/item/weapon/gun/update_held_icon() + if(wielded_item_state) + var/mob/living/M = loc + if(istype(M)) + if(M.can_wield_item(src) && src.is_held_twohanded(M)) + item_state_slots[slot_l_hand_str] = wielded_item_state + item_state_slots[slot_r_hand_str] = wielded_item_state + else + item_state_slots[slot_l_hand_str] = initial(item_state) + item_state_slots[slot_r_hand_str] = initial(item_state) + ..() + + //Checks whether a given mob can use the gun //Any checks that shouldn't result in handle_click_empty() being called if they fail should go here. //Otherwise, if you want handle_click_empty() to be called, check in consume_next_projectile() and return null there. @@ -274,6 +288,7 @@ verbs -= /obj/item/weapon/gun/verb/allow_dna else user << "\The [src] is not accepting modifications at this time." + ..() /obj/item/weapon/gun/emag_act(var/remaining_charges, var/mob/user) if(dna_lock && attached_lock.controller_lock) @@ -317,6 +332,7 @@ /obj/item/weapon/gun/proc/Fire(atom/target, mob/living/user, clickparams, pointblank=0, reflex=0) if(!user || !target) return + if(target.z != user.z) return add_fingerprint(user) @@ -338,12 +354,7 @@ next_fire_time = world.time + shoot_time - var/held_acc_mod = 0 - var/held_disp_mod = 0 - if(requires_two_hands) - if(user.item_is_in_hands(src) && user.hands_are_full()) - held_acc_mod = held_acc_mod - one_handed_penalty - held_disp_mod = held_disp_mod - round(one_handed_penalty / 2) + var/held_twohanded = (user.can_wield_item(src) && src.is_held_twohanded(user)) //actually attempt to shoot var/turf/targloc = get_turf(target) //cache this in case target gets deleted during shooting, e.g. if it was a securitron that got destroyed. @@ -373,9 +384,7 @@ handle_click_empty(user) break - var/acc = burst_accuracy[min(i, burst_accuracy.len)] + held_acc_mod - var/disp = dispersion[min(i, dispersion.len)] + held_disp_mod - process_accuracy(projectile, user, target, acc, disp) + process_accuracy(projectile, user, target, i, held_twohanded) if(pointblank) process_point_blank(projectile, user, target) @@ -397,10 +406,9 @@ shooting = 0 */ // We do this down here, so we don't get the message if we fire an empty gun. - if(requires_two_hands) - if(user.item_is_in_hands(src) && user.hands_are_full()) - if(one_handed_penalty >= 2) - user << "You struggle to keep \the [src] pointed at the correct position with just one hand!" + if(user.item_is_in_hands(src) && user.hands_are_full()) + if(one_handed_penalty >= 20) + to_chat(user, "You struggle to keep \the [src] pointed at the correct position with just one hand!") if(reflex) admin_attack_log(user, target, attacker_message = "fired [src] by reflex.", victim_message = "triggered a reflex shot from [src].", admin_message = "shot [target], who triggered gunfire ([src]) by reflex)") @@ -519,25 +527,45 @@ //called after successfully firing /obj/item/weapon/gun/proc/handle_post_fire(mob/user, atom/target, var/pointblank=0, var/reflex=0) if(silenced) - playsound(user, fire_sound, 10, 1) - to_chat(user, "You fire \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]") - for(var/mob/living/L in oview(2,user)) - if(L.stat) - continue - if(L.blinded) - to_chat(L, "You hear a [fire_sound_text]!") - continue - to_chat(L, "[user] fires \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]") - else - playsound(user, fire_sound, 50, 1) - user.visible_message( - "[user] fires \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]", - "You fire \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]", - "You hear a [fire_sound_text]!" - ) + if(reflex) + user.visible_message( + "\The [user] fires \the [src][pointblank ? " point blank at \the [target]":""] by reflex!", + "You fire \the [src] by reflex!", + "You hear a [fire_sound_text]!" + ) + else + user.visible_message( + "\The [user] fires \the [src][pointblank ? " point blank at \the [target]":""]!", + "You fire \the [src]!", + "You hear a [fire_sound_text]!" + ) - if(muzzle_flash) - set_light(muzzle_flash) + if(muzzle_flash) + set_light(muzzle_flash) + + if(one_handed_penalty) + if(!src.is_held_twohanded(user)) + switch(one_handed_penalty) + if(1 to 15) + if(prob(50)) //don't need to tell them every single time + to_chat(user, "Your aim wavers slightly.") + if(16 to 30) + to_chat(user, "Your aim wavers as you fire \the [src] with just one hand.") + if(31 to 45) + to_chat(user, "You have trouble keeping \the [src] on target with just one hand.") + if(46 to INFINITY) + to_chat(user, "You struggle to keep \the [src] on target with just one hand!") + else if(!user.can_wield_item(src)) + switch(one_handed_penalty) + if(1 to 15) + if(prob(50)) //don't need to tell them every single time + to_chat(user, "Your aim wavers slightly.") + if(16 to 30) + to_chat(user, "Your aim wavers as you try to hold \the [src] steady.") + if(31 to 45) + to_chat(user, "You have trouble holding \the [src] steady.") + if(46 to INFINITY) + to_chat(user, "You struggle to hold \the [src] steady!") if(recoil) spawn() @@ -566,29 +594,37 @@ damage_mult = 1.5 P.damage *= damage_mult -/obj/item/weapon/gun/proc/process_accuracy(obj/projectile, mob/living/user, atom/target, acc_mod, dispersion) +/obj/item/weapon/gun/proc/process_accuracy(obj/projectile, mob/living/user, atom/target, var/burst, var/held_twohanded) var/obj/item/projectile/P = projectile if(!istype(P)) return //default behaviour only applies to true projectiles + var/acc_mod = burst_accuracy[min(burst, burst_accuracy.len)] + var/disp_mod = dispersion[min(burst, dispersion.len)] + + if(one_handed_penalty) + if(!held_twohanded) + acc_mod += -ceil(one_handed_penalty/2) + disp_mod += one_handed_penalty*0.5 //dispersion per point of two-handedness + //Accuracy modifiers P.accuracy = accuracy + acc_mod - P.dispersion = dispersion + P.dispersion = disp_mod // Certain statuses make it harder to aim, blindness especially. Same chances as melee, however guns accuracy uses multiples of 15. if(user.eye_blind) - P.accuracy -= 5 + P.accuracy -= 75 if(user.eye_blurry) - P.accuracy -= 2 + P.accuracy -= 30 if(user.confused) - P.accuracy -= 3 + P.accuracy -= 45 //accuracy bonus from aiming if (aim_targets && (target in aim_targets)) //If you aim at someone beforehead, it'll hit more often. //Kinda balanced by fact you need like 2 seconds to aim //As opposed to no-delay pew pew - P.accuracy += 2 + P.accuracy += 30 // Some modifiers make it harder or easier to hit things. for(var/datum/modifier/M in user.modifiers) @@ -618,17 +654,24 @@ y_offset = rand(-1,1) x_offset = rand(-1,1) - return !P.launch_from_gun(target, user, src, target_zone, x_offset, y_offset) + var/launched = !P.launch_from_gun(target, user, src, target_zone, x_offset, y_offset) -//apart of reskins that have two sprites, touching may result in frustration and breaks -/obj/item/weapon/gun/projectile/colt/detective/attack_hand(var/mob/living/user) - if(!unique_reskin && loc == user) - reskin_gun(user) - return - ..() + if(launched) + play_fire_sound(user, P) + + return launched + + +/obj/item/weapon/gun/proc/play_fire_sound(var/mob/user, var/obj/item/projectile/P) + var/shot_sound = (istype(P) && P.fire_sound)? P.fire_sound : fire_sound + if(silenced) + playsound(user, shot_sound, 10, 1) + else + playsound(user, shot_sound, 50, 1) //Suicide handling. /obj/item/weapon/gun/var/mouthshoot = 0 //To stop people from suiciding twice... >.> + /obj/item/weapon/gun/proc/handle_suicide(mob/living/user) if(!ishuman(user)) return @@ -643,10 +686,11 @@ var/obj/item/projectile/in_chamber = consume_next_projectile() if (istype(in_chamber)) user.visible_message("[user] pulls the trigger.") + var/shot_sound = in_chamber.fire_sound? in_chamber.fire_sound : fire_sound if(silenced) - playsound(user, fire_sound, 10, 1) + playsound(user, shot_sound, 10, 1) else - playsound(user, fire_sound, 50, 1) + playsound(user, shot_sound, 50, 1) if(istype(in_chamber, /obj/item/projectile/beam/lastertag)) user.show_message("You feel rather silly, trying to commit suicide with a toy.") mouthshoot = 0 @@ -692,7 +736,7 @@ ..() if(firemodes.len > 1) var/datum/firemode/current_mode = firemodes[sel_mode] - user << "The fire selector is set to [current_mode.name]." + to_chat(user, "The fire selector is set to [current_mode.name].") /obj/item/weapon/gun/proc/switch_firemodes(mob/user) if(firemodes.len <= 1) @@ -703,7 +747,7 @@ sel_mode = 1 var/datum/firemode/new_mode = firemodes[sel_mode] new_mode.apply_to(src) - user << "\The [src] is now set to [mode_name]." + to_chat(user, "\The [src] is now set to [new_mode.name].") return new_mode diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 447eefe1b8..207d64e6f6 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -7,8 +7,10 @@ var/obj/item/weapon/cell/power_supply //What type of power cell this uses var/charge_cost = 240 //How much energy is needed to fire. + var/cell_type = /obj/item/weapon/cell/device/weapon - var/projectile_type = /obj/item/projectile/beam/practice + projectile_type = /obj/item/projectile/beam/practice + var/modifystate var/charge_meter = 1 //if set, the icon state will be chosen based on the current charge diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index d7ef652b2f..7fa20d8c5d 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -4,7 +4,7 @@ switch between standard fire and a more efficent but weaker 'suppressive' fire." icon_state = "laser" item_state = "laser" - fire_sound = 'sound/weapons/Laser.ogg' + wielded_item_state = "laser-wielded" fire_delay = 8 slot_flags = SLOT_BELT|SLOT_BACK w_class = ITEMSIZE_LARGE @@ -12,8 +12,7 @@ origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 2) matter = list(DEFAULT_WALL_MATERIAL = 2000) projectile_type = /obj/item/projectile/beam/midlaser -// requires_two_hands = 1 - one_handed_penalty = 2 +// one_handed_penalty = 30 firemodes = list( list(mode_name="normal", fire_delay=8, projectile_type=/obj/item/projectile/beam/midlaser, charge_cost = 240), @@ -23,7 +22,7 @@ /obj/item/weapon/gun/energy/laser/mounted self_recharge = 1 use_external_power = 1 - requires_two_hands = 0 // Not sure if two-handing gets checked for mounted weapons, but better safe than sorry. + one_handed_penalty = 0 // Not sure if two-handing gets checked for mounted weapons, but better safe than sorry. /obj/item/weapon/gun/energy/laser/practice name = "practice laser carbine" @@ -43,7 +42,6 @@ icon_state = "retro" item_state = "retro" desc = "An older model of the basic lasergun. Nevertheless, it is still quite deadly and easy to maintain, making it a favorite amongst pirates and other outlaws." - fire_sound = 'sound/weapons/Laser.ogg' slot_flags = SLOT_BELT w_class = ITEMSIZE_NORMAL projectile_type = /obj/item/projectile/beam @@ -79,7 +77,6 @@ item_state = "caplaser" desc = "A rare weapon, handcrafted by a now defunct specialty manufacturer on Luna for a small fortune. It's certainly aged well." force = 5 - fire_sound = 'sound/weapons/Laser.ogg' slot_flags = SLOT_BELT w_class = ITEMSIZE_NORMAL projectile_type = /obj/item/projectile/beam @@ -95,15 +92,13 @@ flux in a nuclear reactor core. This incredible technology may help YOU achieve high excitation rates with small laser volumes!" icon_state = "lasercannon" item_state = null - fire_sound = 'sound/weapons/lasercannonfire.ogg' origin_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3, TECH_POWER = 3) slot_flags = SLOT_BELT|SLOT_BACK projectile_type = /obj/item/projectile/beam/heavylaser/cannon battery_lock = 1 fire_delay = 20 w_class = ITEMSIZE_LARGE -// requires_two_hands = 1 - one_handed_penalty = 6 // The thing's heavy and huge. +// one_handed_penalty = 90 // The thing's heavy and huge. accuracy = 3 charge_cost = 600 @@ -113,7 +108,7 @@ use_external_power = 1 recharge_time = 10 accuracy = 0 // Mounted cannons are just fine the way they are. - requires_two_hands = 0 // Not sure if two-handing gets checked for mounted weapons, but better safe than sorry. + one_handed_penalty = 0 // Not sure if two-handing gets checked for mounted weapons, but better safe than sorry. projectile_type = /obj/item/projectile/beam/heavylaser charge_cost = 400 fire_delay = 20 @@ -124,7 +119,6 @@ standard photonic beams, resulting in an effective 'anti-armor' energy weapon." icon_state = "xray" item_state = "xray" - fire_sound = 'sound/weapons/eluger.ogg' origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 3, TECH_MAGNET = 2) projectile_type = /obj/item/projectile/beam/xray charge_cost = 200 @@ -145,10 +139,10 @@ fire_delay = 35 force = 10 w_class = ITEMSIZE_HUGE // So it can't fit in a backpack. - accuracy = -3 //shooting at the hip + accuracy = -45 //shooting at the hip scoped_accuracy = 0 // requires_two_hands = 1 - one_handed_penalty = 4 // The weapon itself is heavy, and the long barrel makes it hard to hold steady with just one hand. +// one_handed_penalty = 60 // The weapon itself is heavy, and the long barrel makes it hard to hold steady with just one hand. /obj/item/weapon/gun/energy/sniperrifle/verb/scope() set category = "Object" @@ -165,7 +159,6 @@ desc = "Standard issue weapon of the Imperial Guard" origin_tech = list(TECH_COMBAT = 1, TECH_MAGNET = 2) matter = list(DEFAULT_WALL_MATERIAL = 2000) - fire_sound = 'sound/weapons/Laser.ogg' projectile_type = /obj/item/projectile/beam/lastertag/blue cell_type = /obj/item/weapon/cell/device/weapon/recharge battery_lock = 1 diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm index 048dddfe3f..e7e19b9e02 100644 --- a/code/modules/projectiles/guns/energy/nuclear.dm +++ b/code/modules/projectiles/guns/energy/nuclear.dm @@ -3,7 +3,6 @@ desc = "Another bestseller of Lawson Arms and the FTU, the LAEP90 Perun is a versatile energy based sidearm, capable of switching between low and high capacity projectile settings. In other words: Stun or Kill." icon_state = "energystun100" item_state = null //so the human update icon uses the icon_state instead. - fire_sound = 'sound/weapons/Taser.ogg' fire_delay = 10 // Handguns should be inferior to two-handed weapons. projectile_type = /obj/item/projectile/beam/stun/med @@ -11,8 +10,8 @@ modifystate = "energystun" firemodes = list( - list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun/med, modifystate="energystun", fire_sound='sound/weapons/Taser.ogg', charge_cost = 240), - list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, modifystate="energykill", fire_sound='sound/weapons/Laser.ogg', charge_cost = 480), + list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun/med, modifystate="energystun", charge_cost = 240), + list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, modifystate="energykill", charge_cost = 480), ) /obj/item/weapon/gun/energy/gun/mounted @@ -26,7 +25,6 @@ desc = "The FM-2t is a versatile energy based weapon, capable of switching between stun or kill with a three round burst option for both settings." icon_state = "fm-2tstun100" //May resprite this to be more rifley item_state = null //so the human update icon uses the icon_state instead. - fire_sound = 'sound/weapons/Taser.ogg' charge_cost = 100 force = 8 w_class = ITEMSIZE_LARGE //Probably gonna make it a rifle sooner or later @@ -37,13 +35,13 @@ modifystate = "fm-2tstun" // requires_two_hands = 1 - one_handed_penalty = 2 +// one_handed_penalty = 30 firemodes = list( - list(mode_name="stun", burst=1, projectile_type=/obj/item/projectile/beam/stun/weak, modifystate="fm-2tstun", fire_sound='sound/weapons/Taser.ogg', charge_cost = 100), - list(mode_name="stun burst", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,0,0), dispersion=list(0.0, 0.2, 0.5), projectile_type=/obj/item/projectile/beam/stun/weak, modifystate="fm-2tstun", fire_sound='sound/weapons/Taser.ogg'), - list(mode_name="lethal", burst=1, projectile_type=/obj/item/projectile/beam/burstlaser, modifystate="fm-2tkill", fire_sound='sound/weapons/Laser.ogg', charge_cost = 200), - list(mode_name="lethal burst", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,0,0), dispersion=list(0.0, 0.2, 0.5), projectile_type=/obj/item/projectile/beam/burstlaser, modifystate="fm-2tkill", fire_sound='sound/weapons/Laser.ogg'), + list(mode_name="stun", burst=1, projectile_type=/obj/item/projectile/beam/stun/weak, modifystate="fm-2tstun", charge_cost = 100), + list(mode_name="stun burst", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,0,0), dispersion=list(0.0, 0.2, 0.5), projectile_type=/obj/item/projectile/beam/stun/weak, modifystate="fm-2tstun"), + list(mode_name="lethal", burst=1, projectile_type=/obj/item/projectile/beam/burstlaser, modifystate="fm-2tkill", charge_cost = 200), + list(mode_name="lethal burst", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,0,0), dispersion=list(0.0, 0.2, 0.5), projectile_type=/obj/item/projectile/beam/burstlaser, modifystate="fm-2tkill"), ) /obj/item/weapon/gun/energy/gun/nuclear @@ -61,9 +59,9 @@ modifystate = null // requires_two_hands = 1 - one_handed_penalty = 1 // It's rather bulky, so holding it in one hand is a little harder than with two, however it's not 'required'. +// one_handed_penalty = 15 // It's rather bulky, so holding it in one hand is a little harder than with two, however it's not 'required'. firemodes = list( - list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun, modifystate="nucgunstun", fire_sound='sound/weapons/Taser.ogg', charge_cost = 240), - list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, modifystate="nucgunkill", fire_sound='sound/weapons/Laser.ogg', charge_cost = 480), + list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun, modifystate="nucgunstun", charge_cost = 240), + list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, modifystate="nucgunkill", charge_cost = 480), ) \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/pulse.dm b/code/modules/projectiles/guns/energy/pulse.dm index 2bcb2db771..6513a00052 100644 --- a/code/modules/projectiles/guns/energy/pulse.dm +++ b/code/modules/projectiles/guns/energy/pulse.dm @@ -5,15 +5,14 @@ item_state = null //so the human update icon uses the icon_state instead. slot_flags = SLOT_BELT|SLOT_BACK force = 10 - fire_sound='sound/weapons/Laser.ogg' projectile_type = /obj/item/projectile/beam charge_cost = 120 sel_mode = 2 firemodes = list( - list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_sound='sound/weapons/Taser.ogg', fire_delay=null, charge_cost = 120), - list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, fire_sound='sound/weapons/Laser.ogg', fire_delay=null, charge_cost = 120), - list(mode_name="DESTROY", projectile_type=/obj/item/projectile/beam/pulse, fire_sound='sound/weapons/gauss_shoot.ogg', fire_delay=null, charge_cost = 240), + list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_delay=null, charge_cost = 120), + list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, fire_delay=null, charge_cost = 120), + list(mode_name="DESTROY", projectile_type=/obj/item/projectile/beam/pulse, fire_delay=null, charge_cost = 240), ) /obj/item/weapon/gun/energy/pulse_rifle/mounted @@ -39,7 +38,7 @@ charge_cost = 240 firemodes = list( - list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_sound='sound/weapons/Taser.ogg', fire_delay=null, charge_cost = 240), - list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, fire_sound='sound/weapons/Laser.ogg', fire_delay=null, charge_cost = 240), - list(mode_name="DESTROY", projectile_type=/obj/item/projectile/beam/pulse, fire_sound='sound/weapons/gauss_shoot.ogg', fire_delay=null, charge_cost = 480), + list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_delay=null, charge_cost = 240), + list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, fire_delay=null, charge_cost = 240), + list(mode_name="DESTROY", projectile_type=/obj/item/projectile/beam/pulse, fire_delay=null, charge_cost = 480), ) \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index beb44e1a3e..d574938d98 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -3,7 +3,6 @@ desc = "The NT Mk60 EW Halicon is a man portable anti-armor weapon designed to disable mechanical threats, produced by NT. Not the best of its type." icon_state = "ionrifle" item_state = "ionrifle" - fire_sound = 'sound/weapons/Laser.ogg' origin_tech = list(TECH_COMBAT = 2, TECH_MAGNET = 4) w_class = ITEMSIZE_LARGE force = 10 @@ -23,7 +22,7 @@ force = 5 slot_flags = SLOT_BELT|SLOT_HOLSTER charge_cost = 480 - projectile_type = /obj/item/projectile/ion + projectile_type = /obj/item/projectile/ion/pistol /obj/item/weapon/gun/energy/phasegun name = "phase pistol" @@ -202,12 +201,12 @@ obj/item/weapon/gun/energy/staff/focus projectile_type = /obj/item/projectile/energy/blue_pellet cell_type = /obj/item/weapon/cell/device/weapon/recharge battery_lock = 1 - accuracy = 5 // Suppressive weapons don't work too well if there's no risk of being hit. + accuracy = 75 // Suppressive weapons don't work too well if there's no risk of being hit. burst_delay = 1 // Burst faster than average. origin_tech = list(TECH_COMBAT = 6, TECH_MAGNET = 6, TECH_ILLEGAL = 6) firemodes = list( - list(mode_name="single shot", burst = 1, burst_accuracy = list(5), dispersion = list(0), charge_cost = 24), - list(mode_name="five shot burst", burst = 5, burst_accuracy = list(5,5,5,5,5), dispersion = list(1,1,1,1,1)), - list(mode_name="ten shot burst", burst = 10, burst_accuracy = list(5,5,5,5,5,5,5,5,5,5), dispersion = list(2,2,2,2,2,2,2,2,2,2)) + list(mode_name="single shot", burst = 1, burst_accuracy = list(75), dispersion = list(0), charge_cost = 24), + list(mode_name="five shot burst", burst = 5, burst_accuracy = list(75,75,75,75,75), dispersion = list(1,1,1,1,1)), + list(mode_name="ten shot burst", burst = 10, burst_accuracy = list(75,75,75,75,75,75,75,75,75,75), dispersion = list(2,2,2,2,2,2,2,2,2,2)), ) \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index 43bb9e1637..312a6b0648 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -3,7 +3,6 @@ desc = "The NT Mk30 NL is a small gun used for non-lethal takedowns. Produced by NT, it's actually a licensed version of a W-T design." icon_state = "taser" item_state = null //so the human update icon uses the icon_state instead. - fire_sound = 'sound/weapons/Taser.ogg' projectile_type = /obj/item/projectile/beam/stun /obj/item/weapon/gun/energy/taser/mounted @@ -22,7 +21,6 @@ desc = "A LAEP20 Zeus. Designed by Lawson Arms and produced under the wing of Hephaestus, several TSCs have been trying to get a hold of the blueprints for half a decade." icon_state = "stunrevolver" item_state = "stunrevolver" - fire_sound = 'sound/weapons/Gunshot.ogg' origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3, TECH_POWER = 2) projectile_type = /obj/item/projectile/energy/electrode/strong charge_cost = 300 @@ -63,7 +61,6 @@ desc = "The Mars Military Industries MA21 Selkie is a weapon that uses a laser pulse to ionise the local atmosphere, creating a disorienting pulse of plasma and deafening shockwave as the wave expands." icon_state = "plasma_stun" item_state = "plasma_stun" - fire_sound = 'sound/weapons/blaster.ogg' origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2, TECH_POWER = 3) fire_delay = 20 charge_cost = 600 diff --git a/code/modules/projectiles/guns/magnetic/magnetic.dm b/code/modules/projectiles/guns/magnetic/magnetic.dm index ae45454a42..cbce1a7aa1 100644 --- a/code/modules/projectiles/guns/magnetic/magnetic.dm +++ b/code/modules/projectiles/guns/magnetic/magnetic.dm @@ -4,7 +4,7 @@ icon_state = "coilgun" item_state = "coilgun" icon = 'icons/obj/railgun.dmi' -// one_handed_penalty = 1 +// one_handed_penalty = 15 origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 4, TECH_ILLEGAL = 2, TECH_MAGNET = 4) w_class = ITEMSIZE_LARGE @@ -15,7 +15,7 @@ var/obj/item/loaded // Currently loaded object, for retrieval/unloading. var/load_type = /obj/item/stack/rods // Type of stack to load with. - var/projectile_type = /obj/item/projectile/bullet/magnetic // Actual fire type, since this isn't throw_at rod launcher. + projectile_type = /obj/item/projectile/bullet/magnetic // Actual fire type, since this isn't throw_at rod launcher. var/power_cost = 950 // Cost per fire, should consume almost an entire basic cell. var/power_per_tick // Capacitor charge per process(). Updated based on capacitor rating. diff --git a/code/modules/projectiles/guns/magnetic/magnetic_railgun.dm b/code/modules/projectiles/guns/magnetic/magnetic_railgun.dm index 82f10cae24..466fbd3b33 100644 --- a/code/modules/projectiles/guns/magnetic/magnetic_railgun.dm +++ b/code/modules/projectiles/guns/magnetic/magnetic_railgun.dm @@ -11,6 +11,8 @@ w_class = ITEMSIZE_HUGE slot_flags = SLOT_BELT loaded = /obj/item/weapon/rcd_ammo/large + slowdown = 1 // Slowdown equals slowdown_worn, until we decide to import the system to differentiate between held and worn items + fire_delay = 1 var/initial_cell_type = /obj/item/weapon/cell/hyper var/initial_capacitor_type = /obj/item/weapon/stock_parts/capacitor/adv @@ -59,7 +61,9 @@ initial_cell_type = /obj/item/weapon/cell/infinite initial_capacitor_type = /obj/item/weapon/stock_parts/capacitor/super + fire_delay = 0 + slowdown = 2 slowdown_held = 3 slowdown_worn = 2 @@ -67,9 +71,9 @@ w_class = ITEMSIZE_NO_CONTAINER firemodes = list( - list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, one_handed_penalty=1, burst_accuracy=null, dispersion=null), - list(mode_name="short bursts", burst=3, fire_delay=null, move_delay=5, one_handed_penalty=2, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0)), - list(mode_name="long bursts", burst=6, fire_delay=null, move_delay=10, one_handed_penalty=2, burst_accuracy=list(0,-1,-1,-1,-2), dispersion=list(0.6, 0.6, 1.0, 1.0, 1.2)), + list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, one_handed_penalty=15, burst_accuracy=null, dispersion=null), + list(mode_name="short bursts", burst=3, fire_delay=null, move_delay=5, one_handed_penalty=30, burst_accuracy=list(0,-15,-15), dispersion=list(0.0, 0.6, 1.0)), + list(mode_name="long bursts", burst=6, fire_delay=null, move_delay=10, one_handed_penalty=30, burst_accuracy=list(0,-15,-15,-15,-30), dispersion=list(0.6, 0.6, 1.0, 1.0, 1.2)), ) /obj/item/weapon/gun/magnetic/railgun/automatic/examine(var/mob/user) @@ -82,11 +86,18 @@ desc = "The MI-12 Skadi is a burst fire capable railgun that fires flechette rounds at high velocity. Deadly against armour, but much less effective against soft targets." icon_state = "flechette_gun" item_state = "z8carbine" + initial_cell_type = /obj/item/weapon/cell/hyper initial_capacitor_type = /obj/item/weapon/stock_parts/capacitor/adv + + fire_delay = 0 + slot_flags = SLOT_BACK + + slowdown = 0 slowdown_held = 0 slowdown_worn = 0 + power_cost = 100 load_type = /obj/item/weapon/magnetic_ammo projectile_type = /obj/item/projectile/bullet/magnetic/flechette @@ -95,6 +106,6 @@ empty_sound = 'sound/weapons/smg_empty_alarm.ogg' firemodes = list( - list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, one_handed_penalty=1, burst_accuracy=null, dispersion=null), - list(mode_name="short bursts", burst=3, fire_delay=null, move_delay=5, one_handed_penalty=2, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0)), + list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, one_handed_penalty=15, burst_accuracy=null, dispersion=null), + list(mode_name="short bursts", burst=3, fire_delay=null, move_delay=5, one_handed_penalty=30, burst_accuracy=list(0,-15,-15), dispersion=list(0.0, 0.6, 1.0)), ) diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index f1ff50698f..be37c824bb 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -10,6 +10,7 @@ w_class = ITEMSIZE_NORMAL matter = list(DEFAULT_WALL_MATERIAL = 1000) recoil = 1 + projectile_type = /obj/item/projectile/bullet/pistol/strong //Only used for Cham Guns var/caliber = ".357" //determines which casings will fit var/handle_casings = EJECT_CASINGS //determines how spent casings should be handled diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index 39bc6d7ae0..142e688006 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -9,16 +9,16 @@ origin_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 2) slot_flags = SLOT_BELT ammo_type = /obj/item/ammo_casing/a9mm + projectile_type = /obj/item/projectile/bullet/pistol multi_aim = 1 burst_delay = 2 -// requires_two_hands = 1 - one_handed_penalty = 1 +// one_handed_penalty = 15 firemodes = list( list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null), - list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0)) -// list(mode_name="short bursts", burst=5, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1,-2,-2), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)), + list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15), dispersion=list(0.0, 0.6, 1.0)) +// list(mode_name="short bursts", burst=5, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15,-30,-30), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)), ) /obj/item/weapon/gun/projectile/automatic/c20r @@ -35,11 +35,11 @@ load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/m10mm allowed_magazines = list(/obj/item/ammo_magazine/m10mm) + projectile_type = /obj/item/projectile/bullet/pistol/medium auto_eject = 1 auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg' -// requires_two_hands = 1 - one_handed_penalty = 2 +// one_handed_penalty = 15 /obj/item/weapon/gun/projectile/automatic/c20r/update_icon() ..() @@ -62,13 +62,14 @@ load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/m545 allowed_magazines = list(/obj/item/ammo_magazine/m545) + projectile_type = /obj/item/projectile/bullet/rifle/a545 - one_handed_penalty = 4 +// one_handed_penalty = 30 firemodes = list( list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null), - list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=6, burst_accuracy=list(0,-1,-2), dispersion=list(0.0, 0.6, 0.6)) -// list(mode_name="short bursts", burst=5, fire_delay=null, move_delay=6, burst_accuracy=list(0,-1,-2,-2,-3), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)), + list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=6, burst_accuracy=list(0,-15,-30), dispersion=list(0.0, 0.6, 0.6)) +// list(mode_name="short bursts", burst=5, fire_delay=null, move_delay=6, burst_accuracy=list(0,-15,-30,-30,-45), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)), ) /obj/item/weapon/gun/projectile/automatic/sts35/update_icon(var/ignore_inhands) @@ -93,6 +94,7 @@ load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/m9mmt/rubber allowed_magazines = list(/obj/item/ammo_magazine/m9mmt) + projectile_type = /obj/item/projectile/bullet/pistol/medium /obj/item/weapon/gun/projectile/automatic/wt550/update_icon() ..() @@ -116,15 +118,16 @@ load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/m762 allowed_magazines = list(/obj/item/ammo_magazine/m762) + projectile_type = /obj/item/projectile/bullet/rifle/a762 auto_eject = 1 auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg' - one_handed_penalty = 4 +// one_handed_penalty = 60 burst_delay = 4 firemodes = list( list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, use_launcher=null, burst_accuracy=null, dispersion=null), - list(mode_name="2-round bursts", burst=2, fire_delay=null, move_delay=6, use_launcher=null, burst_accuracy=list(0,-1), dispersion=list(0.0, 0.6)), + list(mode_name="2-round bursts", burst=2, fire_delay=null, move_delay=6, use_launcher=null, burst_accuracy=list(0,-15), dispersion=list(0.0, 0.6)), list(mode_name="fire grenades", burst=null, fire_delay=null, move_delay=null, use_launcher=1, burst_accuracy=null, dispersion=null) ) @@ -187,8 +190,9 @@ load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/m545saw allowed_magazines = list(/obj/item/ammo_magazine/m545saw, /obj/item/ammo_magazine/m545) + projectile_type = /obj/item/projectile/bullet/rifle/a545 - one_handed_penalty = 6 +// one_handed_penalty = 90 var/cover_open = 0 @@ -203,8 +207,8 @@ firemodes = list( list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null), - list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0)), - list(mode_name="short bursts", burst=5, move_delay=6, burst_accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)), + list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15), dispersion=list(0.0, 0.6, 1.0)), + list(mode_name="short bursts", burst=5, move_delay=6, burst_accuracy = list(0,-15,-15,-30,-30), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)) ) /obj/item/weapon/gun/projectile/automatic/l6_saw/special_check(mob/user) @@ -260,19 +264,19 @@ w_class = ITEMSIZE_LARGE force = 10 caliber = "12g" - fire_sound = 'sound/weapons/shotgun.ogg' origin_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 1, TECH_ILLEGAL = 4) slot_flags = SLOT_BACK load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/m12gdrum allowed_magazines = list(/obj/item/ammo_magazine/m12gdrum) + projectile_type = /obj/item/projectile/bullet/shotgun - one_handed_penalty = 4 +// one_handed_penalty = 60 firemodes = list( list(mode_name="semiauto", burst=1, fire_delay=0), - list(mode_name="3-round bursts", burst=3, move_delay=6, burst_accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.0, 0.6, 0.6)) -// list(mode_name="6-round bursts", burst=6, move_delay=6, burst_accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2, 1.2)), + list(mode_name="3-round bursts", burst=3, move_delay=6, burst_accuracy = list(0,-15,-15,-30,-30), dispersion = list(0.0, 0.6, 0.6)) +// list(mode_name="6-round bursts", burst=6, move_delay=6, burst_accuracy = list(0,-15,-15,-30,-30, -30), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2, 1.2)), ) /obj/item/weapon/gun/projectile/automatic/as24/update_icon() @@ -296,7 +300,7 @@ firemodes = list( list(mode_name="semiauto", burst=1, fire_delay=0), - list(mode_name="3-round bursts", burst=3, burst_delay=1, fire_delay=4, move_delay=4, burst_accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0)) + list(mode_name="3-round bursts", burst=3, burst_delay=1, fire_delay=4, move_delay=4, burst_accuracy = list(0,-15,-15,-30,-30), dispersion = list(0.6, 1.0, 1.0)) ) /obj/item/weapon/gun/projectile/automatic/mini_uzi/update_icon() @@ -322,7 +326,7 @@ firemodes = list( list(mode_name="semiauto", burst=1, fire_delay=0), - list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0)) + list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15), dispersion=list(0.0, 0.6, 1.0)) ) /obj/item/weapon/gun/projectile/automatic/p90/update_icon() @@ -342,7 +346,7 @@ firemodes = list( list(mode_name="semiauto", burst=1, fire_delay=0), - list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0)) + list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15), dispersion=list(0.0, 0.6, 1.0)) ) /obj/item/weapon/gun/projectile/automatic/tommygun/update_icon() @@ -363,12 +367,13 @@ load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/m762 allowed_magazines = list(/obj/item/ammo_magazine/m762, /obj/item/ammo_magazine/m762m) + projectile_type = /obj/item/projectile/bullet/rifle/a762 - one_handed_penalty = 4 +// one_handed_penalty = 45 firemodes = list( list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null), - list(mode_name="2-round bursts", burst=2, fire_delay=null, move_delay=6, burst_accuracy=list(0,-1), dispersion=list(0.0, 0.6)) + list(mode_name="2-round bursts", burst=2, fire_delay=null, move_delay=6, burst_accuracy=list(0,-15), dispersion=list(0.0, 0.6)) ) /obj/item/weapon/gun/projectile/automatic/bullpup/update_icon(var/ignore_inhands) @@ -379,4 +384,5 @@ icon_state = "bullpup" else item_state = "bullpup-empty" - if(!ignore_inhands) update_held_icon() + if(!ignore_inhands) + update_held_icon() diff --git a/code/modules/projectiles/guns/projectile/boltaction.dm b/code/modules/projectiles/guns/projectile/boltaction.dm index bb6d14d1ee..45e5f1ece5 100644 --- a/code/modules/projectiles/guns/projectile/boltaction.dm +++ b/code/modules/projectiles/guns/projectile/boltaction.dm @@ -37,7 +37,7 @@ icon_state = "sawnrifle" w_class = ITEMSIZE_NORMAL recoil = 2 // Owch - accuracy = -1 // You know damn well why. + accuracy = -15 // You know damn well why. item_state = "gun" slot_flags &= ~SLOT_BACK //you can't sling it on your back slot_flags |= (SLOT_BELT|SLOT_HOLSTER) //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally) - or in a holster, why not. diff --git a/code/modules/projectiles/guns/projectile/contender.dm b/code/modules/projectiles/guns/projectile/contender.dm index 4d840a214b..d5e44ae54a 100644 --- a/code/modules/projectiles/guns/projectile/contender.dm +++ b/code/modules/projectiles/guns/projectile/contender.dm @@ -8,6 +8,7 @@ handle_casings = HOLD_CASINGS max_shells = 1 ammo_type = /obj/item/ammo_casing/a357 + projectile_type = /obj/item/projectile/bullet/pistol/strong var/retracted_bolt = 0 load_method = SINGLE_CASING diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm index 872059df53..a232956684 100644 --- a/code/modules/projectiles/guns/projectile/pistol.dm +++ b/code/modules/projectiles/guns/projectile/pistol.dm @@ -4,10 +4,10 @@ desc = "A cheap Martian knock-off of a Colt M1911. Uses .45 rounds." magazine_type = /obj/item/ammo_magazine/m45 allowed_magazines = list(/obj/item/ammo_magazine/m45) + projectile_type = /obj/item/projectile/bullet/pistol/medium icon_state = "colt" caliber = ".45" origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2) - fire_sound = 'sound/weapons/gunshot3.ogg' load_method = MAGAZINE /obj/item/weapon/gun/projectile/colt/update_icon() @@ -68,14 +68,22 @@ M << "Your gun is now sprited as [choice]. Say hello to your new friend." return 1 +/*//apart of reskins that have two sprites, touching may result in frustration and breaks +/obj/item/weapon/gun/projectile/colt/detective/attack_hand(var/mob/living/user) + if(!unique_reskin && loc == user) + reskin_gun(user) + return + ..() +*/ + /obj/item/weapon/gun/projectile/sec name = ".45 pistol" desc = "The NT Mk58 is a cheap, ubiquitous sidearm, produced by a NanoTrasen subsidiary. Found pretty much everywhere humans are. Uses .45 rounds." icon_state = "secguncomp" magazine_type = /obj/item/ammo_magazine/m45/rubber + projectile_type = /obj/item/projectile/bullet/pistol/medium caliber = ".45" origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2) - fire_sound = 'sound/weapons/gunshot3.ogg' load_method = MAGAZINE /obj/item/weapon/gun/projectile/sec/update_icon() @@ -114,6 +122,7 @@ load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/m45 allowed_magazines = list(/obj/item/ammo_magazine/m45) + projectile_type = /obj/item/projectile/bullet/pistol/medium /obj/item/weapon/gun/projectile/deagle name = "desert eagle" @@ -195,10 +204,10 @@ caliber = "9mm" silenced = 0 origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2, TECH_ILLEGAL = 2) - fire_sound = 'sound/weapons/gunshot3.ogg' load_method = MAGAZINE magazine_type = /obj/item/ammo_magazine/m9mm/compact allowed_magazines = list(/obj/item/ammo_magazine/m9mm/compact) + projectile_type = /obj/item/projectile/bullet/pistol /obj/item/weapon/gun/projectile/pistol/flash name = "compact signal pistol" @@ -291,6 +300,7 @@ load_method = SINGLE_CASING max_shells = 2 ammo_type = /obj/item/ammo_casing/a357 + projectile_type = /obj/item/projectile/bullet/pistol/strong /obj/item/weapon/gun/projectile/luger name = "\improper P08 Luger" @@ -299,9 +309,9 @@ origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2) caliber = "9mm" load_method = MAGAZINE - fire_sound = 'sound/weapons/gunshot3.ogg' magazine_type = /obj/item/ammo_magazine/m9mm/compact allowed_magazines = list(/obj/item/ammo_magazine/m9mm/compact) + projectile_type = /obj/item/projectile/bullet/pistol /obj/item/weapon/gun/projectile/luger/update_icon() ..() diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index 20671d6fd5..b33cf11950 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -8,6 +8,7 @@ handle_casings = CYCLE_CASINGS max_shells = 6 ammo_type = /obj/item/ammo_casing/a357 + projectile_type = /obj/item/projectile/bullet/pistol/strong var/chamber_offset = 0 //how many empty chambers in the cylinder until you hit a round /obj/item/weapon/gun/projectile/revolver/verb/spin_cylinder() @@ -154,6 +155,7 @@ obj/item/weapon/gun/projectile/revolver/detective45/verb/rename_gun() handle_casings = CYCLE_CASINGS max_shells = 7 ammo_type = /obj/item/ammo_casing/cap + projectile_type = /obj/item/projectile/bullet/pistol/strong /obj/item/weapon/gun/projectile/revolver/judge name = "\"The Judge\"" @@ -162,10 +164,10 @@ obj/item/weapon/gun/projectile/revolver/detective45/verb/rename_gun() caliber = "12g" origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2, TECH_ILLEGAL = 4) max_shells = 5 - fire_sound = 'sound/weapons/shotgun.ogg' recoil = 2 // ow my fucking hand - accuracy = -1 // smooth bore + short barrel = shit accuracy + accuracy = -15 // smooth bore + short barrel = shit accuracy ammo_type = /obj/item/ammo_casing/a12g + projectile_type = /obj/item/projectile/bullet/shotgun // ToDo: Remove accuracy debuf in exchange for slightly injuring your hand every time you fire it. /obj/item/weapon/gun/projectile/revolver/lemat @@ -176,9 +178,9 @@ obj/item/weapon/gun/projectile/revolver/detective45/verb/rename_gun() origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2) handle_casings = CYCLE_CASINGS max_shells = 9 - fire_sound = 'sound/weapons/gunshot3.ogg' caliber = ".38" ammo_type = /obj/item/ammo_casing/a38 + projectile_type = /obj/item/projectile/bullet/pistol var/secondary_max_shells = 1 var/secondary_caliber = "12g" var/secondary_ammo_type = /obj/item/ammo_casing/a12g @@ -208,7 +210,6 @@ obj/item/weapon/gun/projectile/revolver/detective45/verb/rename_gun() if(caliber && secondary_caliber) caliber = secondary_caliber - fire_sound = 'sound/weapons/shotgun.ogg' if(ammo_type && secondary_ammo_type) ammo_type = secondary_ammo_type @@ -225,7 +226,6 @@ obj/item/weapon/gun/projectile/revolver/detective45/verb/rename_gun() if(caliber && secondary_caliber) caliber = initial(caliber) - fire_sound = initial(fire_sound) if(ammo_type && secondary_ammo_type) ammo_type = initial(ammo_type) diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm index 2fb6f04abb..087543091d 100644 --- a/code/modules/projectiles/guns/projectile/shotgun.dm +++ b/code/modules/projectiles/guns/projectile/shotgun.dm @@ -12,8 +12,8 @@ origin_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 2) load_method = SINGLE_CASING|SPEEDLOADER ammo_type = /obj/item/ammo_casing/a12g/beanbag + projectile_type = /obj/item/projectile/bullet/shotgun handle_casings = HOLD_CASINGS - fire_sound = 'sound/weapons/shotgun.ogg' var/recentpump = 0 // to prevent spammage var/action_sound = 'sound/weapons/shotgunpump.ogg' @@ -106,7 +106,7 @@ slot_flags |= (SLOT_BELT|SLOT_HOLSTER) //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally) - or in a holster, why not. name = "sawn-off shotgun" desc = "Omar's coming!" - user << "You shorten the barrel of \the [src]!" + to_chat(user, "You shorten the barrel of \the [src]!") else ..() diff --git a/code/modules/projectiles/guns/projectile/sniper.dm b/code/modules/projectiles/guns/projectile/sniper.dm index 183de3cf17..230e2b4d50 100644 --- a/code/modules/projectiles/guns/projectile/sniper.dm +++ b/code/modules/projectiles/guns/projectile/sniper.dm @@ -11,13 +11,14 @@ origin_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 2, TECH_ILLEGAL = 8) caliber = "14.5mm" recoil = 5 //extra kickback - fire_sound = 'sound/weapons/sniper.ogg' // extra boom handle_casings = HOLD_CASINGS load_method = SINGLE_CASING max_shells = 1 ammo_type = /obj/item/ammo_casing/a145 - accuracy = -5 - scoped_accuracy = 5 + projectile_type = /obj/item/projectile/bullet/rifle/a145 + accuracy = -75 + scoped_accuracy = 75 +// one_handed_penalty = 90 var/bolt_open = 0 /obj/item/weapon/gun/projectile/heavysniper/update_icon() @@ -79,10 +80,10 @@ origin_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 2, TECH_ILLEGAL = 8) caliber = "7.62mm" load_method = MAGAZINE - accuracy = -3 //shooting at the hip + accuracy = -45 //shooting at the hip scoped_accuracy = 0 // requires_two_hands = 1 - one_handed_penalty = 4 // The weapon itself is heavy, and the long barrel makes it hard to hold steady with just one hand. +// one_handed_penalty = 60 // The weapon itself is heavy, and the long barrel makes it hard to hold steady with just one hand. fire_sound = 'sound/weapons/SVD_shot.ogg' magazine_type = /obj/item/ammo_magazine/m762svd allowed_magazines = list(/obj/item/ammo_magazine/m762svd) diff --git a/code/modules/projectiles/guns/vox.dm b/code/modules/projectiles/guns/vox.dm index ecc8a1a904..631d255f77 100644 --- a/code/modules/projectiles/guns/vox.dm +++ b/code/modules/projectiles/guns/vox.dm @@ -56,23 +56,23 @@ desc = "A vicious alien beam weapon. Parts of it quiver gelatinously, as though the thing is insectile and alive." icon_state = "darkcannon" item_state = "darkcannon" - fire_sound = 'sound/weapons/eLuger.ogg' w_class = ITEMSIZE_HUGE charge_cost = 300 projectile_type = /obj/item/projectile/beam/stun/darkmatter cell_type = /obj/item/weapon/cell/device/weapon/recharge battery_lock = 1 - accuracy = 2 + accuracy = 30 firemodes = list( - list(mode_name="stunning", burst=1, fire_delay=null, move_delay=null, burst_accuracy=list(2), dispersion=null, projectile_type=/obj/item/projectile/beam/stun/darkmatter, charge_cost = 300), - list(mode_name="focused", burst=1, fire_delay=null, move_delay=null, burst_accuracy=list(2), dispersion=null, projectile_type=/obj/item/projectile/beam/darkmatter, charge_cost = 600), + list(mode_name="stunning", burst=1, fire_delay=null, move_delay=null, burst_accuracy=list(30), dispersion=null, projectile_type=/obj/item/projectile/beam/stun/darkmatter, charge_cost = 300), + list(mode_name="focused", burst=1, fire_delay=null, move_delay=null, burst_accuracy=list(30), dispersion=null, projectile_type=/obj/item/projectile/beam/darkmatter, charge_cost = 600), list(mode_name="scatter burst", burst=8, fire_delay=null, move_delay=4, burst_accuracy=list(0, 0, 0, 0, 0, 0, 0, 0), dispersion=list(3, 3, 3, 3, 3, 3, 3, 3, 3), projectile_type=/obj/item/projectile/energy/darkmatter, charge_cost = 300), ) /obj/item/projectile/beam/stun/darkmatter name = "dark matter wave" icon_state = "darkt" + fire_sound = 'sound/weapons/eLuger.ogg' nodamage = 1 taser_effect = 1 agony = 55 @@ -86,6 +86,7 @@ /obj/item/projectile/beam/darkmatter name = "dark matter bolt" icon_state = "darkb" + fire_sound = 'sound/weapons/eLuger.ogg' damage = 35 armor_penetration = 35 damage_type = BRUTE @@ -101,6 +102,7 @@ /obj/item/projectile/energy/darkmatter name = "dark matter pellet" icon_state = "dark_pellet" + fire_sound = 'sound/weapons/eLuger.ogg' damage = 20 armor_penetration = 35 damage_type = BRUTE @@ -117,7 +119,6 @@ desc = "A vicious alien sound weapon. Parts of it quiver gelatinously, as though the thing is insectile and alive." icon_state = "noise" item_state = "noise" - fire_sound = 'sound/effects/basscannon.ogg' w_class = ITEMSIZE_HUGE cell_type = /obj/item/weapon/cell/device/weapon/recharge battery_lock = 1 @@ -133,6 +134,7 @@ /obj/item/projectile/sonic name = "sonic pulse" icon_state = "sound" + fire_sound = 'sound/effects/basscannon.ogg' damage = 5 armor_penetration = 30 damage_type = BRUTE diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 2040b0a778..f844ac0475 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -69,6 +69,8 @@ var/tracer_type var/impact_type + var/fire_sound + var/vacuum_traversal = 1 //Determines if the projectile can exist in vacuum, if false, the projectile will be deleted if it enters vacuum. var/datum/plot_vector/trajectory // used to plot the path of the projectile @@ -177,7 +179,7 @@ return //roll to-hit - miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier + round(15*target_mob.get_evasion()), 0) + miss_modifier = max(15*(distance-2) - accuracy + miss_modifier + target_mob.get_evasion(), 0) var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, miss_modifier, ranged_attack=(distance > 1 || original != target_mob)) //if the projectile hits a target we weren't originally aiming at then retain the chance to miss var/result = PROJECTILE_FORCE_MISS @@ -192,7 +194,7 @@ //hit messages if(silenced) - target_mob << "You've been hit in the [parse_zone(def_zone)] by \the [src]!" + to_chat(target_mob, "You've been hit in the [parse_zone(def_zone)] by \the [src]!") else visible_message("\The [target_mob] is hit by \the [src] in the [parse_zone(def_zone)]!")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 32dce8e3b9..6fee571544 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -1,6 +1,7 @@ /obj/item/projectile/beam name = "laser" icon_state = "laser" + fire_sound = 'sound/weapons/Laser.ogg' pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE damage = 40 damage_type = BURN @@ -21,7 +22,6 @@ /obj/item/projectile/beam/practice name = "laser" icon_state = "laser" - pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE damage = 0 damage_type = BURN check_armour = "laser" @@ -32,6 +32,9 @@ icon_state = "laser" damage = 15 +/obj/item/projectile/beam/smalllaser + damage = 25 + /obj/item/projectile/beam/burstlaser damage = 30 armor_penetration = 10 @@ -44,6 +47,7 @@ /obj/item/projectile/beam/heavylaser name = "heavy laser" icon_state = "heavylaser" + fire_sound = 'sound/weapons/lasercannonfire.ogg' damage = 60 armor_penetration = 30 light_range = 3 @@ -62,6 +66,7 @@ /obj/item/projectile/beam/xray name = "xray beam" icon_state = "xray" + fire_sound = 'sound/weapons/eluger.ogg' damage = 25 armor_penetration = 50 light_color = "#00CC33" @@ -83,8 +88,9 @@ /obj/item/projectile/beam/pulse name = "pulse" icon_state = "u_laser" - damage = 50 - armor_penetration = 30 + fire_sound='sound/weapons/pulse.ogg' + damage = 100 //Badmin toy, don't care + armor_penetration = 100 light_color = "#0066FF" muzzle_type = /obj/effect/projectile/laser_pulse/muzzle @@ -99,6 +105,7 @@ /obj/item/projectile/beam/emitter name = "emitter beam" icon_state = "emitter" + fire_sound = 'sound/weapons/emitter.ogg' damage = 0 // The actual damage is computed in /code/modules/power/singularity/emitter.dm light_color = "#00CC33" @@ -109,7 +116,6 @@ /obj/item/projectile/beam/lastertag/blue name = "lasertag beam" icon_state = "bluelaser" - pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE damage = 0 no_attack_log = 1 damage_type = BURN @@ -130,7 +136,6 @@ /obj/item/projectile/beam/lastertag/red name = "lasertag beam" icon_state = "laser" - pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE damage = 0 no_attack_log = 1 damage_type = BURN @@ -147,7 +152,6 @@ /obj/item/projectile/beam/lastertag/omni//A laser tag bolt that stuns EVERYONE name = "lasertag beam" icon_state = "omnilaser" - pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE damage = 0 damage_type = BURN check_armour = "laser" @@ -167,6 +171,7 @@ /obj/item/projectile/beam/sniper name = "sniper beam" icon_state = "xray" + fire_sound = 'sound/weapons/gauss_shoot.ogg' damage = 50 armor_penetration = 10 light_color = "#00CC33" @@ -178,6 +183,7 @@ /obj/item/projectile/beam/stun name = "stun beam" icon_state = "stun" + fire_sound = 'sound/weapons/Taser.ogg' nodamage = 1 taser_effect = 1 agony = 40 diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index a7132fa43b..02eab7e93a 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -1,6 +1,7 @@ /obj/item/projectile/bullet name = "bullet" icon_state = "bullet" + fire_sound = 'sound/weapons/gunshot/gunshot_strong.ogg' damage = 60 damage_type = BRUTE nodamage = 0 @@ -124,6 +125,7 @@ /* short-casing projectiles, like the kind used in pistols or SMGs */ /obj/item/projectile/bullet/pistol + fire_sound = 'sound/weapons/gunshot/gunshot_pistol.ogg' damage = 20 /obj/item/projectile/bullet/pistol/ap @@ -142,6 +144,7 @@ armor_penetration = -50 /obj/item/projectile/bullet/pistol/strong //revolvers and matebas + fire_sound = 'sound/weapons/gunshot/gunshot_strong.ogg' damage = 60 /obj/item/projectile/bullet/pistol/rubber //"rubber" bullets @@ -156,6 +159,7 @@ /obj/item/projectile/bullet/shotgun name = "slug" + fire_sound = 'sound/weapons/gunshot/shotgun.ogg' damage = 50 armor_penetration = 15 @@ -171,6 +175,7 @@ //Overall less damage than slugs in exchange for more damage at very close range and more embedding /obj/item/projectile/bullet/pellet/shotgun name = "shrapnel" + fire_sound = 'sound/weapons/gunshot/shotgun.ogg' damage = 13 pellets = 6 range_step = 1 @@ -180,6 +185,7 @@ //EMP shotgun 'slug', it's basically a beanbag that pops a tiny emp when it hits. //Not currently used /obj/item/projectile/bullet/shotgun/ion name = "ion slug" + fire_sound = 'sound/weapons/Laser.ogg' damage = 15 embed_chance = 0 sharp = 0 @@ -194,10 +200,12 @@ /* "Rifle" rounds */ /obj/item/projectile/bullet/rifle + fire_sound = 'sound/weapons/gunshot/gunshot3.ogg' armor_penetration = 15 penetrating = 1 /obj/item/projectile/bullet/rifle/a762 + fire_sound = 'sound/weapons/gunshot/gunshot2.ogg' damage = 35 /obj/item/projectile/bullet/rifle/a762/ap @@ -232,6 +240,7 @@ SA_vulnerability = SA_ANIMAL /obj/item/projectile/bullet/rifle/a145 + fire_sound = 'sound/weapons/gunshot/sniper.ogg' damage = 80 stun = 3 weaken = 3 @@ -253,11 +262,12 @@ /obj/item/projectile/bullet/burstbullet name = "exploding bullet" + fire_sound = 'sound/effects/Explosion1.ogg' damage = 20 embed_chance = 0 edge = 1 -/obj/item/projectile/bullet/gyro/on_hit(var/atom/target, var/blocked = 0) +/obj/item/projectile/bullet/burstbullet/on_hit(var/atom/target, var/blocked = 0) if(isturf(target)) explosion(target, -1, 0, 2) ..() @@ -309,6 +319,7 @@ /obj/item/projectile/bullet/pistol/cap name = "cap" damage_type = HALLOSS + fire_sound = null damage = 0 nodamage = 1 embed_chance = 0 diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index 8138146163..0cbb96a2e0 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -10,6 +10,7 @@ /obj/item/projectile/energy/flash name = "chemical shell" icon_state = "bullet" + fire_sound = 'sound/weapons/gunshot/gunshot_pistol.ogg' damage = 5 kill_count = 15 //if the shell hasn't hit anything after travelling this far it just explodes. var/flash_range = 0 @@ -47,6 +48,7 @@ //blinds people like the flash round, but can also be used for temporary illumination /obj/item/projectile/energy/flash/flare + fire_sound = 'sound/weapons/gunshot/shotgun.ogg' damage = 10 flash_range = 1 brightness = 15 @@ -63,6 +65,7 @@ /obj/item/projectile/energy/electrode name = "electrode" icon_state = "spark" + fire_sound = 'sound/weapons/Gunshot.ogg' taser_effect = 1 agony = 40 light_range = 2 @@ -81,6 +84,7 @@ /obj/item/projectile/energy/declone name = "declone" icon_state = "declone" + fire_sound = 'sound/weapons/pulse3.ogg' nodamage = 1 damage_type = CLONE irradiate = 40 @@ -106,7 +110,6 @@ agony = 40 stutter = 10 - /obj/item/projectile/energy/bolt/large name = "largebolt" damage = 20 @@ -138,6 +141,7 @@ /obj/item/projectile/energy/phoron name = "phoron bolt" icon_state = "energy" + fire_sound = 'sound/effects/stealthoff.ogg' damage = 20 damage_type = TOX irradiate = 20 @@ -148,6 +152,7 @@ /obj/item/projectile/energy/plasmastun name = "plasma pulse" icon_state = "plasma_stun" + fire_sound = 'sound/weapons/blaster.ogg' armor_penetration = 10 kill_count = 4 damage = 5 @@ -187,6 +192,7 @@ /obj/item/projectile/energy/blue_pellet name = "suppressive pellet" icon_state = "blue_pellet" + fire_sound = 'sound/weapons/Laser.ogg' damage = 5 armor_penetration = 75 pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE diff --git a/code/modules/projectiles/projectile/magnetic.dm b/code/modules/projectiles/projectile/magnetic.dm index b4a60a55d7..ed16ea208d 100644 --- a/code/modules/projectiles/projectile/magnetic.dm +++ b/code/modules/projectiles/projectile/magnetic.dm @@ -2,6 +2,7 @@ /obj/item/projectile/bullet/magnetic name = "rod" icon_state = "rod" + fire_sound = 'sound/weapons/railgun.ogg' damage = 65 stun = 1 weaken = 1 @@ -17,6 +18,7 @@ /obj/item/projectile/bullet/magnetic/flechette name = "flechette" icon_state = "flechette" + fire_sound = 'sound/weapons/rapidslice.ogg' damage = 20 armor_penetration = 100 diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 0f1b0abbc6..4e366bed6d 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -1,6 +1,7 @@ /obj/item/projectile/ion name = "ion bolt" icon_state = "ion" + fire_sound = 'sound/weapons/Laser.ogg' damage = 0 damage_type = BURN nodamage = 1 @@ -8,17 +9,26 @@ light_range = 2 light_power = 0.5 light_color = "#55AAFF" - //var/pulse_range = 1 vorestation removal - + var/sev1_range = 0 + var/sev2_range = 1 + var/sev3_range = 1 + var/sev4_range = 2 /obj/item/projectile/ion/on_hit(var/atom/target, var/blocked = 0) - empulse(target, sev1_range, sev2_range, sev3_range, sev4_range) // vorestation edit + empulse(target, sev1_range, sev2_range, sev3_range, sev4_range) return 1 -/* vorestation removal - moved to vr file /obj/item/projectile/ion/small - pulse_range = 0 -*/ + sev1_range = -1 + sev2_range = 0 + sev3_range = 0 + sev4_range = 1 + +/obj/item/projectile/ion/pistol + sev1_range = 0 + sev2_range = 0 + sev3_range = 0 + sev4_range = 0 /obj/item/projectile/bullet/gyro name ="explosive bolt" @@ -29,12 +39,13 @@ edge = 1 /obj/item/projectile/bullet/gyro/on_hit(var/atom/target, var/blocked = 0) - explosion(target, -1, 0, 2) - return 1 + explosion(target, -1, 0, 2) + ..() /obj/item/projectile/temp name = "freeze beam" icon_state = "ice_2" + fire_sound = 'sound/weapons/pulse3.ogg' damage = 0 damage_type = BURN pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE @@ -107,6 +118,7 @@ /obj/item/projectile/energy/floramut name = "alpha somatoray" icon_state = "energy" + fire_sound = 'sound/effects/stealthoff.ogg' damage = 0 damage_type = TOX nodamage = 1 @@ -150,6 +162,7 @@ /obj/item/projectile/energy/floramut/gene name = "gamma somatoray" icon_state = "energy2" + fire_sound = 'sound/effects/stealthoff.ogg' damage = 0 damage_type = TOX nodamage = 1 @@ -159,6 +172,7 @@ /obj/item/projectile/energy/florayield name = "beta somatoray" icon_state = "energy2" + fire_sound = 'sound/effects/stealthoff.ogg' damage = 0 damage_type = TOX nodamage = 1 diff --git a/code/modules/projectiles/projectile/special_vr.dm b/code/modules/projectiles/projectile/special_vr.dm deleted file mode 100644 index 959d7997df..0000000000 --- a/code/modules/projectiles/projectile/special_vr.dm +++ /dev/null @@ -1,18 +0,0 @@ -/obj/item/projectile/ion - var/sev1_range = 0 - var/sev2_range = 1 - var/sev3_range = 1 - var/sev4_range = 2 - -/obj/item/projectile/ion/small - sev1_range = -1 - sev2_range = 0 - sev3_range = 0 - sev4_range = 1 - -/obj/item/projectile/ion/pistol - sev1_range = 0 - sev2_range = 0 - sev3_range = 0 - sev4_range = 0 - diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index a8b7d1fde1..1ac48546f5 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -68,6 +68,10 @@ user.drop_item() B.loc = src user << "You add \the [loaded_pill_bottle] into the dispenser slot!" + + else if(default_unfasten_wrench(user, B, 20)) + return + return /obj/machinery/chem_master/attack_hand(mob/user as mob) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm index 2acf9e57e5..b731f50326 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm @@ -461,11 +461,11 @@ if(M.ingested) for(var/datum/reagent/R in M.ingested.reagent_list) if(istype(R, /datum/reagent/ethanol)) - R.dose = max(R.dose - removed * 5, 0) + R.remove_self(removed * 5) if(M.bloodstr) for(var/datum/reagent/R in M.bloodstr.reagent_list) if(istype(R, /datum/reagent/ethanol)) - R.dose = max(R.dose - removed * 15, 0) + R.remove_self(removed * 15) /datum/reagent/hyronalin name = "Hyronalin" diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm index d9dda36eac..3df633c45b 100644 --- a/code/modules/reagents/Chemistry-Recipes.dm +++ b/code/modules/reagents/Chemistry-Recipes.dm @@ -2215,9 +2215,8 @@ name = "Deuterium" id = "deuterium" result = null - required_reagents = list("water" = 10) - catalysts = list("hydrophoron" = 5) - result_amount = 1 + required_reagents = list("hydrophoron" = 5, "water" = 10) + result_amount = 15 /datum/chemical_reaction/deuterium/on_reaction(var/datum/reagents/holder, var/created_volume) var/turf/T = get_turf(holder.my_atom) diff --git a/code/modules/reagents/reagent_containers/food/lunch.dm b/code/modules/reagents/reagent_containers/food/lunch.dm index 41119d1d6b..b1aab6de8c 100644 --- a/code/modules/reagents/reagent_containers/food/lunch.dm +++ b/code/modules/reagents/reagent_containers/food/lunch.dm @@ -59,7 +59,7 @@ var/list/lunchables_drink_reagents_ = list(/datum/reagent/drink/nothing, /datum/reagent/drink/hell_ramen, /datum/reagent/drink/hot_ramen, /datum/reagent/drink/soda/nuka_cola) - + // This default list is a bit different, it contains items we don't want var/list/lunchables_ethanol_reagents_ = list(/datum/reagent/ethanol/acid_spit, diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index fdc646168b..2fd46b34ef 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -390,6 +390,29 @@ reagents.add_reagent("coco", 2) bitesize = 2 +/obj/item/weapon/reagent_containers/food/snacks/chocolatepiece + name = "chocolate piece" + desc = "A luscious milk chocolate piece filled with gooey caramel." + icon_state = "chocolatepiece" + filling_color = "#7D5F46" + center_of_mass = list("x"=15, "y"=15) + nutriment_amt = 1 + nutriment_desc = list("chocolate" = 3, "caramel" = 2, "lusciousness" = 1) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/white + name = "white chocolate piece" + desc = "A creamy white chocolate piece drizzled in milk chocolate." + icon_state = "chocolatepiece_white" + filling_color = "#E2DAD3" + nutriment_desc = list("white chocolate" = 3, "creaminess" = 1) + +/obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/truffle + name = "chocolate truffle" + desc = "A bite-sized milk chocolate truffle that could buy anyone's love." + icon_state = "chocolatepiece_truffle" + nutriment_desc = list("chocolate" = 3, "undying devotion" = 3) + /obj/item/weapon/reagent_containers/food/snacks/chocolateegg name = "Chocolate Egg" desc = "Such sweet, fattening food." @@ -2459,9 +2482,9 @@ /obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread name = "meatbread loaf" - desc = "The culinary base of every self-respecting eloquen/tg/entleman." + desc = "The culinary base of every self-respecting eloquent gentleman." icon_state = "meatbread" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/slice/meatbread/filled + slice_path = /obj/item/weapon/reagent_containers/food/snacks/slice/meatbread slices_num = 5 filling_color = "#FF7575" center_of_mass = list("x"=19, "y"=9) @@ -2473,7 +2496,7 @@ reagents.add_reagent("protein", 20) bitesize = 2 -/obj/item/weapon/reagent_containers/food/snacks/slice/meatbread/filled +/obj/item/weapon/reagent_containers/food/snacks/slice/meatbread name = "meatbread slice" desc = "A slice of delicious meatbread." icon_state = "meatbreadslice" @@ -2483,14 +2506,14 @@ center_of_mass = list("x"=16, "y"=16) whole_path = /obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread -/obj/item/weapon/reagent_containers/food/snacks/slice/meatbread/filled/filled +/obj/item/weapon/reagent_containers/food/snacks/slice/meatbread/filled filled = TRUE /obj/item/weapon/reagent_containers/food/snacks/sliceable/xenomeatbread name = "xenomeatbread loaf" desc = "The culinary base of every self-respecting eloquent gentleman. Extra Heretical." icon_state = "xenomeatbread" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/slice/xenomeatbread/filled + slice_path = /obj/item/weapon/reagent_containers/food/snacks/slice/xenomeatbread slices_num = 5 filling_color = "#8AFF75" center_of_mass = list("x"=16, "y"=9) @@ -2502,7 +2525,7 @@ reagents.add_reagent("protein", 20) bitesize = 2 -/obj/item/weapon/reagent_containers/food/snacks/slice/xenomeatbread/filled +/obj/item/weapon/reagent_containers/food/snacks/slice/xenomeatbread name = "xenomeatbread slice" desc = "A slice of delicious meatbread. Extra Heretical." icon_state = "xenobreadslice" @@ -2513,7 +2536,7 @@ whole_path = /obj/item/weapon/reagent_containers/food/snacks/sliceable/xenomeatbread -/obj/item/weapon/reagent_containers/food/snacks/slice/xenomeatbread/filled/filled +/obj/item/weapon/reagent_containers/food/snacks/slice/xenomeatbread/filled filled = TRUE /obj/item/weapon/reagent_containers/food/snacks/sliceable/bananabread diff --git a/code/modules/research/mechfab_designs.dm b/code/modules/research/mechfab_designs.dm index 5936c3c9bc..8464c3efc3 100644 --- a/code/modules/research/mechfab_designs.dm +++ b/code/modules/research/mechfab_designs.dm @@ -259,6 +259,7 @@ name = "Cable Layer" id = "mech_cable_layer" build_path = /obj/item/mecha_parts/mecha_equipment/tool/cable_layer + materials = list(DEFAULT_WALL_MATERIAL = 7500, "plastic" = 1000) /datum/design/item/mecha/flaregun name = "Flare Launcher" @@ -305,6 +306,7 @@ /datum/design/item/mecha/weapon req_tech = list(TECH_COMBAT = 3) + materials = list(DEFAULT_WALL_MATERIAL = 8000, "glass" = 2000) // *** Weapon modules /datum/design/item/mecha/weapon/scattershot @@ -312,12 +314,14 @@ id = "mech_scattershot" req_tech = list(TECH_COMBAT = 4) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot + materials = list(DEFAULT_WALL_MATERIAL = 8000, "glass" = 3000, "plastic" = 2000, "silver" = 2500) /datum/design/item/mecha/weapon/laser name = "CH-PS \"Immolator\" Laser" id = "mech_laser" req_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 3) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser + materials = list(DEFAULT_WALL_MATERIAL = 8000, "glass" = 3000, "plastic" = 2000) /datum/design/item/mecha/weapon/laser_rigged name = "Jury-Rigged Welder-Laser" @@ -331,18 +335,21 @@ id = "mech_laser_heavy" req_tech = list(TECH_COMBAT = 4, TECH_MAGNET = 4) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy + materials = list(DEFAULT_WALL_MATERIAL = 10000, "glass" = 3000, "diamond" = 2000, "osmium" = 5000, "plastic" = 2000) /datum/design/item/mecha/weapon/ion name = "MK-IV Ion Heavy Cannon" id = "mech_ion" req_tech = list(TECH_COMBAT = 4, TECH_MAGNET = 4) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/ion + materials = list(DEFAULT_WALL_MATERIAL = 15000, "uranium" = 2000, "silver" = 2000, "osmium" = 4500, "plastic" = 2000) /datum/design/item/mecha/weapon/grenade_launcher name = "SGL-6 Grenade Launcher" id = "mech_grenade_launcher" req_tech = list(TECH_COMBAT = 3) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang + materials = list(DEFAULT_WALL_MATERIAL = 7000, "gold" = 2000, "plastic" = 3000) /datum/design/item/mecha/weapon/clusterbang_launcher name = "SOP-6 Grenade Launcher" @@ -396,7 +403,7 @@ desc = "An exosuit-mounted rapid construction device." id = "mech_rcd" time = 120 - materials = list(DEFAULT_WALL_MATERIAL = 22500, "phoron" = 18750, "silver" = 15000, "gold" = 15000) + materials = list(DEFAULT_WALL_MATERIAL = 20000, "plastic" = 10000, "phoron" = 18750, "silver" = 15000, "gold" = 15000) req_tech = list(TECH_MATERIAL = 4, TECH_BLUESPACE = 3, TECH_MAGNET = 4, TECH_POWER = 4, TECH_ENGINEERING = 4) build_path = /obj/item/mecha_parts/mecha_equipment/tool/rcd diff --git a/code/modules/shieldgen/shield_gen.dm b/code/modules/shieldgen/shield_gen.dm index 6100dda029..aa504fd7a6 100644 --- a/code/modules/shieldgen/shield_gen.dm +++ b/code/modules/shieldgen/shield_gen.dm @@ -20,27 +20,26 @@ var/target_field_strength = 10 var/max_field_strength = 10 var/time_since_fail = 100 - var/energy_conversion_rate = 0.0002 //how many renwicks per watt? Higher numbers equals more effiency. + var/energy_conversion_rate = 0.0006 //how many renwicks per watt? Higher numbers equals more effiency. var/z_range = 0 // How far 'up and or down' to extend the shield to, in z-levels. Only works on MultiZ supported z-levels. use_power = 0 //doesn't use APC power /obj/machinery/shield_gen/advanced name = "advanced bubble shield generator" desc = "A machine that generates a field of energy optimized for blocking meteorites when activated. This version comes with a more efficent shield matrix." - energy_conversion_rate = 0.0004 + energy_conversion_rate = 0.0012 -/obj/machinery/shield_gen/New() - spawn(1 SECOND) - if(anchored) - for(var/obj/machinery/shield_capacitor/cap in range(1, src)) - if(!cap.anchored) - continue - if(cap.owned_gen) - continue - if(get_dir(cap, src) == cap.dir) - capacitors |= cap - cap.owned_gen = src - ..() +/obj/machinery/shield_gen/initialize() + if(anchored) + for(var/obj/machinery/shield_capacitor/cap in range(1, src)) + if(!cap.anchored) + continue + if(cap.owned_gen) + continue + if(get_dir(cap, src) == cap.dir) + capacitors |= cap + cap.owned_gen = src + return ..() /obj/machinery/shield_gen/Destroy() qdel_null_list(field) diff --git a/code/modules/shieldgen/shield_gen_external.dm b/code/modules/shieldgen/shield_gen_external.dm index fa4702feee..0c0c0addd8 100644 --- a/code/modules/shieldgen/shield_gen_external.dm +++ b/code/modules/shieldgen/shield_gen_external.dm @@ -11,7 +11,7 @@ /obj/machinery/shield_gen/external/advanced name = "advanced hull shield generator" desc = "A machine that generates a field of energy optimized for blocking meteorites when activated. This version comes with a more efficent shield matrix." - energy_conversion_rate = 0.0004 + energy_conversion_rate = 0.0012 //Search for space turfs within range that are adjacent to a simulated turf. /obj/machinery/shield_gen/external/get_shielded_turfs_on_z_level(var/turf/gen_turf) diff --git a/code/modules/virus2/admin.dm b/code/modules/virus2/admin.dm index 5769aa099e..dc10bc85f9 100644 --- a/code/modules/virus2/admin.dm +++ b/code/modules/virus2/admin.dm @@ -11,7 +11,7 @@ usr << "Effects:" for(var/datum/disease2/effectholder/E in effects) usr << "[E.stage]: [E.effect.name]; chance=[E.chance]; multiplier=[E.multiplier]" - usr << "Antigens: [antigens2string(antigen)]" + usr << "Antigens: [antigens2string(antigen)]; Resistance: [resistance]" return 1 @@ -46,6 +46,7 @@ var/spreadtype = "Contact" var/list/antigens = list() var/speed = 1 + var/resistance = 10 var/mob/living/carbon/infectee = null // this holds spawned viruses so that the "Info" links work after the proc exits @@ -98,6 +99,7 @@ Infection Chance: [infectionchance]
Spread Type: [spreadtype]
Speed: [speed]
+ Resistance: [resistance]

"} f = 1 @@ -153,8 +155,8 @@ if(!I) return infectionchance = I if("stype") - var/S = alert("Which spread type?", "Spread Type", "Cancel", "Contact", "Airborne") - if(!S || S == "Cancel") return + var/S = alert("Which spread type?", "Spread Type", "Contact", "Airborne", "Blood") + if(!S) return spreadtype = S if("speed") var/S = input("Input speed", "Speed", speed) as null|num @@ -170,6 +172,10 @@ antigens |= T else if(href_list["reset"]) antigens = list() + if("resistance") + var/S = input("Input % resistance to antibiotics", "Resistance", resistance) as null|num + if(!S) return + resistance = S if("infectee") var/list/candidates = list() for(var/mob/living/carbon/G in living_mob_list) @@ -195,6 +201,7 @@ D.antigen = antigens D.affected_species = species D.speed = speed + D.resistance = resistance for(var/i in 1 to 4) var/datum/disease2/effectholder/E = new var/Etype = s[i] diff --git a/code/modules/virus2/analyser.dm b/code/modules/virus2/analyser.dm index 1bd3b3053c..af17836409 100644 --- a/code/modules/virus2/analyser.dm +++ b/code/modules/virus2/analyser.dm @@ -11,7 +11,10 @@ var/obj/item/weapon/virusdish/dish = null /obj/machinery/disease2/diseaseanalyser/attackby(var/obj/O as obj, var/mob/user as mob) - if(!istype(O,/obj/item/weapon/virusdish)) return + if(default_unfasten_wrench(user, O, 20)) + return + + else if(!istype(O,/obj/item/weapon/virusdish)) return if(dish) user << "\The [src] is already loaded." diff --git a/code/modules/virus2/centrifuge.dm b/code/modules/virus2/centrifuge.dm index f6cf9fe390..026bea5e5d 100644 --- a/code/modules/virus2/centrifuge.dm +++ b/code/modules/virus2/centrifuge.dm @@ -13,6 +13,9 @@ if(istype(O, /obj/item/weapon/screwdriver)) return ..(O,user) + if(default_unfasten_wrench(user, O, 20)) + return + if(istype(O,/obj/item/weapon/reagent_containers/glass/beaker/vial)) if(sample) user << "\The [src] is already loaded." diff --git a/code/modules/virus2/disease2.dm b/code/modules/virus2/disease2.dm index 9af07c48b6..fbe5123b2e 100644 --- a/code/modules/virus2/disease2.dm +++ b/code/modules/virus2/disease2.dm @@ -1,7 +1,7 @@ /datum/disease2/disease var/infectionchance = 70 var/speed = 1 - var/spreadtype = "Contact" // Can also be "Airborne" + var/spreadtype = "Blood" // Can also be "Contact" or "Airborne" var/stage = 1 var/stageprob = 10 var/dead = 0 @@ -11,6 +11,7 @@ var/antigen = list() // 16 bits describing the antigens, when one bit is set, a cure with that bit can dock here var/max_stage = 4 var/list/affected_species = list("Human","Unathi","Skrell","Tajara") + var/resistance = 10 // % chance a disease will resist cure, up to 100 /datum/disease2/disease/New() uniqueID = rand(0,10000) @@ -36,6 +37,7 @@ antigen = list(pick(ALL_ANTIGENS)) antigen |= pick(ALL_ANTIGENS) spreadtype = prob(70) ? "Airborne" : "Contact" + resistance = rand(15,70) if(all_species.len) affected_species = get_infectable_species() @@ -79,11 +81,17 @@ if(prob(1)) majormutate() - //Space antibiotics stop disease completely + //Space antibiotics have a good chance to stop disease completely if(mob.reagents.has_reagent("spaceacillin")) - if(stage == 1 && prob(20)) + if(stage == 1 && prob(70-resistance)) src.cure(mob) - return + else + resistance += rand(1,9) + + //Resistance is capped at 90 without being manually set to 100 + if(resistance > 90 && resistance < 100) + resistance = 90 + //Virus food speeds up disease progress if(mob.reagents.has_reagent("virusfood")) @@ -96,7 +104,7 @@ //Moving to the next stage if(clicks > max(stage*100, 200) && prob(10)) - if((stage <= max_stage) && prob(20)) // ~60% of viruses will be cured by the end of S4 with this + if((stage <= max_stage) && prob(5)) // ~20% of viruses will be cured by the end of S4 with this src.cure(mob) mob.antibodies |= src.antigen stage++ @@ -137,11 +145,15 @@ if(D != holder) exclude += D.effect.type holder.majormutate(exclude) - if (prob(5)) + if (prob(5) && prob(100-resistance)) // The more resistant the disease,the lower the chance of randomly developing the antibodies antigen = list(pick(ALL_ANTIGENS)) antigen |= pick(ALL_ANTIGENS) if (prob(5) && all_species.len) affected_species = get_infectable_species() + if (prob(10)) + resistance += rand(1,9) + if(resistance > 90 && resistance < 100) + resistance = 90 /datum/disease2/disease/proc/getcopy() var/datum/disease2/disease/disease = new /datum/disease2/disease @@ -210,6 +222,7 @@ var/global/list/virusDB = list() Antigen: [antigens2string(antigen)]
Transmitted By: [spreadtype]
Rate of Progression: [stageprob * 10]
+ Antibiotic Resistance [resistance]%
Species Affected: [jointext(affected_species, ", ")]
"} @@ -217,7 +230,7 @@ var/global/list/virusDB = list() for(var/datum/disease2/effectholder/E in effects) r += "([E.stage]) [E.effect.name] " r += "Strength: [E.multiplier >= 3 ? "Severe" : E.multiplier > 1 ? "Above Average" : "Average"] " - r += "Verosity: [E.chance * 15]
" + r += "Aggressiveness: [E.chance * 15]
" return r diff --git a/code/modules/virus2/diseasesplicer.dm b/code/modules/virus2/diseasesplicer.dm index 298dc49f27..d9a875050d 100644 --- a/code/modules/virus2/diseasesplicer.dm +++ b/code/modules/virus2/diseasesplicer.dm @@ -15,6 +15,9 @@ if(istype(I, /obj/item/weapon/screwdriver)) return ..(I,user) + if(default_unfasten_wrench(user, I, 20)) + return + if(istype(I,/obj/item/weapon/virusdish)) var/mob/living/carbon/c = user if (dish) diff --git a/code/modules/virus2/dishincubator.dm b/code/modules/virus2/dishincubator.dm index ed6810980c..c94370cebd 100644 --- a/code/modules/virus2/dishincubator.dm +++ b/code/modules/virus2/dishincubator.dm @@ -15,6 +15,9 @@ var/toxins = 0 /obj/machinery/disease2/incubator/attackby(var/obj/O as obj, var/mob/user as mob) + if(default_unfasten_wrench(user, O, 20)) + return + if(istype(O, /obj/item/weapon/reagent_containers/glass) || istype(O,/obj/item/weapon/reagent_containers/syringe)) if(beaker) @@ -131,9 +134,6 @@ if(foodsupply < 100 && beaker.reagents.remove_reagent("virusfood",5)) if(foodsupply + 10 <= 100) foodsupply += 10 - else - beaker.reagents.add_reagent("virusfood",(100 - foodsupply)/2) - foodsupply = 100 nanomanager.update_uis(src) if (locate(/datum/reagent/toxin) in beaker.reagents.reagent_list && toxins < 100) diff --git a/code/modules/virus2/effect.dm b/code/modules/virus2/effect.dm index 523b8e1eaf..51774ecfac 100644 --- a/code/modules/virus2/effect.dm +++ b/code/modules/virus2/effect.dm @@ -58,8 +58,10 @@ /datum/disease2/effect/invisible name = "Waiting Syndrome" stage = 1 - activate(var/mob/living/carbon/mob,var/multiplier) - return + badness = 3 + +/datum/disease2/effect/invisible/activate(var/mob/living/carbon/mob,var/multiplier) + return ////////////////////////STAGE 4///////////////////////////////// @@ -70,142 +72,183 @@ chance_maxm = 0 /datum/disease2/effect/gibbingtons - name = "Gibbingtons Syndrome" + name = "Gibbington's Syndrome" stage = 4 badness = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - // Probabilities have been tweaked to kill in ~2-3 minutes, giving 5-10 messages. - // Probably needs more balancing, but it's better than LOL U GIBBED NOW, especially now that viruses can potentially have no signs up until Gibbingtons. - mob.adjustBruteLoss(10*multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - var/obj/item/organ/external/O = pick(H.organs) - if(prob(25)) - mob << "Your [O.name] feels as if it might burst!" - if(prob(10)) - spawn(50) - if(O) - O.droplimb(0,DROPLIMB_BLUNT) - else - if(prob(75)) - mob << "Your whole body feels like it might fall apart!" - if(prob(10)) - mob.adjustBruteLoss(25*multiplier) + +/datum/disease2/effect/gibbingtons/activate(var/mob/living/carbon/mob,var/multiplier) + // Probabilities have been tweaked to kill in ~2-3 minutes, giving 5-10 messages. + // Probably needs more balancing, but it's better than LOL U GIBBED NOW, especially now that viruses can potentially have no signs up until Gibbingtons. + mob.adjustBruteLoss(10*multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + var/obj/item/organ/external/O = pick(H.organs) + if(prob(25)) + mob << "Your [O.name] feels as if it might burst!" + if(prob(10)) + spawn(50) + if(O) + O.droplimb(0,DROPLIMB_BLUNT) + else + if(prob(75)) + mob << "Your whole body feels like it might fall apart!" + if(prob(10)) + mob.adjustBruteLoss(25*multiplier) /datum/disease2/effect/radian name = "Radian's Syndrome" stage = 4 maxm = 3 badness = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.apply_effect(2*multiplier, IRRADIATE, check_protection = 0) + +/datum/disease2/effect/radian/activate(var/mob/living/carbon/mob,var/multiplier) + mob.apply_effect(2*multiplier, IRRADIATE, check_protection = 0) /datum/disease2/effect/deaf - name = "Dead Ear Syndrome" + name = "Deafness" stage = 4 badness = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.ear_deaf += 20 + +/datum/disease2/effect/deaf/activate(var/mob/living/carbon/mob,var/multiplier) + mob.ear_deaf += 20 /datum/disease2/effect/monkey - name = "Monkism Syndrome" + name = "Genome Regression" stage = 4 badness = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob,/mob/living/carbon/human)) - var/mob/living/carbon/human/h = mob - h.monkeyize() + +/datum/disease2/effect/monkey/activate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob,/mob/living/carbon/human)) + var/mob/living/carbon/human/h = mob + h.monkeyize() /datum/disease2/effect/suicide - name = "Suicidal Syndrome" + name = "Windpipe Contraction" stage = 4 badness = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - var/datum/gender/TM = gender_datums[mob.get_visible_gender()] - mob.suiciding = 30 - //instead of killing them instantly, just put them at -175 health and let 'em gasp for a while - viewers(mob) << "[mob.name] is holding [TM.his] breath. It looks like [TM.he] [TM.is] trying to commit suicide." - mob.adjustOxyLoss(175 - mob.getToxLoss() - mob.getFireLoss() - mob.getBruteLoss() - mob.getOxyLoss()) - mob.updatehealth() + +/datum/disease2/effect/suicide/activate(var/mob/living/carbon/mob,var/multiplier) + var/datum/gender/TM = gender_datums[mob.get_visible_gender()] + mob.suiciding = 30 + //instead of killing them instantly, just put them at -175 health and let 'em gasp for a while + viewers(mob) << "[mob.name] is holding [TM.his] breath. It looks like [TM.he] [TM.is] trying to commit suicide." + mob.adjustOxyLoss(175 - mob.getToxLoss() - mob.getFireLoss() - mob.getBruteLoss() - mob.getOxyLoss()) + mob.updatehealth() /datum/disease2/effect/killertoxins - name = "Toxification Syndrome" + name = "Autoimmune Reponse" stage = 4 badness = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.adjustToxLoss(15*multiplier) + +/datum/disease2/effect/killertoxins/activate(var/mob/living/carbon/mob,var/multiplier) + mob.adjustToxLoss(15*multiplier) /datum/disease2/effect/dna - name = "Reverse Pattern Syndrome" + name = "Catastrophic DNA Degeneration" stage = 4 badness = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.bodytemperature = max(mob.bodytemperature, 350) - scramble(0,mob,10) - mob.apply_damage(10, CLONE) + +/datum/disease2/effect/dna/activate(var/mob/living/carbon/mob,var/multiplier) + mob.bodytemperature = max(mob.bodytemperature, 350) + scramble(0,mob,10) + mob.apply_damage(10, CLONE) /datum/disease2/effect/organs - name = "Shutdown Syndrome" + name = "Limb Paralysis" stage = 4 badness = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - var/organ = pick(list("r_arm","l_arm","r_leg","r_leg")) - var/obj/item/organ/external/E = H.organs_by_name[organ] - if (!(E.status & ORGAN_DEAD)) - E.status |= ORGAN_DEAD - H << "You can't feel your [E.name] anymore..." - for (var/obj/item/organ/external/C in E.children) - C.status |= ORGAN_DEAD - H.update_icons_body() - mob.adjustToxLoss(15*multiplier) - deactivate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - for (var/obj/item/organ/external/E in H.organs) - E.status &= ~ORGAN_DEAD - for (var/obj/item/organ/external/C in E.children) - C.status &= ~ORGAN_DEAD - H.update_icons_body() +/datum/disease2/effect/organs/activate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + var/organ = pick(list("r_arm","l_arm","r_leg","l_leg")) + var/obj/item/organ/external/E = H.organs_by_name[organ] + if (!(E.status & ORGAN_DEAD)) + E.status |= ORGAN_DEAD + H << "You can't feel your [E.name] anymore..." + for (var/obj/item/organ/external/C in E.children) + C.status |= ORGAN_DEAD + H.update_icons_body() + mob.adjustToxLoss(15*multiplier) + +/datum/disease2/effect/organs/deactivate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + for (var/obj/item/organ/external/E in H.organs) + E.status &= ~ORGAN_DEAD + for (var/obj/item/organ/external/C in E.children) + C.status &= ~ORGAN_DEAD + H.update_icons_body() + +/datum/disease2/effect/internalorgan + name = "Organ Shutdown" + stage = 4 + badness = 2 + +/datum/disease2/effect/internalorgan/activate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + var/organ = pick(list("heart","kidney","liver", "lungs")) + var/obj/item/organ/internal/O = H.organs_by_name[organ] + if (!(O.robotic = ORGAN_ROBOT)) + O.damage += (5*multiplier) + H << "You feel a cramp in your guts." /datum/disease2/effect/immortal - name = "Longevity Syndrome" + name = "Hyperaccelerated Aging" stage = 4 badness = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - for (var/obj/item/organ/external/E in H.organs) - if (E.status & ORGAN_BROKEN && prob(30)) - E.status ^= ORGAN_BROKEN - var/heal_amt = -5*multiplier - mob.apply_damages(heal_amt,heal_amt,heal_amt,heal_amt) - deactivate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - H << "You suddenly feel hurt and old..." - H.age += 8 - var/backlash_amt = 5*multiplier - mob.apply_damages(backlash_amt,backlash_amt,backlash_amt,backlash_amt) +/datum/disease2/effect/immortal/activate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + for (var/obj/item/organ/external/E in H.organs) + if (E.status & ORGAN_BROKEN && prob(30)) + E.status ^= ORGAN_BROKEN + var/heal_amt = -5*multiplier + mob.apply_damages(heal_amt,heal_amt,heal_amt,heal_amt) + +/datum/disease2/effect/immortal/deactivate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + H << "You suddenly feel hurt and old..." + H.age += 8 + var/backlash_amt = 5*multiplier + mob.apply_damages(backlash_amt,backlash_amt,backlash_amt,backlash_amt) /datum/disease2/effect/bones - name = "Fragile Bones Syndrome" + name = "Brittle Bones" stage = 4 badness = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - for (var/obj/item/organ/external/E in H.organs) - E.min_broken_damage = max(5, E.min_broken_damage - 30) +/datum/disease2/effect/bones/activate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + for (var/obj/item/organ/external/E in H.organs) + E.min_broken_damage = max(5, E.min_broken_damage - 30) + +/datum/disease2/effect/bones/deactivate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + for (var/obj/item/organ/external/E in H.organs) + E.min_broken_damage = initial(E.min_broken_damage) + +/datum/disease2/effect/combustion + name = "Organic Ignition" + stage = 4 + badness = 3 + +/datum/disease2/effect/combustion/activate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + var/obj/item/organ/external/O = pick(H.organs) + if(prob(25)) + mob << "It feels like your [O.name] is on fire and your blood is boiling!" + H.adjust_fire_stacks(1) + if(prob(10)) + mob << "Flames erupt from your skin, your entire body is burning!" + H.adjust_fire_stacks(2) + H.IgniteMob() - deactivate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - for (var/obj/item/organ/external/E in H.organs) - E.min_broken_damage = initial(E.min_broken_damage) ////////////////////////STAGE 3///////////////////////////////// @@ -213,201 +256,279 @@ name = "Hyperacidity" stage = 3 maxm = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.adjustToxLoss((2*multiplier)) + +/datum/disease2/effect/toxins/activate(var/mob/living/carbon/mob,var/multiplier) + mob.adjustToxLoss((2*multiplier)) /datum/disease2/effect/shakey - name = "World Shaking Syndrome" + name = "Nervous Motor Instability" stage = 3 maxm = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - shake_camera(mob,5*multiplier) + +/datum/disease2/effect/shakey/activate(var/mob/living/carbon/mob,var/multiplier) + shake_camera(mob,5*multiplier) /datum/disease2/effect/telepathic - name = "Telepathy Syndrome" + name = "Pineal Gland Decalcification" stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) + +/datum/disease2/effect/telepathic/activate(var/mob/living/carbon/mob,var/multiplier) mob.dna.SetSEState(REMOTETALKBLOCK,1) domutcheck(mob, null, MUTCHK_FORCED) /datum/disease2/effect/mind - name = "Lazy Mind Syndrome" + name = "Neurodegeneration" stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - var/obj/item/organ/internal/brain/B = H.internal_organs_by_name["brain"] - if (B && B.damage < B.min_broken_damage) - B.take_damage(5) - else - mob.setBrainLoss(10) + +/datum/disease2/effect/mind/activate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + var/obj/item/organ/internal/brain/B = H.internal_organs_by_name["brain"] + if (B && B.damage < B.min_broken_damage) + B.take_damage(5) + else + mob.setBrainLoss(10) /datum/disease2/effect/hallucinations - name = "Hallucinational Syndrome" + name = "Hallucination" stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.hallucination += 25 -/datum/disease2/effect/deaf - name = "Hard of Hearing Syndrome" +/datum/disease2/effect/hallucinations/activate(var/mob/living/carbon/mob,var/multiplier) + mob.hallucination += 25 + +/datum/disease2/effect/minordeaf + name = "Hearing Loss" stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.ear_deaf = 5 + +/datum/disease2/effect/minordeaf/activate(var/mob/living/carbon/mob,var/multiplier) + mob.ear_deaf = 5 /datum/disease2/effect/giggle - name = "Uncontrolled Laughter Effect" + name = "Uncontrolled Laughter" stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) + chance_maxm = 20 + +/datum/disease2/effect/giggle/activate(var/mob/living/carbon/mob,var/multiplier) + if(prob(66)) mob.say("*giggle") + else + to_chat(mob,"What's so funny?") /datum/disease2/effect/confusion name = "Topographical Cretinism" stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob << "You have trouble telling right and left apart all of a sudden." - mob.Confuse(10) + +/datum/disease2/effect/confusion/activate(var/mob/living/carbon/mob,var/multiplier) + mob << "You have trouble telling right and left apart all of a sudden." + mob.Confuse(10) /datum/disease2/effect/mutation name = "DNA Degradation" stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.apply_damage(2, CLONE) + +/datum/disease2/effect/mutation/activate(var/mob/living/carbon/mob,var/multiplier) + mob.apply_damage(2, CLONE) /datum/disease2/effect/groan - name = "Groaning Syndrome" + name = "Phantom Aches" stage = 3 - chance_maxm = 25 - activate(var/mob/living/carbon/mob,var/multiplier) + chance_maxm = 20 + +/datum/disease2/effect/groan/activate(var/mob/living/carbon/mob,var/multiplier) + if(prob(66)) mob.say("*groan") + else if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + var/obj/item/organ/external/E = pick(H.organs) + to_chat(mob,"Your [E] aches.") /datum/disease2/effect/chem_synthesis name = "Chemical Synthesis" stage = 3 chance_maxm = 25 - generate(c_data) - if(c_data) - data = c_data - else - data = pick("bicaridine", "kelotane", "anti_toxin", "inaprovaline", "space_drugs", "sugar", - "tramadol", "dexalin", "cryptobiolin", "impedrezene", "hyperzine", "ethylredoxrazine", - "mindbreaker", "glucose") - var/datum/reagent/R = chemical_reagents_list[data] - name = "[initial(name)] ([initial(R.name)])" +/datum/disease2/effect/chem_synthesis/generate(c_data) + if(c_data) + data = c_data + else + data = pick("bicaridine", "kelotane", "anti_toxin", "inaprovaline", "space_drugs", "sugar", + "tramadol", "dexalin", "cryptobiolin", "impedrezene", "hyperzine", "ethylredoxrazine", + "mindbreaker", "glucose") + var/datum/reagent/R = chemical_reagents_list[data] + name = "[initial(name)] ([initial(R.name)])" + +/datum/disease2/effect/chem_synthesis/activate(var/mob/living/carbon/mob,var/multiplier) + if (mob.reagents.get_reagent_amount(data) < 5) + mob.reagents.add_reagent(data, 2) + +/datum/disease2/effect/nonrejection + name = "Genetic Chameleonism" + stage = 3 + +/datum/disease2/effect/nonrejection/activate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + var/obj/item/organ/internal/O = H.organs_by_name + for (var/organ in H.organs_by_name) + if (!(O.robotic = ORGAN_ROBOT)) + O.rejecting = 0 - activate(var/mob/living/carbon/mob,var/multiplier) - if (mob.reagents.get_reagent_amount(data) < 5) - mob.reagents.add_reagent(data, 2) ////////////////////////STAGE 2///////////////////////////////// /datum/disease2/effect/scream - name = "Loudness Syndrome" + name = "Involuntary Vocalization" stage = 2 - chance_maxm = 25 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*scream") + chance_maxm = 10 + +/datum/disease2/effect/scream/activate(var/mob/living/carbon/mob,var/multiplier) + mob.say("*scream") /datum/disease2/effect/drowsness - name = "Automated Sleeping Syndrome" + name = "Excessive Sleepiness" stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.drowsyness += 10 + +/datum/disease2/effect/drowsness/activate(var/mob/living/carbon/mob,var/multiplier) + mob.drowsyness += 10 /datum/disease2/effect/sleepy - name = "Resting Syndrome" + name = "Narcolepsy" stage = 2 chance_maxm = 15 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*collapse") + +/datum/disease2/effect/sleepy/activate(var/mob/living/carbon/mob,var/multiplier) + mob.say("*collapse") /datum/disease2/effect/blind - name = "Blackout Syndrome" + name = "Vision Loss" stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.eye_blind = max(mob.eye_blind, 4) + +/datum/disease2/effect/blind/activate(var/mob/living/carbon/mob,var/multiplier) + mob.eye_blind = max(mob.eye_blind, 4) /datum/disease2/effect/cough - name = "Anima Syndrome" + name = "Severe Cough" stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) + chance_maxm = 20 + +/datum/disease2/effect/cough/activate(var/mob/living/carbon/mob,var/multiplier) + if(prob(60)) mob.say("*cough") for(var/mob/living/carbon/M in oview(2,mob)) mob.spread_disease_to(M) + else + to_chat(mob,"Something gets caught in your throat.") /datum/disease2/effect/hungry - name = "Appetiser Effect" + name = "Digestive Inefficiency" stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.nutrition = max(0, mob.nutrition - 200) + +/datum/disease2/effect/hungry/activate(var/mob/living/carbon/mob,var/multiplier) + mob.nutrition = max(0, mob.nutrition - 200) /datum/disease2/effect/fridge - name = "Refridgerator Syndrome" + name = "Reduced Circulation" stage = 2 chance_maxm = 25 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*shiver") + +/datum/disease2/effect/fridge/activate(var/mob/living/carbon/mob,var/multiplier) + mob.say("*shiver") /datum/disease2/effect/hair name = "Hair Loss" stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - if(H.species.name == "Human" && !(H.h_style == "Bald") && !(H.h_style == "Balding Hair")) - H << "Your hair starts to fall out in clumps..." - spawn(50) - H.h_style = "Balding Hair" - H.update_hair() + +/datum/disease2/effect/hair/activate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + if(H.species.name == "Human" && !(H.h_style == "Bald") && !(H.h_style == "Balding Hair")) + H << "Your hair starts to fall out in clumps..." + spawn(50) + H.h_style = "Balding Hair" + H.update_hair() /datum/disease2/effect/stimulant - name = "Adrenaline Extra" + name = "Overactive Adrenal Gland" stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob << "You feel a rush of energy inside you!" - if (mob.reagents.get_reagent_amount("hyperzine") < 10) - mob.reagents.add_reagent("hyperzine", 4) - if (prob(30)) - mob.jitteriness += 10 + +/datum/disease2/effect/stimulant/activate(var/mob/living/carbon/mob,var/multiplier) + mob << "You feel a rush of energy inside you!" + if (mob.reagents.get_reagent_amount("hyperzine") < 10) + mob.reagents.add_reagent("hyperzine", 4) + if (prob(30)) + mob.jitteriness += 10 + +/datum/disease2/effect/ringing + name = "Tinnitus" + stage = 2 + chance_maxm = 25 + +/datum/disease2/effect/ringing/activate(var/mob/living/carbon/mob,var/multiplier) + if(istype(mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = mob + H << "You hear an awful ringing in your ears." + H << 'sound/weapons/flash.ogg' + +/datum/disease2/effect/vomiting + name = "Vomiting" + stage = 2 + chance_maxm = 15 + +/datum/disease2/effect/vomiting/activate(var/mob/living/carbon/mob,var/multiplier) + mob << "Your stomach churns!" + if (prob(50)) + mob.say("*vomit") ////////////////////////STAGE 1///////////////////////////////// /datum/disease2/effect/sneeze - name = "Coldingtons Effect" + name = "Sneezing" stage = 1 - activate(var/mob/living/carbon/mob,var/multiplier) - if (prob(30)) - mob << "You feel like you are about to sneeze!" - sleep(5) - mob.say("*sneeze") - for(var/mob/living/carbon/M in get_step(mob,mob.dir)) - mob.spread_disease_to(M) - if (prob(50)) - var/obj/effect/decal/cleanable/mucus/M = new(get_turf(mob)) - M.virus2 = virus_copylist(mob.virus2) + chance_maxm = 20 + +/datum/disease2/effect/sneeze/activate(var/mob/living/carbon/mob,var/multiplier) + if(prob(20)) + to_chat(mob,"You go to sneeze, but it gets caught in your sinuses!") + else if(prob(80)) + if(prob(30)) + to_chat(mob,"You feel like you are about to sneeze!") + spawn(5) //Sleep may have been hanging Mob controller. + mob.say("*sneeze") + for(var/mob/living/carbon/M in get_step(mob,mob.dir)) + mob.spread_disease_to(M) + if (prob(50)) + var/obj/effect/decal/cleanable/mucus/M = new(get_turf(mob)) + M.virus2 = virus_copylist(mob.virus2) /datum/disease2/effect/gunck - name = "Flemmingtons" + name = "Mucus Buildup" stage = 1 - activate(var/mob/living/carbon/mob,var/multiplier) - mob << "Mucous runs down the back of your throat." + +/datum/disease2/effect/gunck/activate(var/mob/living/carbon/mob,var/multiplier) + mob << "Mucous runs down the back of your throat." /datum/disease2/effect/drool - name = "Saliva Effect" + name = "Salivary Gland Stimulation" stage = 1 - chance_maxm = 25 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*drool") + chance_maxm = 15 + +/datum/disease2/effect/drool/activate(var/mob/living/carbon/mob,var/multiplier) + mob.say("*drool") + if (prob(30)) + var/obj/effect/decal/cleanable/mucus/M = new(get_turf(mob)) + M.virus2 = virus_copylist(mob.virus2) /datum/disease2/effect/twitch - name = "Twitcher" + name = "Involuntary Twitching" stage = 1 - chance_maxm = 25 - activate(var/mob/living/carbon/mob,var/multiplier) + chance_maxm = 15 + +/datum/disease2/effect/twitch/activate(var/mob/living/carbon/mob,var/multiplier) mob.say("*twitch") /datum/disease2/effect/headache name = "Headache" stage = 1 - activate(var/mob/living/carbon/mob,var/multiplier) + +/datum/disease2/effect/headache/activate(var/mob/living/carbon/mob,var/multiplier) mob << "Your head hurts a bit." diff --git a/code/modules/virus2/helpers.dm b/code/modules/virus2/helpers.dm index 4daae5c5e2..d10fdbfb68 100644 --- a/code/modules/virus2/helpers.dm +++ b/code/modules/virus2/helpers.dm @@ -82,7 +82,15 @@ proc/airborne_can_reach(turf/source, turf/target) if(antibodies_in_common.len) return if(M.reagents.has_reagent("spaceacillin")) - return + if(prob(disease.resistance)) + var/datum/disease2/disease/D = disease.getcopy() + D.minormutate() + D.resistance += rand(1,9) +// log_debug("Adding virus") + M.virus2["[D.uniqueID]"] = D + BITSET(M.hud_updateflag, STATUS_HUD) + else + return //Virus prevented by antibiotics if(!disease.affected_species.len) return diff --git a/code/modules/virus2/isolator.dm b/code/modules/virus2/isolator.dm index 6a27d2f17d..d992a9c99b 100644 --- a/code/modules/virus2/isolator.dm +++ b/code/modules/virus2/isolator.dm @@ -28,7 +28,10 @@ icon_state = "isolator" /obj/machinery/disease2/isolator/attackby(var/obj/O as obj, var/mob/user) - if(!istype(O,/obj/item/weapon/reagent_containers/syringe)) return + if(default_unfasten_wrench(user, O, 20)) + return + + else if(!istype(O,/obj/item/weapon/reagent_containers/syringe)) return var/obj/item/weapon/reagent_containers/syringe/S = O if(sample) diff --git a/code/modules/xenoarcheaology/finds/misc.dm b/code/modules/xenoarcheaology/finds/misc.dm index 2729872876..ded227bd3a 100644 --- a/code/modules/xenoarcheaology/finds/misc.dm +++ b/code/modules/xenoarcheaology/finds/misc.dm @@ -10,9 +10,12 @@ anchored = TRUE /obj/machinery/crystal/New() - if(prob(50)) + if(prob(30)) icon_state = "crystal2" set_light(3, 3, "#CC00CC") + else if(prob(30)) + icon_state = "crystal3" + set_light(3, 3, "#FF003B") else set_light(3, 3, "#33CC33") diff --git a/code/modules/xenobio/items/extracts.dm b/code/modules/xenobio/items/extracts.dm index f6fb5c885c..8c05faa919 100644 --- a/code/modules/xenobio/items/extracts.dm +++ b/code/modules/xenobio/items/extracts.dm @@ -896,7 +896,7 @@ on_expired_text = "The spores of goo have faded, and you feel your agility returning to what it was before." stacks = MODIFIER_STACK_EXTEND - evasion = 2 + evasion = 30 slowdown = -1 attack_speed_percent = 0.75 diff --git a/code/modules/xenobio/items/weapons.dm b/code/modules/xenobio/items/weapons.dm index a1aba76dab..ec64773cd3 100644 --- a/code/modules/xenobio/items/weapons.dm +++ b/code/modules/xenobio/items/weapons.dm @@ -56,20 +56,33 @@ name = "xeno taser gun" desc = "Straight out of NT's testing laboratories, this small gun is used to subdue non-humanoid xeno life forms. \ While marketed towards handling slimes, it may be useful for other creatures." - desc = "An easy to use weapon designed by NanoTrasen, for NanoTrasen. This weapon is designed to subdue lesser \ - xeno lifeforms at a distance. It is ineffective at stunning larger lifeforms such as humanoids." icon_state = "taserold" fire_sound = 'sound/weapons/taser2.ogg' charge_cost = 120 // Twice as many shots. projectile_type = /obj/item/projectile/beam/stun/xeno - accuracy = 2 // Make it a bit easier to hit the slimes. + accuracy = 30 // Make it a bit easier to hit the slimes. description_info = "This gun will stun a slime or other lesser lifeform for about two seconds, if hit with the projectile it fires." + description_fluff = "An easy to use weapon designed by NanoTrasen, for NanoTrasen. This weapon is designed to subdue lesser \ + xeno lifeforms at a distance. It is ineffective at stunning larger lifeforms such as humanoids." /obj/item/weapon/gun/energy/taser/xeno/robot // Borg version self_recharge = 1 use_external_power = 1 recharge_time = 3 +/obj/item/weapon/gun/energy/taser/xeno/sec //NT's corner-cutting option for their on-station security. + desc = "An NT Mk30 NL retrofitted to fire beams for subduing non-humanoid xeno life forms." + icon_state = "taserblue" + item_state = "taser" + projectile_type = /obj/item/projectile/beam/stun/xeno/weak + charge_cost = 240 + accuracy = 0 //Same accuracy as a normal Sec taser. + description_fluff = "An NT Mk30 NL retrofitted after the events that occurred aboard the NRS Prometheus." + +/obj/item/weapon/gun/energy/taser/xeno/sec/robot //Cyborg variant of the security xeno-taser. + self_recharge = 1 + use_external_power = 1 + recharge_time = 3 /obj/item/projectile/beam/stun/xeno icon_state = "omni" @@ -83,7 +96,10 @@ tracer_type = /obj/effect/projectile/laser_omni/tracer impact_type = /obj/effect/projectile/laser_omni/impact -/obj/item/projectile/beam/stun/xeno/on_hit(var/atom/target, var/blocked = 0) +/obj/item/projectile/beam/stun/xeno/weak //Weaker variant for non-research equipment, turrets, or rapid fire types. + agony = 3 + +/obj/item/projectile/beam/stun/xeno/on_hit(var/atom/target, var/blocked = 0, var/def_zone = null) if(istype(target, /mob/living)) var/mob/living/L = target @@ -91,15 +107,15 @@ if(istype(L, /mob/living/simple_animal/slime)) var/mob/living/simple_animal/SA = L if(SA.intelligence_level <= SA_ANIMAL) // So it doesn't stun hivebots or syndies. - SA.Weaken(2) // Less powerful since its ranged, and therefore safer. + SA.Weaken(round(agony/2)) // Less powerful since its ranged, and therefore safer. if(isslime(SA)) var/mob/living/simple_animal/slime/S = SA - S.adjust_discipline(2) + S.adjust_discipline(round(agony/2)) // Prometheans. if(ishuman(L)) var/mob/living/carbon/human/H = L if(H.species && H.species.name == "Promethean") - var/agony_to_apply = 60 - agony - H.apply_damage(agony_to_apply, HALLOSS) - ..() \ No newline at end of file + if(agony == initial(agony)) + agony = round((14 * agony) - agony) //60-4 = 56, 56 / 4 = 14. Prior was flat 60 - agony of the beam to equate to 60. + ..() diff --git a/html/changelog.html b/html/changelog.html index 45d9cd6099..629a7c1c02 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,80 @@ -->
+

10 February 2018

+

Atermonera updated:

+ +

Cerebulon updated:

+ +

Hubblenaut updated:

+ +

Leshana and mustafakalash updated:

+ +

MistyLuminescence updated:

+ +

Woodrat updated:

+ + +

07 February 2018

+

Anewbe updated:

+ +

Atermonera updated:

+ +

Cerebulon updated:

+ +

Mechoid updated:

+ +

SunnyDaff updated:

+ +

25 January 2018

Anewbe updated: