diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index a014d30878e..2b4c3586bf9 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,15 +9,27 @@ assignees: '' **Issue Description**: + + **What did you expect to happen**: + + **What happened instead**: + + **Why is this bad/What are the consequences**: + + **Steps to reproduce the problem**: + + **When did the problem start happening**: + + **Extra information**: diff --git a/_maps/map_files/Delta/delta.dmm b/_maps/map_files/Delta/delta.dmm index fb8cbaf4304..37231b29651 100644 --- a/_maps/map_files/Delta/delta.dmm +++ b/_maps/map_files/Delta/delta.dmm @@ -49652,8 +49652,8 @@ /obj/item/radio/intercom{ pixel_y = 28 }, -/obj/machinery/deployable/barrier, -/obj/machinery/deployable/barrier, +/obj/item/grenade/barrier, +/obj/item/grenade/barrier, /turf/simulated/floor/plasteel{ icon_state = "vault"; dir = 8 @@ -49673,8 +49673,8 @@ }, /area/security/armoury) "bLK" = ( -/obj/machinery/deployable/barrier, -/obj/machinery/deployable/barrier, +/obj/item/grenade/barrier, +/obj/item/grenade/barrier, /turf/simulated/floor/plasteel{ icon_state = "vault"; dir = 8 diff --git a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm index 5c09a328037..ccfadc2ab79 100644 --- a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm +++ b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm @@ -4795,10 +4795,10 @@ /obj/structure/reagent_dispensers/peppertank{ pixel_y = 29 }, -/obj/machinery/deployable/barrier, -/obj/machinery/deployable/barrier, -/obj/machinery/deployable/barrier, -/obj/machinery/deployable/barrier, +/obj/item/grenade/barrier, +/obj/item/grenade/barrier, +/obj/item/grenade/barrier, +/obj/item/grenade/barrier, /turf/simulated/floor/plasteel{ tag = "icon-vault (WEST)"; icon_state = "vault"; diff --git a/_maps/map_files/RandomZLevels/beach.dmm b/_maps/map_files/RandomZLevels/beach.dmm index 2931d7175b7..fe4060ad52d 100644 --- a/_maps/map_files/RandomZLevels/beach.dmm +++ b/_maps/map_files/RandomZLevels/beach.dmm @@ -13,7 +13,7 @@ /turf/unsimulated/beach/water/deep/rock_wall, /area/awaymission/undersea) "ae" = ( -/obj/structure/ladder/dive_point/anchor{ +/obj/structure/ladder/unbreakable/dive_point/anchor{ id = "pirate" }, /turf/unsimulated/beach/water/deep/sand_floor, @@ -217,7 +217,7 @@ /turf/unsimulated/beach/water/deep/wood_floor, /area/awaymission/undersea) "aU" = ( -/obj/structure/ladder/dive_point/anchor, +/obj/structure/ladder/unbreakable/dive_point/anchor, /turf/unsimulated/beach/water/deep/sand_floor, /area/awaymission/undersea) "aV" = ( @@ -1113,7 +1113,7 @@ /turf/unsimulated/beach/water/deep, /area/awaymission/beach) "dv" = ( -/obj/structure/ladder/dive_point/buoy, +/obj/structure/ladder/unbreakable/dive_point/buoy, /turf/unsimulated/beach/water/deep, /area/awaymission/beach) "dw" = ( @@ -1306,7 +1306,7 @@ }, /area/awaymission/beach) "dW" = ( -/obj/structure/ladder/dive_point/buoy{ +/obj/structure/ladder/unbreakable/dive_point/buoy{ id = "pirate" }, /turf/unsimulated/beach/water, diff --git a/_maps/map_files/RandomZLevels/example.dmm b/_maps/map_files/RandomZLevels/example.dmm index fd85d240c36..779a0bede34 100644 --- a/_maps/map_files/RandomZLevels/example.dmm +++ b/_maps/map_files/RandomZLevels/example.dmm @@ -261,7 +261,7 @@ /turf/simulated/floor/plasteel, /area/awaymission/example) "aH" = ( -/obj/structure/ladder{ +/obj/structure/ladder/unbreakable{ height = 1; id = "example" }, @@ -782,7 +782,7 @@ /turf/simulated/floor/plasteel, /area/awaymission/example) "ca" = ( -/obj/structure/ladder{ +/obj/structure/ladder/unbreakable{ id = "example" }, /turf/simulated/floor/plating, diff --git a/_maps/map_files/RandomZLevels/spacehotel.dmm b/_maps/map_files/RandomZLevels/spacehotel.dmm index 8394ca1b635..4b45711ff3d 100644 --- a/_maps/map_files/RandomZLevels/spacehotel.dmm +++ b/_maps/map_files/RandomZLevels/spacehotel.dmm @@ -540,7 +540,7 @@ requires_power = 0 }) "aZ" = ( -/obj/structure/ladder/dive_point/anchor{ +/obj/structure/ladder/unbreakable/dive_point/anchor{ id = "weirddive"; layer = 4.5 }, @@ -1996,7 +1996,7 @@ requires_power = 0 }) "dA" = ( -/obj/structure/ladder/dive_point/anchor{ +/obj/structure/ladder/unbreakable/dive_point/anchor{ layer = 4.5 }, /turf/unsimulated/beach/water/deep/wood_floor{ @@ -2721,8 +2721,8 @@ /turf/unsimulated/beach/water/drop, /area/awaymission/spacehotel) "fC" = ( -/obj/structure/ladder/dive_point/buoy, -/obj/structure/ladder/dive_point/buoy{ +/obj/structure/ladder/unbreakable/dive_point/buoy, +/obj/structure/ladder/unbreakable/dive_point/buoy{ id = "weirddive"; invisibility = 101 }, @@ -3465,7 +3465,7 @@ }, /area/awaymission/spacehotel) "hG" = ( -/obj/structure/ladder{ +/obj/structure/ladder/unbreakable{ height = 1; icon_state = "ladder10"; id = "service" @@ -3525,7 +3525,7 @@ /area/awaymission/spacehotel) "hN" = ( /obj/effect/decal/cleanable/blood/old, -/obj/structure/ladder{ +/obj/structure/ladder/unbreakable{ height = 2; icon_state = "ladder01"; id = "service" diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index ed6df3dfd53..7fdecb976a1 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -4055,7 +4055,7 @@ /turf/simulated/floor/plasteel, /area/security/armoury) "ahH" = ( -/obj/machinery/deployable/barrier, +/obj/item/grenade/barrier, /obj/structure/window/reinforced{ dir = 8 }, @@ -4155,7 +4155,7 @@ }, /area/security/brig) "ahR" = ( -/obj/machinery/deployable/barrier, +/obj/item/grenade/barrier, /obj/structure/window/reinforced{ dir = 4 }, @@ -4324,7 +4324,7 @@ }, /area/security/brig) "aif" = ( -/obj/machinery/deployable/barrier, +/obj/item/grenade/barrier, /obj/structure/window/reinforced{ dir = 8 }, @@ -4370,7 +4370,7 @@ }, /area/security/brig) "aij" = ( -/obj/machinery/deployable/barrier, +/obj/item/grenade/barrier, /obj/structure/window/reinforced{ dir = 4 }, @@ -79988,7 +79988,7 @@ "cMF" = ( /obj/machinery/door/airlock/engineering{ name = "Engineering Checkpoint"; - req_access_txt = "11" + req_one_access_txt = "11;24" }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 diff --git a/_maps/map_files/cyberiad/z2.dmm b/_maps/map_files/cyberiad/z2.dmm index 0052c80df84..7c7b0403547 100644 --- a/_maps/map_files/cyberiad/z2.dmm +++ b/_maps/map_files/cyberiad/z2.dmm @@ -8742,7 +8742,7 @@ pixel_x = -3; pixel_y = 3 }, -/obj/item/clothing/glasses/hud/health/health_advanced, +/obj/item/clothing/glasses/hud/health/sunglasses, /obj/item/clothing/glasses/hud/security/sunglasses, /turf/unsimulated/floor{ tag = "icon-floor"; diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index fbc28695ebf..d8e051e600e 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -106,9 +106,10 @@ #define SAWN_INTACT 0 #define SAWN_OFF 1 -#define WEAPON_LIGHT 0 -#define WEAPON_MEDIUM 1 -#define WEAPON_HEAVY 2 +#define WEAPON_DUAL_WIELD 0 +#define WEAPON_LIGHT 1 +#define WEAPON_MEDIUM 2 +#define WEAPON_HEAVY 3 #define EXPLODE_NONE 0 //Don't even ask me why we need this. #define EXPLODE_DEVASTATE 1 diff --git a/code/__DEFINES/crafting.dm b/code/__DEFINES/crafting.dm index 4b783490568..6acaea463f9 100644 --- a/code/__DEFINES/crafting.dm +++ b/code/__DEFINES/crafting.dm @@ -5,6 +5,7 @@ #define CAT_FOOD "Food" #define CAT_MISC "Misc" #define CAT_PRIMAL "Tribal" +#define CAT_CLOTHING "Clothing" #define RECIPE_MICROWAVE "Microwave" #define RECIPE_OVEN "Oven" diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm index 0fb9253a083..7213ecc3118 100644 --- a/code/__DEFINES/genetics.dm +++ b/code/__DEFINES/genetics.dm @@ -105,6 +105,9 @@ #define NUTRITION_LEVEL_STARVING 150 #define NUTRITION_LEVEL_CURSED 0 +//Used as an upper limit for species that continuously gain nutriment +#define NUTRITION_LEVEL_ALMOST_FULL 535 + //Blood levels #define BLOOD_VOLUME_MAXIMUM 2000 #define BLOOD_VOLUME_NORMAL 560 diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 1750a89d2df..4eb11963eff 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -487,10 +487,14 @@ // Cult summon possibilities #define SUMMON_POSSIBILITIES 3 +// Dice rigged options. #define DICE_NOT_RIGGED 1 #define DICE_BASICALLY_RIGGED 2 #define DICE_TOTALLY_RIGGED 3 +// Water temperature +#define COLD_WATER_TEMPERATURE 283.15 // 10 degrees celsius + // Parallax #define PARALLAX_DELAY_DEFAULT world.tick_lag #define PARALLAX_DELAY_MED 1 @@ -500,4 +504,4 @@ // Engine types #define ENGTYPE_SING "Singularity" #define ENGTYPE_SM "Supermatter" -#define ENGTYPE_TESLA "Tesla" \ No newline at end of file +#define ENGTYPE_TESLA "Tesla" diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index a28d68a392b..54fd59307f4 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -7,8 +7,9 @@ #define SOUND_BUZZ 64 #define SOUND_INSTRUMENTS 128 #define SOUND_MENTORHELP 256 +#define SOUND_DISCO 512 -#define SOUND_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|SOUND_HEARTBEAT|SOUND_BUZZ|SOUND_INSTRUMENTS|SOUND_MENTORHELP) +#define SOUND_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|SOUND_HEARTBEAT|SOUND_BUZZ|SOUND_INSTRUMENTS|SOUND_MENTORHELP|SOUND_DISCO) #define CHAT_OOC 1 #define CHAT_DEAD 2 @@ -34,7 +35,7 @@ #define AMBIENT_OCCLUSION 2097152 #define CHAT_GHOSTPDA 4194304 #define NUMPAD_TARGET 8388608 -#define TOGGLES_TOTAL 16777215 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined. +#define TOGGLES_TOTAL 16777215 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined. #define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_LOOC|MEMBER_PUBLIC|DONATOR_PUBLIC|AMBIENT_OCCLUSION|CHAT_GHOSTPDA|NUMPAD_TARGET) diff --git a/code/__DEFINES/stat.dm b/code/__DEFINES/stat.dm index 6ef269be1c2..b0a74b6c702 100644 --- a/code/__DEFINES/stat.dm +++ b/code/__DEFINES/stat.dm @@ -34,14 +34,14 @@ #define WAIT_FINISH 3 //shuttle mode defines -#define SHUTTLE_IDLE 0 -#define SHUTTLE_RECALL 1 -#define SHUTTLE_CALL 2 -#define SHUTTLE_DOCKED 3 -#define SHUTTLE_STRANDED 4 -#define SHUTTLE_ESCAPE 5 -#define SHUTTLE_ENDGAME 6 -#define SHUTTLE_IGNITING 7 +#define SHUTTLE_IGNITING 0 +#define SHUTTLE_IDLE 1 +#define SHUTTLE_RECALL 2 +#define SHUTTLE_CALL 3 +#define SHUTTLE_DOCKED 4 +#define SHUTTLE_STRANDED 5 +#define SHUTTLE_ESCAPE 6 +#define SHUTTLE_ENDGAME 7 // Shuttle return values #define SHUTTLE_CAN_DOCK "can_dock" diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index ed4f3242c4d..0b37872decd 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -948,10 +948,16 @@ The _flatIcons list is a cache for generated icon files. return "#[color]" //Imagine removing pixels from the main icon that are covered by pixels from the mask icon. -/proc/get_icon_difference(var/icon/main, var/icon/mask) +//Standard behaviour is to cut pixels from the main icon that are covered by pixels from the mask icon unless passed mask_ready, see below. +/proc/get_icon_difference(var/icon/main, var/icon/mask, var/mask_ready) + /*You should skip prep if the mask is already sprited properly. This significantly improves performance by eliminating most of the realtime icon work. + e.g. A 'ready' mask is a mask where the part you want cut out is missing (no pixels, 0 alpha) from the sprite, and everything else is solid white.*/ + if(istype(main) && istype(mask)) - mask.Blend(rgb(255,255,255), ICON_SUBTRACT) //Make all pixels on the mask as black as possible. - mask.Opaque(rgb(255,255,255)) //Make the transparent pixels (background) white. - mask.BecomeAlphaMask() //Make all the black pixels vanish (fully transparent), leaving only the white pixels. + if(!mask_ready) //Prep the mask if we're using a regular old sprite and not a special-made mask. + mask.Blend(rgb(255,255,255), ICON_SUBTRACT) //Make all pixels on the mask as black as possible. + mask.Opaque(rgb(255,255,255)) //Make the transparent pixels (background) white. + mask.BecomeAlphaMask() //Make all the black pixels vanish (fully transparent), leaving only the white background pixels. + main.AddAlphaMask(mask) //Make the pixels in the main icon that are in the transparent zone of the mask icon also vanish (fully transparent). - return main + return main \ No newline at end of file diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index d9d21c60e1e..ad3798a010e 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -42,6 +42,7 @@ GLOBAL_LIST_INIT(global_radios, list()) //list of all radios, across all z-le GLOBAL_LIST_INIT(meteor_list, list()) //list of all meteors GLOBAL_LIST_INIT(poi_list, list()) //list of points of interest for observe/follow GLOBAL_LIST_INIT(active_jammers, list()) // List of active radio jammers +GLOBAL_LIST_EMPTY(ladders) GLOBAL_LIST_INIT(active_diseases, list()) //List of Active disease in all mobs; purely for quick referencing. diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 4aa30657778..f9528f2b2b9 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -68,8 +68,14 @@ SUBSYSTEM_DEF(ticker) current_state = GAME_STATE_PREGAME fire() // TG says this is a good idea if(GAME_STATE_PREGAME) + if(!going) + return + // This is so we dont have sleeps in controllers, because that is a bad, bad thing - pregame_timeleft = max(0,round_start_time - world.time) + if(!delay_end) + pregame_timeleft = max(0,round_start_time - world.time) // Normal lobby countdown when roundstart was not delayed + else + pregame_timeleft = max(0,pregame_timeleft - 20) // If roundstart was delayed, we should resume the countdown where it left off if(pregame_timeleft <= 600 && !tipped) // 60 seconds send_tip_of_the_round() @@ -83,6 +89,7 @@ SUBSYSTEM_DEF(ticker) current_state = GAME_STATE_STARTUP Master.SetRunLevel(RUNLEVEL_LOBBY) if(GAME_STATE_PLAYING) + delay_end = 0 // reset this in case round start was delayed mode.process() mode.process_job_tasks() var/game_finished = SSshuttle.emergency.mode >= SHUTTLE_ENDGAME || mode.station_was_nuked diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 0ab0453cb95..3f4a0cb6b26 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1151,7 +1151,7 @@ A.set_zeroth_law("") A.show_laws() A.verbs -= /mob/living/silicon/ai/proc/choose_modules - A.malf_picker.remove_verbs(A) + A.malf_picker.remove_malf_verbs(A) qdel(A.malf_picker) SSticker.mode.update_traitor_icons_removed(src) diff --git a/code/datums/pipe_datums.dm b/code/datums/pipe_datums.dm index cf2ec79fe85..83b77425447 100644 --- a/code/datums/pipe_datums.dm +++ b/code/datums/pipe_datums.dm @@ -337,6 +337,13 @@ GLOBAL_LIST_EMPTY(rpd_pipe_list) //Some pipes we don't want to be dispensable pipe_icon = "intake" rpd_dispensable = TRUE +/datum/pipes/disposal/sortjunction + pipe_name = "disposals sort junction" + pipe_id = PIPE_DISPOSALS_SORT_RIGHT + orientations = 4 + pipe_icon = "pipe-j1s" + rpd_dispensable = TRUE + //Pipes the RPD can't dispense. Since these don't use an interface, we don't need to bother with setting an icon. We do, however, want to name these for other purposes /datum/pipes/atmospheric/circulator @@ -363,12 +370,8 @@ GLOBAL_LIST_EMPTY(rpd_pipe_list) //Some pipes we don't want to be dispensable pipe_name = "bent insulated pipe" pipe_id = PIPE_INSULATED_BENT -/datum/pipes/disposal/sortjunction - pipe_name = "disposals sort junction" - pipe_id = PIPE_DISPOSALS_SORT_RIGHT - pipe_icon = "pipe-j1s" - -/datum/pipes/disposal/sortjunction/left +/datum/pipes/disposal/left_sortjunction + pipe_name = "disposals sort junction left" pipe_id = PIPE_DISPOSALS_SORT_LEFT pipe_icon = "pipe-j2s" diff --git a/code/datums/spells/charge.dm b/code/datums/spells/charge.dm index 5dd054f67ed..46cdbff7f94 100644 --- a/code/datums/spells/charge.dm +++ b/code/datums/spells/charge.dm @@ -1,7 +1,6 @@ /obj/effect/proc_holder/spell/targeted/charge name = "Charge" desc = "This spell can be used to recharge a variety of things in your hands, from magical artifacts to electrical components. A creative wizard can even use it to grant magical power to a fellow magic user." - school = "transmutation" charge_max = 600 clothes_req = 0 @@ -10,7 +9,7 @@ range = -1 cooldown_min = 400 //50 deciseconds reduction per rank include_user = 1 - + action_icon_state = "charge" /obj/effect/proc_holder/spell/targeted/charge/cast(list/targets,mob/user = usr) for(var/mob/living/L in targets) diff --git a/code/datums/spells/infinite_guns.dm b/code/datums/spells/infinite_guns.dm index 83cafb88666..35699d4634a 100644 --- a/code/datums/spells/infinite_guns.dm +++ b/code/datums/spells/infinite_guns.dm @@ -11,8 +11,6 @@ cooldown_min = 10 //Gun wizard action_icon_state = "bolt_action" - - /obj/effect/proc_holder/spell/targeted/infinite_guns/cast(list/targets, mob/user = usr) for(var/mob/living/carbon/C in targets) C.drop_item() diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm index 7b648bb72c1..739a03d92c5 100644 --- a/code/datums/spells/wizard.dm +++ b/code/datums/spells/wizard.dm @@ -72,6 +72,7 @@ /obj/effect/proc_holder/spell/noclothes name = "No Clothes" desc = "This always-on spell allows you to cast magic without your garments." + action_icon_state = "no_clothes" /obj/effect/proc_holder/spell/targeted/genetic/mutate name = "Mutate" diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index fb336192b38..0573f3b90ca 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -45,13 +45,6 @@ duration = 10 tick_interval = 0 alert_type = /obj/screen/alert/status_effect/blooddrunk - var/last_health = 0 - var/last_bruteloss = 0 - var/last_fireloss = 0 - var/last_toxloss = 0 - var/last_oxyloss = 0 - var/last_cloneloss = 0 - var/last_staminaloss = 0 /obj/screen/alert/status_effect/blooddrunk name = "Blood-Drunk" @@ -61,108 +54,32 @@ /datum/status_effect/blooddrunk/on_apply() . = ..() if(.) - owner.maxHealth *= 10 - owner.bruteloss *= 10 - owner.fireloss *= 10 if(ishuman(owner)) var/mob/living/carbon/human/H = owner for(var/X in H.bodyparts) var/obj/item/organ/external/BP = X - BP.max_damage *= 10 - BP.min_broken_damage *= 10 - BP.brute_dam *= 10 - BP.burn_dam *= 10 - owner.toxloss *= 10 - owner.oxyloss *= 10 - owner.cloneloss *= 10 - owner.staminaloss *= 10 - owner.updatehealth() - last_health = owner.health - last_bruteloss = owner.getBruteLoss() - last_fireloss = owner.getFireLoss() - last_toxloss = owner.getToxLoss() - last_oxyloss = owner.getOxyLoss() - last_cloneloss = owner.getCloneLoss() - last_staminaloss = owner.getStaminaLoss() + BP.brute_mod *= 0.1 + BP.burn_mod *= 0.1 + H.dna.species.tox_mod *= 0.1 + H.dna.species.oxy_mod *= 0.1 + H.dna.species.clone_mod *= 0.1 + H.dna.species.stamina_mod *= 0.1 add_attack_logs(owner, owner, "gained blood-drunk stun immunity") var/status = CANSTUN | CANWEAKEN | CANPARALYSE | IGNORESLOWDOWN owner.status_flags &= ~status owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1) -/datum/status_effect/blooddrunk/tick() //multiply the effect of healing by 10 - if(owner.health > last_health) - var/needs_health_update = FALSE - var/new_bruteloss = owner.getBruteLoss() - if(new_bruteloss < last_bruteloss) - var/heal_amount = (new_bruteloss - last_bruteloss) * 10 - owner.adjustBruteLoss(heal_amount, updating_health = FALSE) - new_bruteloss = owner.getBruteLoss() - needs_health_update = TRUE - last_bruteloss = new_bruteloss - - var/new_fireloss = owner.getFireLoss() - if(new_fireloss < last_fireloss) - var/heal_amount = (new_fireloss - last_fireloss) * 10 - owner.adjustFireLoss(heal_amount, updating_health = FALSE) - new_fireloss = owner.getFireLoss() - needs_health_update = TRUE - last_fireloss = new_fireloss - - var/new_toxloss = owner.getToxLoss() - if(new_toxloss < last_toxloss) - var/heal_amount = (new_toxloss - last_toxloss) * 10 - owner.adjustToxLoss(heal_amount, updating_health = FALSE) - new_toxloss = owner.getToxLoss() - needs_health_update = TRUE - last_toxloss = new_toxloss - - var/new_oxyloss = owner.getOxyLoss() - if(new_oxyloss < last_oxyloss) - var/heal_amount = (new_oxyloss - last_oxyloss) * 10 - owner.adjustOxyLoss(heal_amount, updating_health = FALSE) - new_oxyloss = owner.getOxyLoss() - needs_health_update = TRUE - last_oxyloss = new_oxyloss - - var/new_cloneloss = owner.getCloneLoss() - if(new_cloneloss < last_cloneloss) - var/heal_amount = (new_cloneloss - last_cloneloss) * 10 - owner.adjustCloneLoss(heal_amount, updating_health = FALSE) - new_cloneloss = owner.getCloneLoss() - needs_health_update = TRUE - last_cloneloss = new_cloneloss - - var/new_staminaloss = owner.getStaminaLoss() - if(new_staminaloss < last_staminaloss) - var/heal_amount = (new_staminaloss - last_staminaloss) * 10 - owner.adjustStaminaLoss(heal_amount, updating_health = FALSE) - new_staminaloss = owner.getStaminaLoss() - needs_health_update = TRUE - last_staminaloss = new_staminaloss - - if(needs_health_update) - owner.updatehealth() - owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1) - last_health = owner.health - /datum/status_effect/blooddrunk/on_remove() - tick() - owner.maxHealth *= 0.1 - owner.bruteloss *= 0.1 - owner.fireloss *= 0.1 if(ishuman(owner)) var/mob/living/carbon/human/H = owner for(var/X in H.bodyparts) var/obj/item/organ/external/BP = X - BP.brute_dam *= 0.1 - BP.burn_dam *= 0.1 - BP.max_damage /= 10 - BP.min_broken_damage /= 10 - owner.toxloss *= 0.1 - owner.oxyloss *= 0.1 - owner.cloneloss *= 0.1 - owner.staminaloss *= 0.1 - owner.updatehealth() + BP.brute_mod *= 10 + BP.burn_mod *= 10 + H.dna.species.tox_mod *= 10 + H.dna.species.oxy_mod *= 10 + H.dna.species.clone_mod *= 10 + H.dna.species.stamina_mod *= 10 add_attack_logs(owner, owner, "lost blood-drunk stun immunity") owner.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | IGNORESLOWDOWN diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 9345387e304..494379aa821 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -482,10 +482,10 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine /datum/supply_packs/security/securitybarriers name = "Security Barriers Crate" - contains = list(/obj/machinery/deployable/barrier, - /obj/machinery/deployable/barrier, - /obj/machinery/deployable/barrier, - /obj/machinery/deployable/barrier) + contains = list(/obj/item/grenade/barrier, + /obj/item/grenade/barrier, + /obj/item/grenade/barrier, + /obj/item/grenade/barrier) cost = 20 containername = "security barriers crate" @@ -1173,6 +1173,7 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine /datum/supply_packs/organic/hydroponics/seeds name = "Seeds Crate" contains = list(/obj/item/seeds/chili, + /obj/item/seeds/cotton, /obj/item/seeds/berry, /obj/item/seeds/corn, /obj/item/seeds/eggplant, diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm index f90cfc94480..dfe28336631 100644 --- a/code/game/gamemodes/blob/powers.dm +++ b/code/game/gamemodes/blob/powers.dm @@ -234,14 +234,18 @@ blobber.color = blob_reagent_datum.complementary_color blobber.overmind = src blob_mobs.Add(blobber) + blobber.AIStatus = AI_OFF + blobber.LoseTarget() spawn() - var/list/candidates = pollCandidates("Do you want to play as a blobbernaut?", ROLE_BLOB, 1, 150) + var/list/candidates = pollCandidates("Do you want to play as a blobbernaut?", ROLE_BLOB, 1, 100) if(candidates.len) var/mob/C = pick(candidates) if(C) blobber.key = C.key to_chat(blobber, "You are a blobbernaut! You must assist all blob lifeforms in their mission to consume everything!") to_chat(blobber, "You heal while standing on blob structures, however you will decay slowly if you are damaged outside of the blob.") + if(!blobber.ckey) + blobber.AIStatus = AI_ON return diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 038f331f924..713779af241 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -303,7 +303,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" /datum/changeling/proc/can_absorb_dna(mob/living/carbon/user, mob/living/carbon/target) if(using_stale_dna(user))//If our current DNA is the stalest, we gotta ditch it. - to_chat(user, "We have reached our capacity to store genetic information! We must transform before absorbing more.") + to_chat(user, "The DNA we are wearing is stale. Transform and try again.") return if(!target || !target.dna) diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 8eeee9e4f2a..9a40cb58881 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -1,46 +1,243 @@ +//The malf AI action subtype. All malf actions are subtypes of this. +/datum/action/innate/ai + name = "AI Action" + desc = "You aren't entirely sure what this does, but it's very beepy and boopy." + background_icon_state = "bg_tech_blue" + var/mob/living/silicon/ai/owner_AI //The owner AI, so we don't have to typecast every time + var/uses //If we have multiple uses of the same power + var/auto_use_uses = TRUE //If we automatically use up uses on each activation + var/cooldown_period //If applicable, the time in deciseconds we have to wait before using any more modules + +/datum/action/innate/ai/Grant(mob/living/L) + . = ..() + if(!isAI(owner)) + WARNING("AI action [name] attempted to grant itself to non-AI mob [L.real_name] ([L.key])!") + qdel(src) + else + owner_AI = owner + +/datum/action/innate/ai/IsAvailable() + . = ..() + if(owner_AI && owner_AI.malf_cooldown > world.time) + return + +/datum/action/innate/ai/Trigger() + . = ..() + if(auto_use_uses) + adjust_uses(-1) + if(cooldown_period) + owner_AI.malf_cooldown = world.time + cooldown_period + +/datum/action/innate/ai/proc/adjust_uses(amt, silent) + uses += amt + if(!silent && uses) + to_chat(owner, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.") + if(!uses) + if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway! + to_chat(owner, "[name] has run out of uses!") + qdel(src) + +//Framework for ranged abilities that can have different effects by left-clicking stuff. +/datum/action/innate/ai/ranged + name = "Ranged AI Action" + auto_use_uses = FALSE //This is so we can do the thing and disable/enable freely without having to constantly add uses + var/obj/effect/proc_holder/ranged_ai/linked_ability //The linked proc holder that contains the actual ability code + var/linked_ability_type //The path of our linked ability + +/datum/action/innate/ai/ranged/New() + if(!linked_ability_type) + WARNING("Ranged AI action [name] attempted to spawn without a linked ability!") + qdel(src) //uh oh! + return + linked_ability = new linked_ability_type() + linked_ability.attached_action = src + ..() + +/datum/action/innate/ai/ranged/adjust_uses(amt, silent) + uses += amt + if(!silent && uses) + to_chat(owner, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.") + if(!uses) + if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway! + to_chat(owner, "[name] has run out of uses!") + Remove(owner) + QDEL_IN(src, 100) //let any active timers on us finish up + +/datum/action/innate/ai/ranged/Destroy() + QDEL_NULL(linked_ability) + return ..() + +/datum/action/innate/ai/ranged/Activate() + linked_ability.toggle(owner) + return TRUE + +//The actual ranged proc holder. +/obj/effect/proc_holder/ranged_ai + var/enable_text = "Hello World!" //Appears when the user activates the ability + var/disable_text = "Goodbye Cruel World!" //Context clues! + var/datum/action/innate/ai/ranged/attached_action + +/obj/effect/proc_holder/ranged_ai/Destroy() + QDEL_NULL(attached_action) + return ..() + +/obj/effect/proc_holder/ranged_ai/proc/toggle(mob/user) + if(active) + remove_ranged_ability(disable_text) + else + add_ranged_ability(user, enable_text) + +//The datum and interface for the malf unlock menu, which lets them choose actions to unlock. +/datum/module_picker + var/temp + var/processing_time = 50 + var/list/possible_modules + +/datum/module_picker/New() + possible_modules = list() + for(var/type in typesof(/datum/AI_Module)) + var/datum/AI_Module/AM = new type + if((AM.power_type && AM.power_type != /datum/action/innate/ai) || AM.upgrade) + possible_modules += AM + +/datum/module_picker/proc/remove_malf_verbs(mob/living/silicon/ai/AI) //Removes all malfunction-related abilities from the target AI. + for(var/datum/AI_Module/AM in possible_modules) + for(var/datum/action/A in AI.actions) + if(istype(A, initial(AM.power_type))) + qdel(A) + +/datum/module_picker/proc/use(user as mob) + var/dat + dat += {"Select use of processing time: (currently #[processing_time] left.)
+
+ Install Module:
+ The number afterwards is the amount of processing time it consumes.
"} + for(var/datum/AI_Module/large/module in possible_modules) + dat += "[module.module_name]\[?\] ([module.cost])
" + for(var/datum/AI_Module/small/module in possible_modules) + dat += "[module.module_name]\[?\] ([module.cost])
" + dat += "
" + if(temp) + dat += "[temp]" + var/datum/browser/popup = new(user, "modpicker", "Malf Module Menu", 400, 500) + popup.set_content(dat) + popup.open() + return + +/datum/module_picker/Topic(href, href_list) + ..() + + if(!isAI(usr)) + return + var/mob/living/silicon/ai/A = usr + + if(A.stat == DEAD) + to_chat(A, "You are already dead!") + return + + for(var/datum/AI_Module/AM in possible_modules) + if (href_list[AM.mod_pick_name]) + + // Cost check + if(AM.cost > processing_time) + temp = "You cannot afford this module." + break + + var/datum/action/innate/ai/action = locate(AM.power_type) in A.actions + + // Give the power and take away the money. + if(AM.upgrade) //upgrade and upgrade() are separate, be careful! + AM.upgrade(A) + possible_modules -= AM + to_chat(A, AM.unlock_text) + A.playsound_local(A, AM.unlock_sound, 50, 0) + else + if(AM.power_type) + if(!action) //Unlocking for the first time + var/datum/action/AC = new AM.power_type + AC.Grant(A) + A.current_modules += new AM.type + temp = AM.description + if(AM.one_purchase) + possible_modules -= AM + if(AM.unlock_text) + to_chat(A, AM.unlock_text) + if(AM.unlock_sound) + A.playsound_local(A, AM.unlock_sound, 50, 0) + else //Adding uses to an existing module + action.uses += initial(action.uses) + action.desc = "[initial(action.desc)] It has [action.uses] use\s remaining." + action.UpdateButtonIcon() + temp = "Additional use[action.uses > 1 ? "s" : ""] added to [action.name]!" + processing_time -= AM.cost + + if(href_list["showdesc"]) + if(AM.mod_pick_name == href_list["showdesc"]) + temp = AM.description + use(usr) + +//The base module type, which holds info about each ability. /datum/AI_Module - var/uses = 0 var/module_name var/mod_pick_name var/description = "" var/engaged = 0 var/cost = 5 - var/one_time = 0 + var/one_purchase = FALSE //If this module can only be purchased once. This always applies to upgrades, even if the variable is set to false. + var/power_type = /datum/action/innate/ai //If the module gives an active ability, use this. Mutually exclusive with upgrade. + var/upgrade //If the module gives a passive upgrade, use this. Mutually exclusive with power_type. + var/unlock_text = "Hello World!" //Text shown when an ability is unlocked + var/unlock_sound //Sound played when an ability is unlocked - var/power_type +/datum/AI_Module/proc/upgrade(mob/living/silicon/AI/AI) //Apply upgrades! + return -/datum/AI_Module/large/ - uses = 1 - -/datum/AI_Module/small/ - uses = 5 +/datum/AI_Module/large //Big, powerful stuff that can only be used once. +/datum/AI_Module/small //Weak, usually localized stuff with multiple uses. +//Doomsday Device: Starts the self-destruct timer. It can only be stopped by killing the AI completely. /datum/AI_Module/large/nuke_station module_name = "Doomsday Device" mod_pick_name = "nukestation" - description = "Activate a weapon that will disintegrate all organic life on the station after a 450 second delay." + description = "Activate a weapon that will disintegrate all organic life on the station after a 450 second delay. Can only be used while on the station, will fail if your core is moved off station or destroyed." cost = 130 - one_time = 1 + one_purchase = TRUE + power_type = /datum/action/innate/ai/nuke_station + unlock_text = "You slowly, carefully, establish a connection with the on-station self-destruct. You can now activate it at any time." + unlock_sound = 'sound/items/timer.ogg' - power_type = /mob/living/silicon/ai/proc/nuke_station +/datum/action/innate/ai/nuke_station + name = "Doomsday Device" + desc = "Activates the doomsday device. This is not reversible." + button_icon_state = "doomsday_device" + auto_use_uses = FALSE -/mob/living/silicon/ai/proc/nuke_station() - set category = "Malfunction" - set name = "Doomsday Device" +/datum/action/innate/ai/nuke_station/Activate() + var/turf/T = get_turf(owner) + if(!istype(T) || !is_station_level(T.z)) + to_chat(owner, "You cannot activate the doomsday device while off-station!") + return + if(alert(owner, "Send arming signal? (true = arm, false = cancel)", "purge_all_life()", "confirm = TRUE;", "confirm = FALSE;") != "confirm = TRUE;") + return + if(active) + return //prevent the AI from activating an already active doomsday + active = TRUE + set_us_up_the_bomb() - to_chat(src, "Nuclear device armed.") +/datum/action/innate/ai/nuke_station/proc/set_us_up_the_bomb() + to_chat(owner_AI, "Nuclear device armed.") event_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", new_sound = 'sound/AI/aimalf.ogg') set_security_level("delta") - nuking = 1 - var/obj/machinery/doomsday_device/DOOM = new /obj/machinery/doomsday_device(src) - doomsday_device = DOOM - doomsday_device.start() - verbs -= /mob/living/silicon/ai/proc/nuke_station + owner_AI.nuking = TRUE + var/obj/machinery/doomsday_device/DOOM = new /obj/machinery/doomsday_device(owner_AI) + owner_AI.doomsday_device = DOOM + owner_AI.doomsday_device.start() for(var/obj/item/pinpointer/point in GLOB.pinpointer_list) for(var/mob/living/silicon/ai/A in ai_list) if((A.stat != DEAD) && A.nuking) point.the_disk = A //The pinpointer now tracks the AI core + qdel(src) /obj/machinery/doomsday_device icon = 'icons/obj/machines/nuke_terminal.dmi' @@ -113,49 +310,42 @@ to_chat(world, "The AI cleansed the station of life with the doomsday device!") SSticker.force_ending = 1 - +//AI Turret Upgrade: Increases the health and damage of all turrets. /datum/AI_Module/large/upgrade_turrets module_name = "AI Turret Upgrade" mod_pick_name = "turret" description = "Improves the power and health of all AI turrets. This effect is permanent." cost = 30 - one_time = 1 + upgrade = TRUE + unlock_text = "You establish a power diversion to your turrets, upgrading their health and damage." + unlock_sound = 'sound/items/rped.ogg' - power_type = /mob/living/silicon/ai/proc/upgrade_turrets - -/mob/living/silicon/ai/proc/upgrade_turrets() - set category = "Malfunction" - set name = "Upgrade Turrets" - - if(stat) - return - - src.verbs -= /mob/living/silicon/ai/proc/upgrade_turrets +/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/AI/AI) for(var/obj/machinery/porta_turret/turret in GLOB.machines) var/turf/T = get_turf(turret) if(is_station_level(T.z)) turret.health += 30 turret.eprojectile = /obj/item/projectile/beam/laser/heavylaser //Once you see it, you will know what it means to FEAR. turret.eshot_sound = 'sound/weapons/lasercannonfire.ogg' - to_chat(src, "Turrets upgraded.") - +//Hostile Station Lockdown: Locks, bolts, and electrifies every airlock on the station. After 90 seconds, the doors reset. /datum/AI_Module/large/lockdown module_name = "Hostile Station Lockdown" mod_pick_name = "lockdown" - description = "Overload the airlock, blast door and fire control networks, locking them down. Caution! This command also electrifies all airlocks. The networks will automatically reset after 90 seconds." + description = "Overload the airlock, blast door and fire control networks, locking them down. Caution! This command also electrifies all airlocks. The networks will automatically reset after 90 seconds, briefly \ + opening all doors on the station." cost = 30 - one_time = 1 + one_purchase = TRUE + power_type = /datum/action/innate/ai/lockdown + unlock_text = "You upload a sleeper trojan into the door control systems. You can send a signal to set it off at any time." - power_type = /mob/living/silicon/ai/proc/lockdown - -/mob/living/silicon/ai/proc/lockdown() - set category = "Malfunction" - set name = "Initiate Hostile Lockdown" - - if(stat) - return +/datum/action/innate/ai/lockdown + name = "Lockdown" + desc = "Closes, bolts, and depowers every airlock, firelock, and blast door on the station. After 90 seconds, they will reset themselves." + button_icon_state = "lockdown" + uses = 1 +/datum/action/innate/ai/lockdown/Activate() for(var/obj/machinery/door/D in GLOB.airlocks) if(!is_station_level(D.z)) continue @@ -164,342 +354,360 @@ post_status("alert", "lockdown") - verbs -= /mob/living/silicon/ai/proc/lockdown minor_announcement.Announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.", "Network Alert") - to_chat(src, "Lockdown Initiated. Network reset in 90 seconds.") + to_chat(owner, "Lockdown Initiated. Network reset in 90 seconds.") spawn(900) minor_announcement.Announce("Automatic system reboot complete. Have a secure day.","Network reset:") - +//Destroy RCDs: Detonates all non-cyborg RCDs on the station. /datum/AI_Module/large/destroy_rcd module_name = "Destroy RCDs" mod_pick_name = "rcd" description = "Send a specialised pulse to detonate all hand-held and exosuit Rapid Construction Devices on the station." cost = 25 - one_time = 1 + one_purchase = TRUE + power_type = /datum/action/innate/ai/destroy_rcds + unlock_text = "After some improvisation, you rig your onboard radio to be able to send a signal to detonate all RCDs." - power_type = /mob/living/silicon/ai/proc/disable_rcd - -/mob/living/silicon/ai/proc/disable_rcd() - set category = "Malfunction" - set name = "Destroy RCDs" - set desc = "Detonate all RCDs on the station, while sparing onboard cyborg RCDs." - - if(stat || malf_cooldown > world.time) - return +/datum/action/innate/ai/destroy_rcds + name = "Destroy RCDs" + desc = "Detonate all non-cyborg RCDs on the station." + button_icon_state = "detonate_rcds" + uses = 1 + cooldown_period = 100 +/datum/action/innate/ai/destroy_rcds/Activate() for(var/obj/item/rcd/RCD in GLOB.rcd_list) if(!istype(RCD, /obj/item/rcd/borg)) //Ensures that cyborg RCDs are spared. RCD.detonate_pulse() - to_chat(src, "RCD detonation pulse emitted.") - malf_cooldown = world.time + 100 - + to_chat(owner, "RCD detonation pulse emitted.") + owner.playsound_local(owner, 'sound/machines/twobeep.ogg', 50, 0) +//Unlock Mech Domination: Unlocks the ability to dominate mechs. Big shocker, right? /datum/AI_Module/large/mecha_domination - module_name = "Viral Mech Domination" + module_name = "Unlock Mech Domination" mod_pick_name = "mechjack" - description = "Hack into a mech's onboard computer, shunting all processes into it and ejecting any occupants. Once uploaded to the mech, it is impossible to leave. \ + description = "Allows you to hack into a mech's onboard computer, shunting all processes into it and ejecting any occupants. Once uploaded to the mech, it is impossible to leave.\ Do not allow the mech to leave the station's vicinity or allow it to be destroyed." cost = 30 - one_time = 1 - - power_type = /mob/living/silicon/ai/proc/mech_takeover - -/mob/living/silicon/ai/proc/mech_takeover() - set name = "Compile Mecha Virus" - set category = "Malfunction" - set desc = "Target a mech by clicking it. Click the appropriate command when ready." - - if(stat) - return - - can_dominate_mechs = 1 //Yep. This is all it does. Honk! - to_chat(src, "Virus package compiled. Select a target mech at any time. You must remain on the station at all times. Loss of signal will result in total system lockout.") - - verbs -= /mob/living/silicon/ai/proc/mech_takeover + upgrade = TRUE + unlock_text = "Virus package compiled. Select a target mech at any time. You must remain on the station at all times. Loss of signal will result in total system lockout." + unlock_sound = 'sound/mecha/nominal.ogg' +/datum/AI_Module/large/mecha_domination/upgrade(mob/living/silicon/ai/AI) + AI.can_dominate_mechs = TRUE //Yep. This is all it does. Honk! +//Thermal Sensor Override: Unlocks the ability to disable all fire alarms from doing their job. /datum/AI_Module/large/break_fire_alarms module_name = "Thermal Sensor Override" mod_pick_name = "burnpigs" description = "Gives you the ability to override the thermal sensors on all fire alarms. This will remove their ability to scan for fire and thus their ability to alert. \ Anyone can check the fire alarm's interface and may be tipped off by its status." - one_time = 1 + one_purchase = TRUE cost = 25 + power_type = /datum/action/innate/ai/break_fire_alarms + unlock_text = "You replace the thermal sensing capabilities of all fire alarms with a manual override, allowing you to turn them off at will." - power_type = /mob/living/silicon/ai/proc/break_fire_alarms - -/mob/living/silicon/ai/proc/break_fire_alarms() - set name = "Override Thermal Sensors" - set category = "Malfunction" - - if(stat) - return +/datum/action/innate/ai/break_fire_alarms + name = "Override Thermal Sensors" + desc = "Disables the automatic temperature sensing on all fire alarms, making them effectively useless." + button_icon_state = "break_fire_alarms" + uses = 1 +/datum/action/innate/ai/break_fire_alarms/Activate() for(var/obj/machinery/firealarm/F in GLOB.machines) if(!is_station_level(F.z)) continue - F.emagged = 1 - to_chat(src, "All thermal sensors on the station have been disabled. Fire alerts will no longer be recognized.") - verbs -= /mob/living/silicon/ai/proc/break_fire_alarms - + F.emagged = TRUE + to_chat(owner, "All thermal sensors on the station have been disabled. Fire alerts will no longer be recognized.") + owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, 0) +//Air Alarm Safety Override: Unlocks the ability to enable flooding on all air alarms. /datum/AI_Module/large/break_air_alarms module_name = "Air Alarm Safety Override" mod_pick_name = "allow_flooding" description = "Gives you the ability to disable safeties on all air alarms. This will allow you to use the environmental mode Flood, which disables scrubbers as well as pressure checks on vents. \ Anyone can check the air alarm's interface and may be tipped off by their nonfunctionality." - one_time = 1 + one_purchase = TRUE cost = 50 + power_type = /datum/action/innate/ai/break_air_alarms + unlock_text = "You remove the safety overrides on all air alarms, but you leave the confirm prompts open. You can hit 'Yes' at any time... you bastard." - power_type = /mob/living/silicon/ai/proc/break_air_alarms - -/mob/living/silicon/ai/proc/break_air_alarms() - set name = "Disable Air Alarm Safeties" - set category = "Malfunction" - - if(stat) - return +/datum/action/innate/ai/break_air_alarms + name = "Override Air Alarm Safeties" + desc = "Enables the Flood setting on all air alarms." + button_icon_state = "break_air_alarms" + uses = 1 +/datum/action/innate/ai/break_air_alarms/Activate() for(var/obj/machinery/alarm/AA in GLOB.machines) if(!is_station_level(AA.z)) continue - AA.emagged = 1 - to_chat(src, "All air alarm safeties on the station have been overriden. Air alarms may now use the Flood environmental mode.") - verbs -= /mob/living/silicon/ai/proc/break_air_alarms - + AA.emagged = TRUE + to_chat(owner, "All air alarm safeties on the station have been overriden. Air alarms may now use the Flood environmental mode.") + owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, 0) +//Overload Machine: Allows the AI to overload a machine, detonating it after a delay. Two uses per purchase. /datum/AI_Module/small/overload_machine module_name = "Machine Overload" mod_pick_name = "overload" - description = "Overloads an electrical machine, causing a small explosion. 2 uses." - uses = 2 + description = "Overheats an electrical machine, causing a small explosion and destroying it. Two uses per purchase." cost = 20 + power_type = /datum/action/innate/ai/overload_machine + unlock_text = "You enable the ability for the station's APCs to direct intense energy into machinery." - power_type = /mob/living/silicon/ai/proc/overload_machine +/datum/action/innate/ai/overload_machine + name = "Overload Machine" + desc = "Overheats a machine, causing a small explosion after a short time." + button_icon_state = "overload_machine" + uses = 2 + auto_use_uses = FALSE -/mob/living/silicon/ai/proc/overload_machine(obj/machinery/M in GLOB.machines) - set name = "Overload Machine" - set category = "Malfunction" +/datum/action/innate/ai/overload_machine/New() + ..() + desc = "[desc] It has [uses] use\s remaining." + button.desc = desc - if(stat) +/datum/action/innate/ai/overload_machine/Activate() + var/select = input("Choose a device to overload", "Overload Machine", null, null) as null|anything in GLOB.machines + if(!select) return + var/obj/machinery/M = select if(istype(M, /obj/machinery)) - for(var/datum/AI_Module/small/overload_machine/overload in current_modules) - if(overload.uses > 0) - overload.uses -- - audible_message("You hear a loud electrical buzzing sound!") - to_chat(src, "Overloading machine circuitry...") - spawn(50) - if(M) - explosion(get_turf(M), 0,1,1,0) - qdel(M) - else - to_chat(src, "Out of uses.") + if(uses > 0) + adjust_uses(-1) + if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe + desc = "[initial(desc)] It has [uses] use\s remaining." + UpdateButtonIcon() + M.audible_message("You hear a loud electrical buzzing sound!") + to_chat(owner, "Overloading machine circuitry...") + spawn(50) + if(M) + explosion(get_turf(M), 0,1,1,0) + qdel(M) + else + to_chat(owner, "Out of uses.") else - to_chat(src, "That's not a machine.") - + to_chat(owner, "That's not a machine.") + return +//Override Machine: Allows the AI to override a machine, animating it into an angry, living version of itself. /datum/AI_Module/small/override_machine module_name = "Machine Override" mod_pick_name = "override" - description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. 4 uses." - uses = 4 + description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. Four uses." cost = 30 + power_type = /datum/action/innate/ai/override_machine + unlock_text = "You procure a virus from the Space Dark Web and prepare to distribute it to the station's machines." - power_type = /mob/living/silicon/ai/proc/override_machine +/datum/action/innate/ai/override_machine + name = "Override Machine" + desc = "Animates a targeted machine, causing it to attack anyone nearby." + button_icon_state = "override_machine" + uses = 4 + auto_use_uses = FALSE +/datum/action/innate/ai/override_machine/New() + ..() + desc = "[desc] It has [uses] use\s remaining." + button.desc = desc -/mob/living/silicon/ai/proc/override_machine(obj/machinery/M in GLOB.machines) - set name = "Override Machine" - set category = "Malfunction" - - if(stat) +/datum/action/innate/ai/override_machine/Activate() + var/select = input("Choose a device to override", "Override Machine", null, null) as null|anything in GLOB.machines + if(!select) return - if (istype(M, /obj/machinery)) + var/obj/machinery/M = select + if(istype(M, /obj/machinery)) if(!M.can_be_overridden()) - to_chat(src, "Can't override this device.") - for(var/datum/AI_Module/small/override_machine/override in current_modules) - if(override.uses > 0) - override.uses -- - audible_message("You hear a loud electrical buzzing sound!") - to_chat(src, "Reprogramming machine behaviour...") - spawn(50) - if(M && !QDELETED(M)) - new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, src, 1) - else - to_chat(src, "Out of uses.") + to_chat(owner, "Can't override this device.") + return + else if(uses > 0) + adjust_uses(-1) + if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe + desc = "[initial(desc)] It has [uses] use\s remaining." + UpdateButtonIcon() + M.audible_message("You hear a loud electrical buzzing sound!") + to_chat(owner, "Reprogramming machine behaviour...") + spawn(50) + if(M && !QDELETED(M)) + new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, src, 1) + else + to_chat(owner, "Out of uses.") else - to_chat(src, "That's not a machine.") - + to_chat(owner, "That's not a machine.") + return +//Robotic Factory: Places a large machine that converts humans that go through it into cyborgs. Unlocking this ability removes shunting. /datum/AI_Module/large/place_cyborg_transformer module_name = "Robotic Factory (Removes Shunting)" mod_pick_name = "cyborgtransformer" description = "Build a machine anywhere, using expensive nanomachines, that can convert a living human into a loyal cyborg slave when placed inside." cost = 100 - power_type = /mob/living/silicon/ai/proc/place_transformer - var/list/turfOverlays = list() + one_purchase = TRUE + power_type = /datum/action/innate/ai/place_transformer + unlock_text = "You prepare a robotics factory for deployment." + unlock_sound = 'sound/machines/ping.ogg' -/datum/AI_Module/large/place_cyborg_transformer/New() - for(var/i=0;i<3;i++) - var/image/I = image("icon"='icons/turf/overlays.dmi') - turfOverlays += I +/datum/action/innate/ai/place_transformer + name = "Place Robotics Factory" + desc = "Places a machine that converts humans into cyborgs. Conveyor belts included!" + button_icon_state = "robotic_factory" + uses = 1 + auto_use_uses = FALSE //So we can attempt multiple times + var/list/turfOverlays + +/datum/action/innate/ai/place_transformer/New() ..() + for(var/i in 1 to 3) + var/image/I = image("icon"='icons/turf/overlays.dmi') + LAZYADD(turfOverlays, I) -/mob/living/silicon/ai/proc/place_transformer() - set name = "Place Robotic Factory" - set category = "Malfunction" - - if(!canPlaceTransformer()) +/datum/action/innate/ai/place_transformer/Activate() + if(!owner_AI.can_place_transformer(src)) return - - var/sure = alert(src, "Are you sure you want to place the machine here?", "Are you sure?", "Yes", "No") - if(sure == "Yes") - if(!canPlaceTransformer()) - return - var/turf/T = get_turf(eyeobj) - new /obj/machinery/transformer/conveyor(T) - playsound(T, 'sound/effects/phasein.ogg', 100, 1) - var/datum/AI_Module/large/place_cyborg_transformer/PCT = locate() in current_modules - PCT.uses -- - can_shunt = 0 - to_chat(src, "You cannot shunt anymore.") - -/mob/living/silicon/ai/proc/canPlaceTransformer() - if(!eyeobj || !isturf(src.loc)) + active = TRUE + if(alert(owner, "Are you sure you want to place the machine here?", "Are you sure?", "Yes", "No") == "No") + active = FALSE return - var/datum/AI_Module/large/place_cyborg_transformer/PCT = locate() in current_modules - if(!PCT || PCT.uses < 1) - alert(src, "Out of uses.") + if(!owner_AI.can_place_transformer(src)) + active = FALSE + return + var/turf/T = get_turf(owner_AI.eyeobj) + new /obj/machinery/transformer/conveyor(T) + playsound(T, 'sound/effects/phasein.ogg', 100, 1) + owner_AI.can_shunt = FALSE + to_chat(owner, "You are no longer able to shunt your core to APCs.") + adjust_uses(-1) + +/mob/living/silicon/ai/proc/remove_transformer_image(client/C, image/I, turf/T) + if(C && I.loc == T) + C.images -= I + +/mob/living/silicon/ai/proc/can_place_transformer(datum/action/innate/ai/place_transformer/action) + if(!eyeobj || !isturf(loc) || incapacitated() || !action) return var/turf/middle = get_turf(eyeobj) var/list/turfs = list(middle, locate(middle.x - 1, middle.y, middle.z), locate(middle.x + 1, middle.y, middle.z)) - var/alert_msg = "There isn't enough room. Make sure you are placing the machine in a clear area and on a floor." - var/success = 1 - if(turfs.len == 3) - for(var/n=1;n<4,n++) - var/fail - var/turf/T = turfs[n] - if(!istype(T, /turf/simulated/floor)) - fail = 1 - var/datum/camerachunk/C = cameranet.getCameraChunk(T.x, T.y, T.z) - if(!C.visibleTurfs[T]) - alert_msg = "We cannot get camera vision of this location." - fail = 1 - for(var/atom/movable/AM in T.contents) - if(AM.density) - fail = 1 - var/image/I = PCT.turfOverlays[n] - I.loc = T - client.images += I - if(fail) - success = 0 - I.icon_state = "redOverlay" - else - I.icon_state = "greenOverlay" - spawn(30) - if(client && (I.loc == T)) - client.images -= I - if(success) - return 1 - alert(src, alert_msg) - + var/alert_msg = "There isn't enough room! Make sure you are placing the machine in a clear area and on a floor." + var/success = TRUE + for(var/n in 1 to 3) //We have to do this instead of iterating normally because of how overlay images are handled + var/turf/T = turfs[n] + if(!isfloorturf(T)) + success = FALSE + var/datum/camerachunk/C = cameranet.getCameraChunk(T.x, T.y, T.z) + if(!C.visibleTurfs[T]) + alert_msg = "You don't have camera vision of this location!" + success = FALSE + for(var/atom/movable/AM in T.contents) + if(AM.density) + alert_msg = "That area must be clear of objects!" + success = FALSE + var/image/I = action.turfOverlays[n] + I.loc = T + client.images += I + I.icon_state = "[success ? "green" : "red"]Overlay" //greenOverlay and redOverlay for success and failure respectively + addtimer(CALLBACK(src, .proc/remove_transformer_image, client, I, T), 30) + if(!success) + to_chat(src, "[alert_msg]") + return success +//Blackout: Overloads a random number of lights across the station. Three uses. /datum/AI_Module/small/blackout module_name = "Blackout" mod_pick_name = "blackout" - description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. 3 uses." - uses = 3 + description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. Three uses." cost = 15 + power_type = /datum/action/innate/ai/blackout + unlock_text = "You hook into the powernet and route bonus power towards the station's lighting." - power_type = /mob/living/silicon/ai/proc/blackout +/datum/action/innate/ai/blackout + name = "Blackout" + desc = "Overloads random lights across the station." + button_icon_state = "blackout" + uses = 3 + auto_use_uses = FALSE -/mob/living/silicon/ai/proc/blackout() - set category = "Malfunction" - set name = "Blackout" +/datum/action/innate/ai/blackout/New() + ..() + desc = "[desc] It has [uses] use\s remaining." + button.desc = desc - if(stat) - return - - for(var/datum/AI_Module/small/blackout/blackout in current_modules) - if(blackout.uses > 0) - blackout.uses -- - for(var/obj/machinery/power/apc/apc in GLOB.apcs) - if(prob(30*apc.overload)) - apc.overload_lighting() - else - apc.overload++ - to_chat(src, "Overcurrent applied to the powernet.") +/datum/action/innate/ai/blackout/Activate() + for(var/obj/machinery/power/apc/apc in GLOB.apcs) + if(prob(30 * apc.overload)) + apc.overload_lighting() else - to_chat(src, "Out of uses.") - + apc.overload++ + to_chat(owner, "Overcurrent applied to the powernet.") + owner.playsound_local(owner, "sparks", 50, 0) + adjust_uses(-1) + if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe + desc = "[initial(desc)] It has [uses] use\s remaining." + UpdateButtonIcon() +//Reactivate Camera Network: Reactivates up to 30 cameras across the station. /datum/AI_Module/small/reactivate_cameras module_name = "Reactivate Camera Network" mod_pick_name = "recam" description = "Runs a network-wide diagnostic on the camera network, resetting focus and re-routing power to failed cameras. Can be used to repair up to 30 cameras." - uses = 30 cost = 10 - one_time = 1 + one_purchase = TRUE + power_type = /datum/action/innate/ai/reactivate_cameras + unlock_text = "You deploy nanomachines to the cameranet." - power_type = /mob/living/silicon/ai/proc/reactivate_cameras +/datum/action/innate/ai/reactivate_cameras + name = "Reactivate Cameras" + desc = "Reactivates disabled cameras across the station; remaining uses can be used later." + button_icon_state = "reactivate_cameras" + uses = 30 + auto_use_uses = FALSE + cooldown_period = 30 -/mob/living/silicon/ai/proc/reactivate_cameras() - set name = "Reactivate Cameranet" - set category = "Malfunction" - - if(stat || malf_cooldown > world.time) - return - var/fixedcams = 0 //Tells the AI how many cams it fixed. Stats are fun. - - for(var/datum/AI_Module/small/reactivate_cameras/camera in current_modules) - for(var/obj/machinery/camera/C in cameranet.cameras) - var/initial_range = initial(C.view_range) //To prevent calling the proc twice - if(camera.uses > 0) - if(!C.status) - C.toggle_cam(src, 1) //Reactivates the camera based on status. Badly named proc. - fixedcams++ - camera.uses-- - if(C.view_range != initial_range) - C.view_range = initial_range //Fixes cameras with bad focus. - camera.uses-- - fixedcams++ - //If a camera is both deactivated and has bad focus, it will cost two uses to fully fix! - else - to_chat(src, "Out of uses.") - verbs -= /mob/living/silicon/ai/proc/reactivate_cameras //It is useless now, clean it up. - break - to_chat(src, "Diagnostic complete! Operations completed: [fixedcams].") - - malf_cooldown = world.time + 30 +/datum/action/innate/ai/reactivate_cameras/New() + ..() + desc = "[desc] It has [uses] use\s remaining." + button.desc = desc +/datum/action/innate/ai/reactivate_cameras/Activate() + var/fixed_cameras = 0 + for(var/V in cameranet.cameras) + if(!uses) + break + var/obj/machinery/camera/C = V + if(!C.status || C.view_range != initial(C.view_range)) + C.toggle_cam(owner_AI, 0) //Reactivates the camera based on status. Badly named proc. + C.view_range = initial(C.view_range) + fixed_cameras++ + uses-- //Not adjust_uses() so it doesn't automatically delete or show a message + to_chat(owner, "Diagnostic complete! Cameras reactivated: [fixed_cameras]. Reactivations remaining: [uses].") + owner.playsound_local(owner, 'sound/items/wirecutter.ogg', 50, 0) + adjust_uses(0, TRUE) //Checks the uses remaining + if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe + desc = "[initial(desc)] It has [uses] use\s remaining." + UpdateButtonIcon() +//Upgrade Camera Network: EMP-proofs all cameras, in addition to giving them X-ray vision. /datum/AI_Module/large/upgrade_cameras module_name = "Upgrade Camera Network" mod_pick_name = "upgradecam" - description = "Install broad-spectrum scanning and electrical redundancy firmware to the camera network, enabling EMP-Proofing and light-amplified X-ray vision." //I <3 pointless technobabble + description = "Install broad-spectrum scanning and electrical redundancy firmware to the camera network, enabling EMP-proofing and light-amplified X-ray vision." //I <3 pointless technobabble //This used to have motion sensing as well, but testing quickly revealed that giving it to the whole cameranet is PURE HORROR. - one_time = 1 + one_purchase = TRUE cost = 35 //Decent price for omniscience! + upgrade = TRUE + unlock_text = "OTA firmware distribution complete! Cameras upgraded: CAMSUPGRADED. Light amplification system online." + unlock_sound = 'sound/items/rped.ogg' - power_type = /mob/living/silicon/ai/proc/upgrade_cameras +/datum/AI_Module/large/upgrade_cameras/upgrade(mob/living/silicon/ai/AI) + AI.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE //Night-vision, without which X-ray would be very limited in power. + AI.update_sight() + var/upgraded_cameras = 0 -/mob/living/silicon/ai/proc/upgrade_cameras() - set name = "Upgrade Cameranet" - set category = "Malfunction" - - if(stat) - return - - var/upgradedcams = 0 - RegisterSignal(src, COMSIG_MOB_UPDATE_SIGHT, .proc/update_upgraded_cameras_sight) //Makes sure the AI has night vision, without which X-ray would be very limited in power. - update_sight() - - for(var/obj/machinery/camera/C in cameranet.cameras) + for(var/V in cameranet.cameras) + var/obj/machinery/camera/C = V if(C.assembly) var/upgraded = FALSE @@ -514,107 +722,21 @@ upgraded = TRUE if(upgraded) - upgradedcams++ + upgraded_cameras++ - to_chat(src, "OTA firmware distribution complete! Cameras upgraded: [upgradedcams]. Light amplification system online.") - verbs -= /mob/living/silicon/ai/proc/upgrade_cameras - -/mob/living/silicon/ai/proc/update_upgraded_cameras_sight() - lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE + unlock_text = replacetext(unlock_text, "CAMSUPGRADED", "[upgraded_cameras]") //This works, since unlock text is called after upgrade() /datum/AI_Module/large/eavesdrop module_name = "Enhanced Surveillance" mod_pick_name = "eavesdrop" description = "Via a combination of hidden microphones and lip reading software, you are able to use your cameras to listen in on conversations." cost = 30 - one_time = 1 + one_purchase = TRUE + upgrade = TRUE + unlock_text = "OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online." + unlock_sound = 'sound/items/rped.ogg' - power_type = /mob/living/silicon/ai/proc/surveillance +/datum/AI_Module/large/eavesdrop/upgrade(mob/living/silicon/ai/AI) + if(AI.eyeobj) + AI.eyeobj.relay_speech = TRUE -/mob/living/silicon/ai/proc/surveillance() - set category = "Malfunction" - set name = "Enhanced Surveillance" - - if(eyeobj) - eyeobj.relay_speech = 1 - to_chat(src, "OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online.") - verbs -= /mob/living/silicon/ai/proc/surveillance - - -/datum/module_picker - var/temp = null - var/processing_time = 50 - var/list/possible_modules = list() - -/datum/module_picker/New() - for(var/type in subtypesof(/datum/AI_Module)) - var/datum/AI_Module/AM = new type - if(AM.power_type != null) - src.possible_modules += AM - -/datum/module_picker/proc/remove_verbs(var/mob/living/silicon/ai/A) - - for(var/datum/AI_Module/AM in possible_modules) - A.verbs.Remove(AM.power_type) - - -/datum/module_picker/proc/use(user as mob) - var/dat - dat += {"Select use of processing time: (currently #[src.processing_time] left.)
-
- Install Module:
- The number afterwards is the amount of processing time it consumes.
"} - for(var/datum/AI_Module/large/module in src.possible_modules) - dat += "[module.module_name]\[?\] ([module.cost])
" - for(var/datum/AI_Module/small/module in src.possible_modules) - dat += "[module.module_name]\[?\] ([module.cost])
" - dat += "
" - if(src.temp) - dat += "[src.temp]" - var/datum/browser/popup = new(user, "modpicker", "Malf Module Menu") - popup.set_content(dat) - popup.open() - return - -/datum/module_picker/Topic(href, href_list) - ..() - - if(!isAI(usr)) - return - var/mob/living/silicon/ai/A = usr - - if(A.stat == DEAD) - to_chat(A, "You are already dead!") //Omae Wa Mou Shindeiru - return - - for(var/datum/AI_Module/AM in possible_modules) - if(href_list[AM.mod_pick_name]) - - // Cost check - if(AM.cost > src.processing_time) - temp = "You cannot afford this module." - break - - // Add new uses if we can, and it is allowed. - var/datum/AI_Module/already_AM = locate(AM.type) in A.current_modules - if(already_AM) - if(!AM.one_time) - already_AM.uses += AM.uses - src.processing_time -= AM.cost - temp = "Additional use added to [already_AM.module_name]" - break - else - temp = "This module is only needed once." - break - - // Give the power and take away the money. - A.view_core() //A BYOND bug requires you to be viewing your core before your verbs update - A.verbs += AM.power_type - A.current_modules += new AM.type - temp = AM.description - src.processing_time -= AM.cost - - if(href_list["showdesc"]) - if(AM.mod_pick_name == href_list["showdesc"]) - temp = AM.description - use(usr) diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm index 09d5fecb8a2..4a8f215ee47 100644 --- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm +++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm @@ -290,10 +290,10 @@ emote_hear = list("gaffaws", "laughs") response_help = "hugs" attacktext = "wildly tickles" - maxHealth = 150 - health = 150 - melee_damage_lower = 20 - melee_damage_upper = 20 + maxHealth = 175 + health = 175 + melee_damage_lower = 25 + melee_damage_upper = 25 attack_sound = 'sound/items/bikehorn.ogg' feast_sound = 'sound/spookoween/scary_horn2.ogg' diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index b5f468ad319..50a427ae70c 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -12,7 +12,7 @@ var/buy_word = "Learn" var/limit //used to prevent a spellbook_entry from being bought more than X times with one wizard spellbook -/datum/spellbook_entry/proc/IsAvailible() // For config prefs / gamemode restrictions - these are round applied +/datum/spellbook_entry/proc/IsSpellAvailable() // For config prefs / gamemode restrictions - these are round applied return 1 /datum/spellbook_entry/proc/CanBuy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book) // Specific circumstances if(book.uses" return dat -/datum/spellbook_entry/noclothes - name = "Remove Clothes Requirement" - spell_type = /obj/effect/proc_holder/spell/noclothes - log_name = "NC" - category = "Defensive" +//Main category - Spells +//Offensive +/datum/spellbook_entry/blind + name = "Blind" + spell_type = /obj/effect/proc_holder/spell/targeted/trigger/blind + log_name = "BD" + category = "Offensive" + cost = 1 -/datum/spellbook_entry/fireball - name = "Fireball" - spell_type = /obj/effect/proc_holder/spell/fireball - log_name = "FB" +/datum/spellbook_entry/lightningbolt + name = "Lightning Bolt" + spell_type = /obj/effect/proc_holder/spell/targeted/lightning + log_name = "LB" + category = "Offensive" + cost = 1 -/datum/spellbook_entry/rod_form - name = "Rod Form" - spell_type = /obj/effect/proc_holder/spell/targeted/rod_form - log_name = "RF" +/datum/spellbook_entry/cluwne + name = "Curse of the Cluwne" + spell_type = /obj/effect/proc_holder/spell/targeted/touch/cluwne + log_name = "CC" + category = "Offensive" -/datum/spellbook_entry/magicm - name = "Magic Missile" - spell_type = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile - log_name = "MM" - category = "Defensive" +/datum/spellbook_entry/horseman + name = "Curse of the Horseman" + spell_type = /obj/effect/proc_holder/spell/targeted/horsemask + log_name = "HH" + category = "Offensive" /datum/spellbook_entry/disintegrate name = "Disintegrate" spell_type = /obj/effect/proc_holder/spell/targeted/touch/disintegrate log_name = "DG" + category = "Offensive" +/datum/spellbook_entry/fireball + name = "Fireball" + spell_type = /obj/effect/proc_holder/spell/fireball + log_name = "FB" + category = "Offensive" + +/datum/spellbook_entry/fleshtostone + name = "Flesh to Stone" + spell_type = /obj/effect/proc_holder/spell/targeted/touch/flesh_to_stone + log_name = "FS" + category = "Offensive" + +/datum/spellbook_entry/mutate + name = "Mutate" + spell_type = /obj/effect/proc_holder/spell/targeted/genetic/mutate + log_name = "MU" + category = "Offensive" + +/datum/spellbook_entry/rod_form + name = "Rod Form" + spell_type = /obj/effect/proc_holder/spell/targeted/rod_form + log_name = "RF" + category = "Offensive" + +/datum/spellbook_entry/infinite_guns + name = "Lesser Summon Guns" + spell_type = /obj/effect/proc_holder/spell/targeted/infinite_guns + log_name = "IG" + category = "Offensive" + cost = 4 + +//Defensive /datum/spellbook_entry/disabletech name = "Disable Tech" spell_type = /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech @@ -128,37 +167,6 @@ category = "Defensive" cost = 1 -/datum/spellbook_entry/repulse - name = "Repulse" - spell_type = /obj/effect/proc_holder/spell/aoe_turf/repulse - log_name = "RP" - category = "Defensive" - -/datum/spellbook_entry/timestop - name = "Time Stop" - spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop - log_name = "TS" - category = "Defensive" - -/datum/spellbook_entry/smoke - name = "Smoke" - spell_type = /obj/effect/proc_holder/spell/targeted/smoke - log_name = "SM" - category = "Defensive" - cost = 1 - -/datum/spellbook_entry/blind - name = "Blind" - spell_type = /obj/effect/proc_holder/spell/targeted/trigger/blind - log_name = "BD" - cost = 1 - -/datum/spellbook_entry/mindswap - name = "Mindswap" - spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer - log_name = "MT" - category = "Mobility" - /datum/spellbook_entry/forcewall name = "Force Wall" spell_type = /obj/effect/proc_holder/spell/targeted/forcewall @@ -173,54 +181,18 @@ category = "Defensive" cost = 1 -/datum/spellbook_entry/blink - name = "Blink" - spell_type = /obj/effect/proc_holder/spell/targeted/turf_teleport/blink - log_name = "BL" - category = "Mobility" - -/datum/spellbook_entry/teleport - name = "Teleport" - spell_type = /obj/effect/proc_holder/spell/targeted/area_teleport/teleport - log_name = "TP" - category = "Mobility" - -/datum/spellbook_entry/mutate - name = "Mutate" - spell_type = /obj/effect/proc_holder/spell/targeted/genetic/mutate - log_name = "MU" - -/datum/spellbook_entry/jaunt - name = "Ethereal Jaunt" - spell_type = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt - log_name = "EJ" - category = "Mobility" - -/datum/spellbook_entry/knock - name = "Knock" - spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock - log_name = "KN" - category = "Mobility" +/datum/spellbook_entry/repulse + name = "Repulse" + spell_type = /obj/effect/proc_holder/spell/aoe_turf/repulse + log_name = "RP" + category = "Defensive" cost = 1 -/datum/spellbook_entry/greaterknock - name = "Greater Knock" - spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock/greater - log_name = "GK" - category = "Mobility" - cost = 2 - refundable = 0 //global effect on cast - -/datum/spellbook_entry/fleshtostone - name = "Flesh to Stone" - spell_type = /obj/effect/proc_holder/spell/targeted/touch/flesh_to_stone - log_name = "FS" - -/datum/spellbook_entry/summonitem - name = "Summon Item" - spell_type = /obj/effect/proc_holder/spell/targeted/summonitem - log_name = "IS" - category = "Assistance" +/datum/spellbook_entry/smoke + name = "Smoke" + spell_type = /obj/effect/proc_holder/spell/targeted/smoke + log_name = "SM" + category = "Defensive" cost = 1 /datum/spellbook_entry/lichdom @@ -229,28 +201,64 @@ log_name = "LD" category = "Defensive" -/datum/spellbook_entry/lichdom/IsAvailible() +/datum/spellbook_entry/lichdom/IsSpellAvailable() if(SSticker.mode.name == "ragin' mages") return FALSE else return TRUE -/datum/spellbook_entry/lightningbolt - name = "Lightning Bolt" - spell_type = /obj/effect/proc_holder/spell/targeted/lightning - log_name = "LB" +/datum/spellbook_entry/magicm + name = "Magic Missile" + spell_type = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile + log_name = "MM" + category = "Defensive" -/datum/spellbook_entry/infinite_guns - name = "Lesser Summon Guns" - spell_type = /obj/effect/proc_holder/spell/targeted/infinite_guns - log_name = "IG" - cost = 4 +/datum/spellbook_entry/timestop + name = "Time Stop" + spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop + log_name = "TS" + category = "Defensive" -/datum/spellbook_entry/horseman - name = "Curse of The Horseman" - spell_type = /obj/effect/proc_holder/spell/targeted/horsemask - log_name = "HH" +//Mobility +/datum/spellbook_entry/knock + name = "Knock" + spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock + log_name = "KN" + category = "Mobility" + cost = 1 +/datum/spellbook_entry/blink + name = "Blink" + spell_type = /obj/effect/proc_holder/spell/targeted/turf_teleport/blink + log_name = "BL" + category = "Mobility" + +/datum/spellbook_entry/jaunt + name = "Ethereal Jaunt" + spell_type = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt + log_name = "EJ" + category = "Mobility" + +/datum/spellbook_entry/greaterknock + name = "Greater Knock" + spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock/greater + log_name = "GK" + category = "Mobility" + refundable = 0 //global effect on cast + +/datum/spellbook_entry/mindswap + name = "Mindswap" + spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer + log_name = "MT" + category = "Mobility" + +/datum/spellbook_entry/teleport + name = "Teleport" + spell_type = /obj/effect/proc_holder/spell/targeted/area_teleport/teleport + log_name = "TP" + category = "Mobility" + +//Assistance /datum/spellbook_entry/charge name = "Charge" spell_type = /obj/effect/proc_holder/spell/targeted/charge @@ -258,192 +266,20 @@ category = "Assistance" cost = 1 -/datum/spellbook_entry/cluwne - name = "Curse of the Cluwne" - spell_type = /obj/effect/proc_holder/spell/targeted/touch/cluwne - log_name = "CC" - -/datum/spellbook_entry/item - name = "Buy Item" - refundable = 0 - buy_word = "Summon" - var/item_path= null - - -/datum/spellbook_entry/item/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book) - new item_path(get_turf(user)) - feedback_add_details("wizard_spell_learned",log_name) - return 1 - -/datum/spellbook_entry/item/GetInfo() - var/dat ="" - dat += "[name]" - dat += " Cost:[cost]
" - dat += "[desc]
" - if(surplus>=0) - dat += "[surplus] left.
" - return dat - -/datum/spellbook_entry/item/staffchange - name = "Staff of Change" - desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself." - item_path = /obj/item/gun/magic/staff/change - log_name = "ST" - -/datum/spellbook_entry/item/staffanimation - name = "Staff of Animation" - desc = "An arcane staff capable of shooting bolts of eldritch energy which cause inanimate objects to come to life. This magic doesn't affect machines." - item_path = /obj/item/gun/magic/staff/animate - log_name = "SA" +/datum/spellbook_entry/summonitem + name = "Summon Item" + spell_type = /obj/effect/proc_holder/spell/targeted/summonitem + log_name = "IS" category = "Assistance" - -/datum/spellbook_entry/item/staffchaos - name = "Staff of Chaos" - desc = "A caprious tool that can fire all sorts of magic without any rhyme or reason. Using it on people you care about is not recommended." - item_path = /obj/item/gun/magic/staff/chaos - log_name = "SC" - -/datum/spellbook_entry/item/staffslipping - name = "Staff of Slipping" - desc = "A staff that shoots magical bananas. These bananas will either slip or stun the target when hit. Surprisingly reliable!" - item_path = /obj/item/gun/magic/staff/slipping - log_name = "SL" cost = 1 -/datum/spellbook_entry/item/staffdoor - name = "Staff of Door Creation" - desc = "A particular staff that can mold solid metal into ornate wooden doors. Useful for getting around in the absence of other transportation. Does not work on glass." - item_path = /obj/item/gun/magic/staff/door - log_name = "SD" - cost = 1 - category = "Mobility" - -/datum/spellbook_entry/item/staffhealing - name = "Staff of Healing" - desc = "An altruistic staff that can heal the lame and raise the dead." - item_path = /obj/item/gun/magic/staff/healing - log_name = "SH" - cost = 1 - category = "Defensive" - -/datum/spellbook_entry/item/scryingorb - name = "Scrying Orb" - desc = "An incandescent orb of crackling energy, using it will allow you to ghost while alive, allowing you to spy upon the station with ease. In addition, buying it will permanently grant you x-ray vision." - item_path = /obj/item/scrying - log_name = "SO" - category = "Defensive" - -/datum/spellbook_entry/item/scryingorb/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book) - if(..()) - if(!(XRAY in user.mutations)) - user.mutations.Add(XRAY) - user.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) - user.see_in_dark = 8 - user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE - to_chat(user, "The walls suddenly disappear.") - return 1 - - -/datum/spellbook_entry/item/soulstones - name = "Six Soul Stone Shards and the spell Artificer" - desc = "Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot." - item_path = /obj/item/storage/belt/soulstone/full - log_name = "SS" +/datum/spellbook_entry/noclothes + name = "Remove Clothes Requirement" + spell_type = /obj/effect/proc_holder/spell/noclothes + log_name = "NC" category = "Assistance" -/datum/spellbook_entry/item/soulstones/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book) - . =..() - if(.) - user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(null)) - return . - -/datum/spellbook_entry/item/necrostone - name = "A Necromantic Stone" - desc = "A Necromantic stone is able to resurrect three dead individuals as skeletal thralls for you to command." - item_path = /obj/item/necromantic_stone - log_name = "NS" - category = "Assistance" - -/datum/spellbook_entry/item/wands - name = "Wand Assortment" - desc = "A collection of wands that allow for a wide variety of utility. Wands do not recharge, so be conservative in use. Comes in a handy belt." - item_path = /obj/item/storage/belt/wands/full - log_name = "WA" - category = "Defensive" - -/datum/spellbook_entry/item/armor - name = "Mastercrafted Armor Set" - desc = "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space. Comes bundled with Boots of Gripping." - item_path = /obj/item/clothing/suit/space/hardsuit/wizard - log_name = "HS" - category = "Defensive" - -/datum/spellbook_entry/item/armor/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book) - . = ..() - if(.) - new /obj/item/clothing/shoes/magboots/wizard(get_turf(user)) - new /obj/item/clothing/gloves/color/purple(get_turf(user))//To complete the outfit - -/datum/spellbook_entry/item/contract - name = "Contract of Apprenticeship" - desc = "A magical contract binding an apprentice wizard to your service, using it will summon them to your side." - item_path = /obj/item/contract - log_name = "CT" - category = "Assistance" - -/datum/spellbook_entry/item/bloodbottle - name = "Bottle of Blood" - desc = "A bottle of magically infused blood, the smell of which will attract extradimensional beings when broken. Be careful though, the kinds of creatures summoned by blood magic are indiscriminate in their killing, and you yourself may become a victim." - item_path = /obj/item/antag_spawner/slaughter_demon - log_name = "BB" - limit = 3 - category = "Assistance" - -/datum/spellbook_entry/item/hugbottle - name = "Bottle of Tickles" - desc = "A bottle of magically infused fun, the smell of which will \ - attract adorable extradimensional beings when broken. These beings \ - are similar to slaughter demons, but are a little weaker and they do not permamently \ - kill their victims, instead putting them in an extradimensional hugspace, \ - to be released on the demon's death. Chaotic, but not ultimately \ - damaging. The crew's reaction to the other hand could be very \ - destructive." - item_path = /obj/item/antag_spawner/slaughter_demon/laughter - cost = 1 //non-destructive; it's just a jape, sibling! - log_name = "HB" - limit = 3 - category = "Assistance" - -/datum/spellbook_entry/item/oozebottle - name = "Bottle of Ooze" - desc = "A bottle of magically infused ooze, which will awake an all-consuming Morph, capable of cunningly disguising itself as any object it comes in contact with and even casting some very basic spells. Be careful though, as Morph diet includes Wizards." - item_path = /obj/item/antag_spawner/morph - cost = 1 - log_name = "BO" - limit = 3 - category = "Assistance" - -/datum/spellbook_entry/item/tarotdeck - name = "Guardian Deck" - desc = "A deck of guardian tarot cards, capable of binding a personal guardian to your body. There are multiple types of guardian available, but all of them will transfer some amount of damage to you. \ - It would be wise to avoid buying these with anything capable of causing you to swap bodies with others." - item_path = /obj/item/guardiancreator - log_name = "TD" - limit = 1 - category = "Assistance" - -/datum/spellbook_entry/item/mjolnir - name = "Mjolnir" - desc = "A mighty hammer on loan from Thor, God of Thunder. It crackles with barely contained power." - item_path = /obj/item/twohanded/mjollnir - log_name = "MJ" - -/datum/spellbook_entry/item/singularity_hammer - name = "Singularity Hammer" - desc = "A hammer that creates an intensely powerful field of gravity where it strikes, pulling everthing nearby to the point of impact." - item_path = /obj/item/twohanded/singularityhammer - log_name = "SI" - +//Rituals /datum/spellbook_entry/summon name = "Summon Stuff" category = "Rituals" @@ -472,7 +308,7 @@ cost = 0 log_name = "SGH" -/datum/spellbook_entry/summon/ghosts/IsAvailible() +/datum/spellbook_entry/summon/ghosts/IsSpellAvailable() if(!SSticker.mode) // In case spellbook is placed on map return FALSE if(SSticker.mode.name == "ragin' mages") @@ -493,7 +329,7 @@ cost = 0 log_name = "SG" -/datum/spellbook_entry/summon/guns/IsAvailible() +/datum/spellbook_entry/summon/guns/IsSpellAvailable() if(!SSticker.mode) // In case spellbook is placed on map return FALSE if(SSticker.mode.name == "ragin' mages") @@ -502,7 +338,7 @@ return TRUE /datum/spellbook_entry/summon/guns/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book) - feedback_add_details("wizard_spell_learned",log_name) + feedback_add_details("wizard_spell_learned", log_name) user.rightandwrong(0) book.uses += 1 active = 1 @@ -515,7 +351,7 @@ cost = 0 log_name = "SU" -/datum/spellbook_entry/summon/magic/IsAvailible() +/datum/spellbook_entry/summon/magic/IsSpellAvailable() if(!SSticker.mode) // In case spellbook is placed on map return FALSE if(SSticker.mode.name == "ragin' mages") @@ -524,18 +360,207 @@ return TRUE /datum/spellbook_entry/summon/magic/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book) - feedback_add_details("wizard_spell_learned",log_name) + feedback_add_details("wizard_spell_learned", log_name) user.rightandwrong(1) book.uses += 1 active = 1 to_chat(user, "You have cast summon magic and gained an extra charge for your spellbook.") return 1 +//Main category - Magical Items +/datum/spellbook_entry/item + name = "Buy Item" + refundable = 0 + buy_word = "Summon" + var/item_path = null + +/datum/spellbook_entry/item/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book) + new item_path(get_turf(user)) + feedback_add_details("wizard_spell_learned", log_name) + return 1 + +/datum/spellbook_entry/item/GetInfo() + var/dat ="" + dat += "[name]" + dat += " Cost:[cost]
" + dat += "[desc]
" + if(surplus>=0) + dat += "[surplus] left.
" + return dat + +//Artefacts +/datum/spellbook_entry/item/necrostone + name = "A Necromantic Stone" + desc = "A Necromantic stone is able to resurrect three dead individuals as skeletal thralls for you to command." + item_path = /obj/item/necromantic_stone + log_name = "NS" + category = "Artefacts" + +/datum/spellbook_entry/item/scryingorb + name = "Scrying Orb" + desc = "An incandescent orb of crackling energy, using it will allow you to ghost while alive, allowing you to spy upon the station with ease. In addition, buying it will permanently grant you x-ray vision." + item_path = /obj/item/scrying + log_name = "SO" + category = "Artefacts" + +/datum/spellbook_entry/item/scryingorb/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book) + if(..()) + if(!(XRAY in user.mutations)) + user.mutations.Add(XRAY) + user.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) + user.see_in_dark = 8 + user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE + to_chat(user, "The walls suddenly disappear.") + return TRUE + +/datum/spellbook_entry/item/soulstones + name = "Six Soul Stone Shards and the spell Artificer" + desc = "Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot." + item_path = /obj/item/storage/belt/soulstone/full + log_name = "SS" + category = "Artefacts" + +/datum/spellbook_entry/item/soulstones/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book) + . = ..() + if(.) + user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(null)) + return . + +/datum/spellbook_entry/item/wands + name = "Wand Assortment" + desc = "A collection of wands that allow for a wide variety of utility. Wands do not recharge, so be conservative in use. Comes in a handy belt." + item_path = /obj/item/storage/belt/wands/full + log_name = "WA" + category = "Artefacts" + +//Weapons and Armors +/datum/spellbook_entry/item/armor + name = "Mastercrafted Armor Set" + desc = "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space. Comes bundled with Boots of Gripping." + item_path = /obj/item/clothing/suit/space/hardsuit/wizard + log_name = "HS" + category = "Weapons and Armors" + +/datum/spellbook_entry/item/armor/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book) + . = ..() + if(.) + new /obj/item/clothing/shoes/magboots/wizard(get_turf(user)) + new /obj/item/clothing/gloves/color/purple(get_turf(user)) // To complete the outfit + +/datum/spellbook_entry/item/mjolnir + name = "Mjolnir" + desc = "A mighty hammer on loan from Thor, God of Thunder. It crackles with barely contained power." + item_path = /obj/item/twohanded/mjollnir + log_name = "MJ" + category = "Weapons and Armors" + +/datum/spellbook_entry/item/singularity_hammer + name = "Singularity Hammer" + desc = "A hammer that creates an intensely powerful field of gravity where it strikes, pulling everthing nearby to the point of impact." + item_path = /obj/item/twohanded/singularityhammer + log_name = "SI" + category = "Weapons and Armors" + +//Staves +/datum/spellbook_entry/item/staffdoor + name = "Staff of Door Creation" + desc = "A particular staff that can mold solid metal into ornate wooden doors. Useful for getting around in the absence of other transportation. Does not work on glass." + item_path = /obj/item/gun/magic/staff/door + log_name = "SD" + category = "Staves" + cost = 1 + +/datum/spellbook_entry/item/staffhealing + name = "Staff of Healing" + desc = "An altruistic staff that can heal the lame and raise the dead." + item_path = /obj/item/gun/magic/staff/healing + log_name = "SH" + category = "Staves" + cost = 1 + +/datum/spellbook_entry/item/staffslipping + name = "Staff of Slipping" + desc = "A staff that shoots magical bananas. These bananas will either slip or stun the target when hit. Surprisingly reliable!" + item_path = /obj/item/gun/magic/staff/slipping + log_name = "SL" + category = "Staves" + cost = 1 + +/datum/spellbook_entry/item/staffanimation + name = "Staff of Animation" + desc = "An arcane staff capable of shooting bolts of eldritch energy which cause inanimate objects to come to life. This magic doesn't affect machines." + item_path = /obj/item/gun/magic/staff/animate + log_name = "SA" + category = "Staves" + +/datum/spellbook_entry/item/staffchange + name = "Staff of Change" + desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself." + item_path = /obj/item/gun/magic/staff/change + log_name = "ST" + category = "Staves" + +/datum/spellbook_entry/item/staffchaos + name = "Staff of Chaos" + desc = "A caprious tool that can fire all sorts of magic without any rhyme or reason. Using it on people you care about is not recommended." + item_path = /obj/item/gun/magic/staff/chaos + log_name = "SC" + category = "Staves" + +//Summons +/datum/spellbook_entry/item/oozebottle + name = "Bottle of Ooze" + desc = "A bottle of magically infused ooze, which will awake an all-consuming Morph, capable of cunningly disguising itself as any object it comes in contact with and even casting some very basic spells. Be careful though, as Morph diet includes Wizards." + item_path = /obj/item/antag_spawner/morph + log_name = "BO" + category = "Summons" + limit = 3 + cost = 1 + +/datum/spellbook_entry/item/hugbottle + name = "Bottle of Tickles" + desc = "A bottle of magically infused fun, the smell of which will \ + attract adorable extradimensional beings when broken. These beings \ + are similar to slaughter demons, but are a little weaker and they do not permamently \ + kill their victims, instead putting them in an extradimensional hugspace, \ + to be released on the demon's death. Chaotic, but not ultimately \ + damaging. The crew's reaction to the other hand could be very \ + destructive." + item_path = /obj/item/antag_spawner/slaughter_demon/laughter + log_name = "HB" + category = "Summons" + limit = 3 + cost = 1 // Non-destructive; it's just a jape, sibling! + +/datum/spellbook_entry/item/bloodbottle + name = "Bottle of Blood" + desc = "A bottle of magically infused blood, the smell of which will attract extradimensional beings when broken. Be careful though, the kinds of creatures summoned by blood magic are indiscriminate in their killing, and you yourself may become a victim." + item_path = /obj/item/antag_spawner/slaughter_demon + log_name = "BB" + category = "Summons" + limit = 3 + +/datum/spellbook_entry/item/contract + name = "Contract of Apprenticeship" + desc = "A magical contract binding an apprentice wizard to your service, using it will summon them to your side." + item_path = /obj/item/contract + log_name = "CT" + category = "Summons" + +/datum/spellbook_entry/item/tarotdeck + name = "Guardian Deck" + desc = "A deck of guardian tarot cards, capable of binding a personal guardian to your body. There are multiple types of guardian available, but all of them will transfer some amount of damage to you. \ + It would be wise to avoid buying these with anything capable of causing you to swap bodies with others." + item_path = /obj/item/guardiancreator + log_name = "TD" + category = "Summons" + limit = 1 + /obj/item/spellbook name = "spell book" desc = "The legendary book of spells of the wizard." icon = 'icons/obj/library.dmi' - icon_state ="book" + icon_state = "spellbook" throw_speed = 2 throw_range = 5 w_class = WEIGHT_CLASS_TINY @@ -543,19 +568,24 @@ var/temp = null var/op = 1 var/tab = null + var/main_tab = null var/mob/living/carbon/human/owner var/list/datum/spellbook_entry/entries = list() var/list/categories = list() + var/list/main_categories = list("Spells", "Magical Items") + var/list/spell_categories = list("Offensive", "Defensive", "Mobility", "Assistance", "Rituals") + var/list/item_categories = list("Artefacts", "Weapons and Armors", "Staves", "Summons") /obj/item/spellbook/proc/initialize() var/entry_types = subtypesof(/datum/spellbook_entry) - /datum/spellbook_entry/item - /datum/spellbook_entry/summon for(var/T in entry_types) var/datum/spellbook_entry/E = new T - if(E.IsAvailible()) + if(E.IsSpellAvailable()) entries |= E categories |= E.category else qdel(E) + main_tab = main_categories[1] tab = categories[1] /obj/item/spellbook/New() @@ -569,48 +599,64 @@ to_chat(user, "The contract has been used, you can't get your points back now!") else to_chat(user, "You feed the contract back into the spellbook, refunding your points.") - uses+=2 - qdel(O) if(istype(O, /obj/item/antag_spawner/slaughter_demon)) to_chat(user, "On second thought, maybe summoning a demon is a bad idea. You refund your points.") - if(istype(O, /obj/item/antag_spawner/slaughter_demon/laughter)) uses += 1 + for(var/datum/spellbook_entry/item/hugbottle/HB in entries) + if(!isnull(HB.limit)) + HB.limit++ else uses += 2 - for(var/datum/spellbook_entry/item/bloodbottle/BB in entries) - if(!isnull(BB.limit)) - BB.limit++ + for(var/datum/spellbook_entry/item/bloodbottle/BB in entries) + if(!isnull(BB.limit)) + BB.limit++ + qdel(O) + + if(istype(O, /obj/item/antag_spawner/morph)) + to_chat(user, "On second thought, maybe awakening a morph is a bad idea. You refund your points.") + uses += 1 + for(var/datum/spellbook_entry/item/oozebottle/OB in entries) + if(!isnull(OB.limit)) + OB.limit++ qdel(O) /obj/item/spellbook/proc/GetCategoryHeader(var/category) var/dat = "" switch(category) if("Offensive") - dat += "Spells and items geared towards debilitating and destroying.

" - dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
" + dat += "Spells geared towards debilitating and destroying.

" dat += "For spells: the number after the spell name is the cooldown time.
" dat += "You can reduce this number by spending more points on the spell.
" if("Defensive") - dat += "Spells and items geared towards improving your survivabilty or reducing foes ability to attack.

" - dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
" + dat += "Spells geared towards improving your survivabilty or reducing foes ability to attack.

" dat += "For spells: the number after the spell name is the cooldown time.
" dat += "You can reduce this number by spending more points on the spell.
" if("Mobility") - dat += "Spells and items geared towards improving your ability to move. It is a good idea to take at least one.

" - dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
" + dat += "Spells geared towards improving your ability to move. It is a good idea to take at least one.

" dat += "For spells: the number after the spell name is the cooldown time.
" dat += "You can reduce this number by spending more points on the spell.
" if("Assistance") - dat += "Spells and items geared towards bringing in outside forces to aid you or improving upon your other items and abilties.

" - dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
" + dat += "Spells geared towards improving your other items and abilities.

" dat += "For spells: the number after the spell name is the cooldown time.
" dat += "You can reduce this number by spending more points on the spell.
" if("Rituals") - dat += "These powerful spells change the very fabric of reality. Not always in your favour.
" + dat += "These powerful spells are capable of changing the very fabric of reality. Not always in your favour.
" + if("Weapons and Armors") + dat += "Various weapons and armors to crush your enemies and protect you from harm.

" + dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
" + if("Staves") + dat += "Various staves granting you their power, which they slowly recharge over time.

" + dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
" + if("Artefacts") + dat += "Various magical artefacts to aid you.

" + dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
" + if("Summons") + dat += "Magical items geared towards bringing in outside forces to aid you.

" + dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
" return dat /obj/item/spellbook/proc/wrap(var/content) @@ -620,11 +666,16 @@ @@ -644,13 +695,29 @@ user.set_machine(src) var/dat = "" - dat += "
    " + dat += "
      " var/list/cat_dat = list() - for(var/category in categories) - cat_dat[category] = "
      " - dat += "
    • [category]
    • " - - dat += "
    • Points remaining : [uses]
    • " + for(var/main_category in main_categories) + cat_dat[main_category] = "
      " + dat += "
    • [main_category]
    • " + dat += "
    " + switch(main_tab) + if("Spells") + dat += "
      " + for(var/category in categories) + if(category in item_categories) + continue + cat_dat[category] = "
      " + dat += "
    • [category]
    • " + dat += "
    • Points remaining : [uses]
    • " + if("Magical Items") + dat += "" var/datum/spellbook_entry/E @@ -674,7 +741,7 @@ dat += cat_dat[category] dat += "" - user << browse(wrap(dat), "window=spellbook;size=700x500") + user << browse(wrap(dat), "window=spellbook;size=800x600") onclose(user, "spellbook") return @@ -708,13 +775,19 @@ if(!isnull(E.limit)) E.limit += result uses += result + else if(href_list["mainpage"]) + main_tab = sanitize(href_list["mainpage"]) + tab = sanitize(href_list["page"]) + if(main_tab == "Spells") + tab = spell_categories[1] + else if(main_tab == "Magical Items") + tab = item_categories[1] else if(href_list["page"]) tab = sanitize(href_list["page"]) attack_self(H) return 1 -//Single Use Spellbooks// - +//Single Use Spellbooks /obj/item/spellbook/oneuse var/spell = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile //just a placeholder to avoid runtimes if someone spawned the generic var/spellname = "sandbox" @@ -748,7 +821,6 @@ user.create_attack_log("[key_name(user)] learned the spell [spellname] ([S]).") onlearned(user) - /obj/item/spellbook/oneuse/proc/recoil(mob/user) user.visible_message("[src] glows in a black light!") @@ -762,7 +834,7 @@ /obj/item/spellbook/oneuse/fireball spell = /obj/effect/proc_holder/spell/fireball spellname = "fireball" - icon_state ="bookfireball" + icon_state = "bookfireball" desc = "This book feels warm to the touch." /obj/item/spellbook/oneuse/fireball/recoil(mob/user as mob) @@ -773,7 +845,7 @@ /obj/item/spellbook/oneuse/smoke spell = /obj/effect/proc_holder/spell/targeted/smoke spellname = "smoke" - icon_state ="booksmoke" + icon_state = "booksmoke" desc = "This book is overflowing with the dank arts." /obj/item/spellbook/oneuse/smoke/recoil(mob/user as mob) @@ -787,7 +859,7 @@ /obj/item/spellbook/oneuse/blind spell = /obj/effect/proc_holder/spell/targeted/trigger/blind spellname = "blind" - icon_state ="bookblind" + icon_state = "bookblind" desc = "This book looks blurry, no matter how you look at it." /obj/item/spellbook/oneuse/blind/recoil(mob/user as mob) @@ -798,7 +870,7 @@ /obj/item/spellbook/oneuse/mindswap spell = /obj/effect/proc_holder/spell/targeted/mind_transfer spellname = "mindswap" - icon_state ="bookmindswap" + icon_state = "bookmindswap" desc = "This book's cover is pristine, though its pages look ragged and torn." var/mob/stored_swap = null //Used in used book recoils to store an identity for mindswaps @@ -830,7 +902,7 @@ /obj/item/spellbook/oneuse/forcewall spell = /obj/effect/proc_holder/spell/targeted/forcewall spellname = "forcewall" - icon_state ="bookforcewall" + icon_state = "bookforcewall" desc = "This book has a dedication to mimes everywhere inside the front cover." /obj/item/spellbook/oneuse/forcewall/recoil(mob/user as mob) @@ -840,11 +912,10 @@ S.timer = 30 user.drop_item() - /obj/item/spellbook/oneuse/knock spell = /obj/effect/proc_holder/spell/aoe_turf/knock spellname = "knock" - icon_state ="bookknock" + icon_state = "bookknock" desc = "This book is hard to hold closed properly." /obj/item/spellbook/oneuse/knock/recoil(mob/user as mob) @@ -855,7 +926,7 @@ /obj/item/spellbook/oneuse/horsemask spell = /obj/effect/proc_holder/spell/targeted/horsemask spellname = "horses" - icon_state ="bookhorses" + icon_state = "bookhorses" desc = "This book is more horse than your mind has room for." /obj/item/spellbook/oneuse/horsemask/recoil(mob/living/carbon/user as mob) @@ -875,7 +946,7 @@ /obj/item/spellbook/oneuse/charge spell = /obj/effect/proc_holder/spell/targeted/charge spellname = "charging" - icon_state ="bookcharge" + icon_state = "bookcharge" desc = "This book is made of 100% post-consumer wizard." /obj/item/spellbook/oneuse/charge/recoil(mob/user as mob) @@ -886,7 +957,7 @@ /obj/item/spellbook/oneuse/summonitem spell = /obj/effect/proc_holder/spell/targeted/summonitem spellname = "instant summons" - icon_state ="booksummons" + icon_state = "booksummons" desc = "This book is bright and garish, very hard to miss." /obj/item/spellbook/oneuse/summonitem/recoil(mob/user as mob) @@ -897,13 +968,13 @@ /obj/item/spellbook/oneuse/fake_gib spell = /obj/effect/proc_holder/spell/targeted/touch/fake_disintegrate spellname = "disintegrate" - icon_state ="bookfireball" + icon_state = "bookfireball" desc = "This book feels like it will rip stuff apart." /obj/item/spellbook/oneuse/sacredflame spell = /obj/effect/proc_holder/spell/targeted/sacred_flame spellname = "sacred flame" - icon_state ="booksacredflame" + icon_state = "booksacredflame" desc = "Become one with the flames that burn within... and invite others to do so as well." /obj/item/spellbook/oneuse/random diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index 407393eb489..0dfd0876817 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -214,7 +214,7 @@ suit = /obj/item/clothing/suit/storage/fr_jacket shoes = /obj/item/clothing/shoes/white l_ear = /obj/item/radio/headset/headset_sec/alt - glasses = /obj/item/clothing/glasses/hud/health/health_advanced + glasses = /obj/item/clothing/glasses/hud/health/sunglasses id = /obj/item/card/id/security suit_store = /obj/item/flashlight/pen l_hand = /obj/item/storage/firstaid/adv diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm index 3208e9d3533..849f54169f5 100644 --- a/code/game/jobs/job/supervisor.dm +++ b/code/game/jobs/job/supervisor.dm @@ -175,7 +175,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 0) gloves = /obj/item/clothing/gloves/combat shoes = /obj/item/clothing/shoes/jackboots l_ear = /obj/item/radio/headset/heads/blueshield/alt - glasses = /obj/item/clothing/glasses/hud/health/health_advanced + glasses = /obj/item/clothing/glasses/hud/health/sunglasses id = /obj/item/card/id/nanotrasen pda = /obj/item/pda/heads/blueshield backpack_contents = list( diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm index aac1c291355..a247fa6810b 100644 --- a/code/game/jobs/job/support.dm +++ b/code/game/jobs/job/support.dm @@ -66,6 +66,12 @@ l_ear = /obj/item/radio/headset/headset_service pda = /obj/item/pda/chef +/datum/outfit/job/chef/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) + ..() + if(visualsOnly) + return + var/datum/martial_art/cqc/under_siege/justacook = new + justacook.teach(H) /datum/job/hydro diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm index 75c4e466a79..a0c0d2234af 100644 --- a/code/game/machinery/dance_machine.dm +++ b/code/game/machinery/dance_machine.dm @@ -322,6 +322,9 @@ /obj/machinery/disco/proc/dance(mob/living/M) //Show your moves set waitfor = FALSE + if(M.client && !(M.client.prefs.sound & SOUND_DISCO)) //We have a client that doesn't want to dance. + rangers -= M //Doing that here as it'll be checked less often than in processing. + return switch(rand(0,9)) if(0 to 1) dance2(M) @@ -460,17 +463,18 @@ var/sound/song_played = sound(selection.song_path) for(var/mob/M in range(10,src)) - if(!(M in rangers)) - rangers[M] = TRUE - M.playsound_local(get_turf(M), null, 100, channel = CHANNEL_JUKEBOX, S = song_played) - if(prob(5+(allowed(M) * 4)) && M.canmove && isliving(M)) - dance(M) + if(!M.client || M.client.prefs.sound & SOUND_DISCO) + if(!(M in rangers)) + rangers[M] = TRUE + M.playsound_local(get_turf(M), null, 100, channel = CHANNEL_JUKEBOX, S = song_played) for(var/mob/L in rangers) if(get_dist(src, L) > 10) rangers -= L if(!L || !L.client) continue L.stop_sound_channel(CHANNEL_JUKEBOX) + else if(prob(9) && L.canmove && isliving(L)) + dance(L) else if(active) active = FALSE STOP_PROCESSING(SSobj, src) diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index e0fb65787cd..6785c5ed8ff 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -1,144 +1,231 @@ -/* -CONTAINS: +#define SINGLE "single" +#define VERTICAL "vertical" +#define HORIZONTAL "horizontal" -Deployable items -Barricades +#define METAL 1 +#define WOOD 2 +#define SAND 3 -for reference: +//Barricades/cover - access_security = 1 - access_brig = 2 - access_armory = 3 - access_forensics_lockers= 4 - access_medical = 5 - access_morgue = 6 - access_tox = 7 - access_tox_storage = 8 - access_genetics = 9 - access_engine = 10 - access_engine_equip= 11 - access_maint_tunnels = 12 - access_external_airlocks = 13 - access_emergency_storage = 14 - access_change_ids = 15 - access_ai_upload = 16 - access_teleporter = 17 - access_eva = 18 - access_heads = 19 - access_captain = 20 - access_all_personal_lockers = 21 - access_chapel_office = 22 - access_tech_storage = 23 - access_atmospherics = 24 - access_bar = 25 - access_janitor = 26 - access_crematorium = 27 - access_kitchen = 28 - access_robotics = 29 - access_rd = 30 - access_cargo = 31 - access_construction = 32 - access_chemistry = 33 - access_cargo_bot = 34 - access_hydroponics = 35 - access_manufacturing = 36 - access_library = 37 - access_lawyer = 38 - access_virology = 39 - access_cmo = 40 - access_qm = 41 - access_court = 42 - access_clown = 43 - access_mime = 44 - -*/ - - -//Barricades, maybe there will be a metal one later... /obj/structure/barricade - anchored = 1.0 - density = 1.0 - var/health = 100.0 - var/maxhealth = 100.0 + name = "chest high wall" + desc = "Looks like this would make good cover." + anchored = TRUE + density = TRUE + max_integrity = 100 + var/proj_pass_rate = 50 //How many projectiles will pass the cover. Lower means stronger cover + var/bar_material = METAL + var/drop_amount = 3 var/stacktype = /obj/item/stack/sheet/metal -/obj/structure/barricade/attackby(obj/item/W as obj, mob/user as mob, params) - if(istype(W, stacktype)) - if(src.health < src.maxhealth) - visible_message("[user] begins to repair the [src]!") - if(do_after(user, 20 * W.toolspeed, target = src)) - src.health = src.maxhealth - W:use(1) - visible_message("[user] repairs the [src]!") - return - else - return - return - else if(istype(W, /obj/item/crowbar)) - user.changeNext_move(CLICK_CD_MELEE) - user.visible_message("[user] is prying apart \the [src].", "You begin to pry apart \the [src].") - playsound(src, W.usesound, 200, 1) +/obj/structure/barricade/blob_act(obj/structure/blob/B) //TO-DO-OBJECT-DAMAGE: Kill off when everything is damageable + take_damage(400, BRUTE, "melee", 0, get_dir(src, B)) - if(do_after(user, 300 * W.toolspeed, target = src) && !QDELETED(src)) - user.visible_message("[user] pries apart \the [src].", "You pry apart \the [src].") - dismantle() +/obj/structure/barricade/ex_act(severity) //TO-DO-OBJECT-DAMAGE: Kill off when everything is damageable + if(resistance_flags & INDESTRUCTIBLE) return - else - switch(W.damtype) - if("fire") - src.health -= W.force * 1 - if("brute") - src.health -= W.force * 0.75 - else - if(src.health <= 0) - visible_message("\The [src] is smashed apart!") - dismantle() - ..() - -/obj/structure/barricade/ex_act(severity) switch(severity) - if(1.0) - visible_message("\The [src] is blown apart!") + if(1) + obj_integrity = 0 qdel(src) - return - if(2.0) - src.health -= 25 - if(src.health <= 0) - visible_message("\The [src] is blown apart!") - dismantle() - return + if(2) + take_damage(rand(100, 250), BRUTE, "bomb", 0) + if(3) + take_damage(rand(10, 90), BRUTE, "bomb", 0) -/obj/structure/barricade/blob_act() - src.health -= 25 - if(src.health <= 0) - visible_message("The blob eats through \the [src]!") - qdel(src) - return - -/obj/structure/barricade/CanPass(atom/movable/mover, turf/target, height=0)//So bullets will fly over and stuff. - if(height==0) - return 1 - if(istype(mover) && mover.checkpass(PASSTABLE)) - return 1 +/obj/structure/barricade/mech_melee_attack(obj/mecha/M) //TO-DO-OBJECT-DAMAGE: Kill off when everything is damageable + M.do_attack_animation(src) + var/play_soundeffect = 0 + var/mech_damtype = M.damtype + if(M.selected) + mech_damtype = M.selected.damtype + play_soundeffect = 1 else - return 0 + switch(M.damtype) + if(BRUTE) + playsound(src, 'sound/weapons/punch4.ogg', 50, 1) + if(BURN) + playsound(src, 'sound/items/welder.ogg', 50, 1) + if(TOX) + playsound(src, 'sound/effects/spray2.ogg', 50, 1) + return 0 + else + return 0 + visible_message("[M.name] has hit [src].") + return take_damage(M.force*3, mech_damtype, "melee", play_soundeffect, get_dir(src, M)) // multiplied by 3 so we can hit objs hard but not be overpowered against mobs. -/obj/structure/barricade/proc/dismantle() - if(stacktype) - new stacktype(get_turf(src)) - new stacktype(get_turf(src)) - new stacktype(get_turf(src)) +/obj/structure/barricade/deconstruct(disassembled = TRUE) + make_debris() qdel(src) +/obj/structure/barricade/proc/make_debris() + if(stacktype) + new stacktype(get_turf(src), drop_amount) + +/obj/structure/barricade/attackby(obj/item/I, mob/user, params) + if(iswelder(I) && user.a_intent != INTENT_HARM && bar_material == METAL) + var/obj/item/weldingtool/WT = I + if(obj_integrity < max_integrity) + if(WT.remove_fuel(0, user)) + to_chat(user, "You begin repairing [src]...") + playsound(loc, WT.usesound, 40, 1) + if(do_after(user, 40 * I.toolspeed, target = src)) + obj_integrity = Clamp(obj_integrity + 20, 0, max_integrity) + else + return ..() + +/obj/structure/barricade/CanPass(atom/movable/mover, turf/target)//So bullets will fly over and stuff. + if(locate(/obj/structure/barricade) in get_turf(mover)) + return TRUE + else if(istype(mover, /obj/item/projectile)) + if(!anchored) + return TRUE + var/obj/item/projectile/proj = mover + if(proj.firer && Adjacent(proj.firer)) + return TRUE + if(prob(proj_pass_rate)) + return TRUE + return FALSE + else + return !density + + + +/////BARRICADE TYPES/////// + /obj/structure/barricade/wooden name = "wooden barricade" desc = "This space is blocked off by a wooden barricade." icon = 'icons/obj/structures.dmi' icon_state = "woodenbarricade" + bar_material = WOOD stacktype = /obj/item/stack/sheet/wood burn_state = FLAMMABLE burntime = 25 +/obj/structure/barricade/wooden/attackby(obj/item/I, mob/user) + if(istype(I,/obj/item/stack/sheet/wood)) + var/obj/item/stack/sheet/wood/W = I + if(W.amount < 5) + to_chat(user, "You need at least five wooden planks to make a wall!") + return + else + to_chat(user, "You start adding [I] to [src]...") + if(do_after(user, 50, target = src)) + W.use(5) + new /turf/simulated/wall/mineral/wood/nonmetal(get_turf(src)) + qdel(src) + return + return ..() + +/obj/structure/barricade/wooden/crude + name = "crude plank barricade" + desc = "This space is blocked off by a crude assortment of planks." + icon_state = "woodenbarricade-old" + drop_amount = 1 + max_integrity = 50 + proj_pass_rate = 65 + +/obj/structure/barricade/wooden/crude/snow + desc = "This space is blocked off by a crude assortment of planks. It seems to be covered in a layer of snow." + icon_state = "woodenbarricade-snow-old" + max_integrity = 75 + +/obj/structure/barricade/sandbags + name = "sandbags" + desc = "Bags of sand. Self explanatory." + icon = 'icons/obj/smooth_structures/sandbags.dmi' + icon_state = "sandbags" + max_integrity = 280 + proj_pass_rate = 20 + pass_flags = LETPASSTHROW + bar_material = SAND + climbable = TRUE + smooth = SMOOTH_TRUE + canSmoothWith = list(/obj/structure/barricade/sandbags, /turf/simulated/wall, /turf/simulated/wall/r_wall, /obj/structure/falsewall, /obj/structure/falsewall/reinforced, /turf/simulated/wall/rust, /turf/simulated/wall/r_wall/rust, /obj/structure/barricade/security) + stacktype = null + +/obj/structure/barricade/security + name = "security barrier" + desc = "A deployable barrier. Provides good cover in fire fights." + icon = 'icons/obj/objects.dmi' + icon_state = "barrier0" + density = FALSE + anchored = FALSE + max_integrity = 180 + proj_pass_rate = 20 + armor = list(melee = 10, bullet = 50, laser = 50, energy = 50, bomb = 10, bio = 100, rad = 100) + stacktype = null + var/deploy_time = 40 + var/deploy_message = TRUE + +/obj/structure/barricade/security/New() + ..() + addtimer(CALLBACK(src, .proc/deploy), deploy_time) + +/obj/structure/barricade/security/proc/deploy() + icon_state = "barrier1" + density = TRUE + anchored = TRUE + if(deploy_message) + visible_message("[src] deploys!") + + +/obj/item/grenade/barrier + name = "barrier grenade" + desc = "Instant cover." + icon = 'icons/obj/grenade.dmi' + icon_state = "flashbang" + item_state = "flashbang" + actions_types = list(/datum/action/item_action/toggle_barrier_spread) + var/mode = SINGLE + +/obj/item/grenade/barrier/examine(mob/user) + . = ..() + to_chat(user, "Alt-click to toggle modes.") + +/obj/item/grenade/barrier/AltClick(mob/living/carbon/user) + if(!istype(user) || !user.Adjacent(src) || user.incapacitated()) + return + toggle_mode(user) + +/obj/item/grenade/barrier/proc/toggle_mode(mob/user) + switch(mode) + if(SINGLE) + mode = VERTICAL + if(VERTICAL) + mode = HORIZONTAL + if(HORIZONTAL) + mode = SINGLE + + to_chat(user, "[src] is now in [mode] mode.") + +/obj/item/grenade/barrier/prime() + new /obj/structure/barricade/security(get_turf(loc)) + switch(mode) + if(VERTICAL) + var/target_turf = get_step(src, NORTH) + if(!(is_blocked_turf(target_turf))) + new /obj/structure/barricade/security(target_turf) + + var/target_turf2 = get_step(src, SOUTH) + if(!(is_blocked_turf(target_turf2))) + new /obj/structure/barricade/security(target_turf2) + if(HORIZONTAL) + var/target_turf = get_step(src, EAST) + if(!(is_blocked_turf(target_turf))) + new /obj/structure/barricade/security(target_turf) + + var/target_turf2 = get_step(src, WEST) + if(!(is_blocked_turf(target_turf2))) + new /obj/structure/barricade/security(target_turf2) + qdel(src) + +/obj/item/grenade/barrier/ui_action_click(mob/user) + toggle_mode(user) + + /obj/structure/barricade/mime name = "floor" desc = "Is... this a floor?" @@ -149,128 +236,10 @@ for reference: /obj/structure/barricade/mime/mrcd stacktype = null -//Actual Deployable machinery stuff +#undef SINGLE +#undef VERTICAL +#undef HORIZONTAL -/obj/machinery/deployable - name = "deployable" - desc = "deployable" - icon = 'icons/obj/objects.dmi' - req_access = list(access_security)//I'm changing this until these are properly tested./N - -/obj/machinery/deployable/barrier - name = "deployable barrier" - desc = "A deployable barrier. Swipe your ID card to lock/unlock it." - icon = 'icons/obj/objects.dmi' - anchored = 0.0 - density = 1.0 - icon_state = "barrier0" - var/health = 100.0 - var/maxhealth = 100.0 - var/locked = 0.0 -// req_access = list(access_maint_tunnels) - -/obj/machinery/deployable/barrier/New() - ..() - - src.icon_state = "barrier[src.locked]" - -/obj/machinery/deployable/barrier/attackby(obj/item/W as obj, mob/user as mob, params) - if(istype(W, /obj/item/card/id)) - if(src.allowed(user)) - if(src.emagged < 2.0) - src.locked = !src.locked - src.anchored = !src.anchored - src.icon_state = "barrier[src.locked]" - if((src.locked == 1.0) && (src.emagged < 2.0)) - to_chat(user, "Barrier lock toggled on.") - return - else if((src.locked == 0.0) && (src.emagged < 2.0)) - to_chat(user, "Barrier lock toggled off.") - return - else - do_sparks(2, 1, src) - visible_message("BZZzZZzZZzZT") - return - return - else if(istype(W, /obj/item/wrench)) - if(src.health < src.maxhealth) - src.health = src.maxhealth - src.emagged = 0 - src.req_access = list(access_security) - visible_message("[user] repairs the [src]!") - return - else if(src.emagged > 0) - src.emagged = 0 - src.req_access = list(access_security) - visible_message("[user] repairs the [src]!") - return - return - else - switch(W.damtype) - if("fire") - src.health -= W.force * 0.75 - if("brute") - src.health -= W.force * 0.5 - else - if(src.health <= 0) - src.explode() - ..() - -/obj/machinery/deployable/barrier/emag_act(user as mob) - if(!emagged) - emagged = 1 - req_access = null - to_chat(user, "You break the ID authentication lock on the [src].") - do_sparks(2, 1, src) - visible_message("BZZzZZzZZzZT") - else if(src.emagged == 1) - src.emagged = 2 - to_chat(user, "You short out the anchoring mechanism on the [src].") - do_sparks(2, 1, src) - visible_message("BZZzZZzZZzZT") - -/obj/machinery/deployable/barrier/ex_act(severity) - switch(severity) - if(1.0) - src.explode() - return - if(2.0) - src.health -= 25 - if(src.health <= 0) - src.explode() - return - -/obj/machinery/deployable/barrier/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - return - if(prob(50/severity)) - locked = !locked - anchored = !anchored - icon_state = "barrier[src.locked]" - -/obj/machinery/deployable/barrier/blob_act() - src.health -= 25 - if(src.health <= 0) - src.explode() - return - -/obj/machinery/deployable/barrier/CanPass(atom/movable/mover, turf/target, height=0)//So bullets will fly over and stuff. - if(height==0) - return 1 - if(istype(mover) && mover.checkpass(PASSTABLE)) - return 1 - else - return 0 - -/obj/machinery/deployable/barrier/proc/explode() - visible_message("[src] blows apart!") - var/turf/Tsec = get_turf(src) - -/* var/obj/item/stack/rods/ =*/ - new /obj/item/stack/rods(Tsec) - - do_sparks(3, 1, src) - - explosion(src.loc,-1,-1,0) - if(src) - qdel(src) +#undef METAL +#undef WOOD +#undef SAND \ No newline at end of file diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 797eee044ad..5abfc313047 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -109,6 +109,7 @@ var/obj/item/gun/energy/E = charging if(E.power_supply.charge < E.power_supply.maxcharge) E.power_supply.give(E.power_supply.chargerate * recharge_coeff) + E.on_recharge() use_power(250) using_power = TRUE diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 1532eeaccbd..c15aed3b757 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -203,6 +203,7 @@ if(D.power_supply.charge < D.power_supply.maxcharge) var/obj/item/ammo_casing/energy/E = D.ammo_type[D.select] D.power_supply.give(E.e_cost) + D.on_recharge() D.update_icon() else D.charge_tick = 0 diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index cf7937474c8..dd5772149a0 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -1191,7 +1191,7 @@ product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!" product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!" icon_state = "seeds" - products = list(/obj/item/seeds/aloe =3, /obj/item/seeds/ambrosia = 3, /obj/item/seeds/apple = 3, /obj/item/seeds/banana = 3, /obj/item/seeds/berry = 3, + products = list(/obj/item/seeds/aloe =3, /obj/item/seeds/ambrosia = 3, /obj/item/seeds/apple = 3, /obj/item/seeds/cotton = 3, /obj/item/seeds/banana = 3, /obj/item/seeds/berry = 3, /obj/item/seeds/cabbage = 3, /obj/item/seeds/carrot = 3, /obj/item/seeds/cherry = 3, /obj/item/seeds/chanter = 3, /obj/item/seeds/chili = 3, /obj/item/seeds/cocoapod = 3, /obj/item/seeds/coffee = 3, /obj/item/seeds/comfrey =3, /obj/item/seeds/corn = 3, /obj/item/seeds/nymph =3, /obj/item/seeds/eggplant = 3, /obj/item/seeds/grape = 3, /obj/item/seeds/grass = 3, /obj/item/seeds/lemon = 3, @@ -1355,7 +1355,7 @@ desc = "Spare tool vending. What? Did you expect some witty description?" icon_state = "engivend" icon_deny = "engivend-deny" - req_access_txt = "11" //Engineering Equipment access + req_one_access_txt = "11;24" // Engineers and atmos techs can use this products = list(/obj/item/clothing/glasses/meson = 2,/obj/item/multitool = 4,/obj/item/airlock_electronics = 10,/obj/item/firelock_electronics = 10,/obj/item/firealarm_electronics = 10,/obj/item/apc_electronics = 10,/obj/item/airalarm_electronics = 10,/obj/item/stock_parts/cell/high = 10,/obj/item/camera_assembly = 10) contraband = list(/obj/item/stock_parts/cell/potato = 3) premium = list(/obj/item/storage/belt/utility = 3) @@ -1470,24 +1470,90 @@ product_slogans = "Dress for success!;Prepare to look swagalicious!;Look at all this free swag!;Why leave style up to fate? Use the ClothesMate!" vend_delay = 15 vend_reply = "Thank you for using the ClothesMate!" - products = list(/obj/item/clothing/head/that=2,/obj/item/clothing/head/fedora=1,/obj/item/clothing/glasses/monocle=1, - /obj/item/clothing/under/suit_jacket/navy=2,/obj/item/clothing/under/kilt=1,/obj/item/clothing/under/overalls=1, - /obj/item/clothing/under/suit_jacket/really_black=2,/obj/item/clothing/suit/storage/lawyer/blackjacket=2,/obj/item/clothing/under/pants/jeans=3,/obj/item/clothing/under/pants/classicjeans=2, - /obj/item/clothing/under/pants/camo = 1,/obj/item/clothing/under/pants/blackjeans=2,/obj/item/clothing/under/pants/khaki=2, - /obj/item/clothing/under/pants/white=2,/obj/item/clothing/under/pants/red=1,/obj/item/clothing/under/pants/black=2, - /obj/item/clothing/under/pants/tan=2,/obj/item/clothing/under/pants/blue=1,/obj/item/clothing/under/pants/track=1,/obj/item/clothing/suit/jacket/miljacket = 1, - /obj/item/clothing/accessory/scarf/red=1,/obj/item/clothing/accessory/scarf/green=1,/obj/item/clothing/accessory/scarf/darkblue=1, - /obj/item/clothing/accessory/scarf/purple=1,/obj/item/clothing/accessory/scarf/yellow=1,/obj/item/clothing/accessory/scarf/orange=1, - /obj/item/clothing/accessory/scarf/lightblue=1,/obj/item/clothing/accessory/scarf/white=1,/obj/item/clothing/accessory/scarf/black=1, - /obj/item/clothing/accessory/scarf/zebra=1,/obj/item/clothing/accessory/scarf/christmas=1,/obj/item/clothing/accessory/stripedredscarf=1, - /obj/item/clothing/accessory/stripedbluescarf=1,/obj/item/clothing/accessory/stripedgreenscarf=1,/obj/item/clothing/accessory/waistcoat=1, - /obj/item/clothing/under/sundress=2,/obj/item/clothing/under/stripeddress = 1, /obj/item/clothing/under/sailordress = 1, /obj/item/clothing/under/redeveninggown = 1, /obj/item/clothing/under/blacktango=1,/obj/item/clothing/suit/jacket=3, - /obj/item/clothing/glasses/regular=2,/obj/item/clothing/glasses/sunglasses/fake=2,/obj/item/clothing/head/sombrero=1,/obj/item/clothing/suit/poncho=1, - /obj/item/clothing/suit/ianshirt=1,/obj/item/clothing/shoes/laceup=2,/obj/item/clothing/shoes/black=4, - /obj/item/clothing/shoes/sandal=1, /obj/item/clothing/gloves/fingerless=2, - /obj/item/storage/belt/fannypack=1, /obj/item/storage/belt/fannypack/blue=1, /obj/item/storage/belt/fannypack/red=1, /obj/item/clothing/suit/mantle = 2, /obj/item/clothing/suit/mantle/old = 1, /obj/item/clothing/suit/mantle/regal = 2) - contraband = list(/obj/item/clothing/under/syndicate/tacticool=1,/obj/item/clothing/mask/balaclava=1,/obj/item/clothing/head/ushanka=1,/obj/item/clothing/under/soviet=1,/obj/item/storage/belt/fannypack/black=1) - premium = list(/obj/item/clothing/under/suit_jacket/checkered=1,/obj/item/clothing/head/mailman=1,/obj/item/clothing/under/rank/mailman=1,/obj/item/clothing/suit/jacket/leather=1,/obj/item/clothing/under/pants/mustangjeans=1) + products = list(/obj/item/clothing/head/that = 2, + /obj/item/clothing/head/fedora = 1, + /obj/item/clothing/glasses/monocle = 1, + /obj/item/clothing/under/suit_jacket/navy = 2, + /obj/item/clothing/under/kilt = 1, + /obj/item/clothing/under/overalls = 1, + /obj/item/clothing/under/suit_jacket/really_black = 2, + /obj/item/clothing/suit/storage/lawyer/blackjacket = 2, + /obj/item/clothing/under/pants/jeans = 3, + /obj/item/clothing/under/pants/classicjeans = 2, + /obj/item/clothing/under/pants/camo = 1, + /obj/item/clothing/under/pants/blackjeans = 2, + /obj/item/clothing/under/pants/khaki = 2, + /obj/item/clothing/under/pants/white = 2, + /obj/item/clothing/under/pants/red = 1, + /obj/item/clothing/under/pants/black = 2, + /obj/item/clothing/under/pants/tan = 2, + /obj/item/clothing/under/pants/blue = 1, + /obj/item/clothing/under/pants/track = 1, + /obj/item/clothing/suit/jacket/miljacket = 1, + /obj/item/clothing/head/beanie = 3, + /obj/item/clothing/head/beanie/black = 3, + /obj/item/clothing/head/beanie/red = 3, + /obj/item/clothing/head/beanie/green = 3, + /obj/item/clothing/head/beanie/darkblue = 3, + /obj/item/clothing/head/beanie/purple = 3, + /obj/item/clothing/head/beanie/yellow = 3, + /obj/item/clothing/head/beanie/orange = 3, + /obj/item/clothing/head/beanie/cyan = 3, + /obj/item/clothing/head/beanie/christmas = 3, + /obj/item/clothing/head/beanie/striped = 3, + /obj/item/clothing/head/beanie/stripedred = 3, + /obj/item/clothing/head/beanie/stripedblue = 3, + /obj/item/clothing/head/beanie/stripedgreen = 3, + /obj/item/clothing/head/beanie/rasta = 3, + /obj/item/clothing/accessory/scarf/red = 1, + /obj/item/clothing/accessory/scarf/green = 1, + /obj/item/clothing/accessory/scarf/darkblue = 1, + /obj/item/clothing/accessory/scarf/purple = 1, + /obj/item/clothing/accessory/scarf/yellow = 1, + /obj/item/clothing/accessory/scarf/orange = 1, + /obj/item/clothing/accessory/scarf/lightblue = 1, + /obj/item/clothing/accessory/scarf/white = 1, + /obj/item/clothing/accessory/scarf/black = 1, + /obj/item/clothing/accessory/scarf/zebra = 1, + /obj/item/clothing/accessory/scarf/christmas = 1, + /obj/item/clothing/accessory/stripedredscarf = 1, + /obj/item/clothing/accessory/stripedbluescarf = 1, + /obj/item/clothing/accessory/stripedgreenscarf = 1, + /obj/item/clothing/accessory/waistcoat = 1, + /obj/item/clothing/under/sundress = 2, + /obj/item/clothing/under/stripeddress = 1, + /obj/item/clothing/under/sailordress = 1, + /obj/item/clothing/under/redeveninggown = 1, + /obj/item/clothing/under/blacktango = 1, + /obj/item/clothing/suit/jacket = 3, + /obj/item/clothing/glasses/regular = 2, + /obj/item/clothing/glasses/sunglasses_fake = 2, + /obj/item/clothing/head/sombrero = 1, + /obj/item/clothing/suit/poncho = 1, + /obj/item/clothing/suit/ianshirt = 1, + /obj/item/clothing/shoes/laceup = 2, + /obj/item/clothing/shoes/black = 4, + /obj/item/clothing/shoes/sandal = 1, + /obj/item/clothing/gloves/fingerless = 2, + /obj/item/storage/belt/fannypack = 1, + /obj/item/storage/belt/fannypack/blue = 1, + /obj/item/storage/belt/fannypack/red = 1, + /obj/item/clothing/suit/mantle = 2, + /obj/item/clothing/suit/mantle/old = 1, + /obj/item/clothing/suit/mantle/regal = 2) + + contraband = list(/obj/item/clothing/under/syndicate/tacticool = 1, + /obj/item/clothing/mask/balaclava = 1, + /obj/item/clothing/head/ushanka = 1, + /obj/item/clothing/under/soviet = 1, + /obj/item/storage/belt/fannypack/black = 1) + + premium = list(/obj/item/clothing/under/suit_jacket/checkered = 1, + /obj/item/clothing/head/mailman = 1, + /obj/item/clothing/under/rank/mailman = 1, + /obj/item/clothing/suit/jacket/leather = 1, + /obj/item/clothing/under/pants/mustangjeans = 1) + refill_canister = /obj/item/vending_refill/clothing /obj/machinery/vending/clothing/New() diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index d9210f66e8b..d282e1264e2 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -11,6 +11,7 @@ var/global/list/image/splatter_cache = list() density = FALSE anchored = TRUE layer = TURF_LAYER + plane = GAME_PLANE icon = 'icons/effects/blood.dmi' icon_state = "mfloor1" random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7") diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm index 893250bf862..349b8039d92 100644 --- a/code/game/objects/effects/decals/Cleanable/misc.dm +++ b/code/game/objects/effects/decals/Cleanable/misc.dm @@ -175,6 +175,7 @@ density = FALSE anchored = TRUE layer = TURF_LAYER + plane = GAME_PLANE icon = 'icons/effects/effects.dmi' icon_state = "flour" color = "#D5820B" diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index 566c84a081c..06243b1db8a 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -4,6 +4,7 @@ icon = 'icons/effects/crayondecal.dmi' icon_state = "rune1" layer = MID_TURF_LAYER + plane = GAME_PLANE //makes the graffiti visible over a wall. anchored = TRUE diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index 8bb117b832c..a145fcea1d4 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -79,7 +79,7 @@ would spawn and follow the beaker, even if it is carried or thrown. reagents.reaction(A) if(istype(A,/atom/movable)) var/atom/movable/AM = A - AM.water_act(life, 310.15, src) + AM.water_act(life, COLD_WATER_TEMPERATURE, src) return ..() diff --git a/code/game/objects/effects/effect_system/effects_water.dm b/code/game/objects/effects/effect_system/effects_water.dm index c4009516f92..12fc9732bb5 100644 --- a/code/game/objects/effects/effect_system/effects_water.dm +++ b/code/game/objects/effects/effect_system/effects_water.dm @@ -21,7 +21,7 @@ reagents.reaction(A) if(istype(A,/atom/movable)) var/atom/movable/AM = A - AM.water_act(life, 310.15, src) + AM.water_act(life, COLD_WATER_TEMPERATURE, src) return ..() ///////////////////////////////////////////// diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 0e95f509463..d021c0254a8 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -123,6 +123,19 @@ origin_tech = "biotech=2" stop_bleeding = 1800 +/obj/item/stack/medical/bruise_pack/attackby(obj/item/I, mob/user, params) + if(I.sharp) + if(get_amount() < 2) + to_chat(user, "You need at least two gauzes to do this!") + return + new /obj/item/stack/sheet/cloth(user.drop_location()) + user.visible_message("[user] cuts [src] into pieces of cloth with [I].", \ + "You cut [src] into pieces of cloth with [I].", \ + "You hear cutting.") + use(2) + else + return ..() + /obj/item/stack/medical/bruise_pack/attack(mob/living/M, mob/user) if(..()) return 1 @@ -145,6 +158,11 @@ else to_chat(user, "[affecting] is cut open, you'll need more than a bandage!") +/obj/item/stack/medical/bruise_pack/improvised + name = "improvised gauze" + singular_name = "improvised gauze" + desc = "A roll of cloth roughly cut from something that can stop bleeding, but does not heal wounds." + stop_bleeding = 900 /obj/item/stack/medical/bruise_pack/advanced name = "advanced trauma kit" diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 8c60bcefa11..c9099d6d38b 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -137,6 +137,44 @@ var/global/list/datum/stack_recipe/snow_recipes = list( ..() recipes = sandstone_recipes +/* + * Sandbags + */ + +/obj/item/stack/sheet/mineral/sandbags + name = "sandbags" + icon_state = "sandbags" + singular_name = "sandbag" + layer = LOW_ITEM_LAYER + merge_type = /obj/item/stack/sheet/mineral/sandbags + +GLOBAL_LIST_INIT(sandbag_recipes, list ( \ + new/datum/stack_recipe("sandbags", /obj/structure/barricade/sandbags, 1, time = 25, one_per_turf = 1, on_floor = 1), \ + )) + +/obj/item/stack/sheet/mineral/sandbags/New() + recipes = GLOB.sandbag_recipes + ..() + +/obj/item/emptysandbag + name = "empty sandbag" + desc = "A bag to be filled with sand." + icon = 'icons/obj/items.dmi' + icon_state = "sandbag" + w_class = WEIGHT_CLASS_TINY + +/obj/item/emptysandbag/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/stack/ore/glass)) + var/obj/item/stack/ore/glass/G = I + to_chat(user, "You fill the sandbag.") + var/obj/item/stack/sheet/mineral/sandbags/S = new /obj/item/stack/sheet/mineral/sandbags(drop_location()) + qdel(src) + if(Adjacent(user) && !issilicon(user)) + user.put_in_hands(S) + G.use(1) + else + return ..() + /obj/item/stack/sheet/mineral/diamond name = "diamond" icon_state = "sheet-diamond" diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index f7df69cad2f..8698a4a2bbe 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -182,6 +182,7 @@ var/global/list/datum/stack_recipe/wood_recipes = list( new /datum/stack_recipe("rake", /obj/item/cultivator/rake, 5, time = 10), new /datum/stack_recipe("ore box", /obj/structure/ore_box, 4, time = 50, one_per_turf = TRUE, on_floor = TRUE), new /datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15), + new /datum/stack_recipe("loom", /obj/structure/loom, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \ new /datum/stack_recipe("fermenting barrel", /obj/structure/fermenting_barrel, 30, time = 50), new /datum/stack_recipe("firebrand", /obj/item/match/firebrand, 2, time = 100) ) @@ -204,8 +205,9 @@ var/global/list/datum/stack_recipe/wood_recipes = list( * Cloth */ var/global/list/datum/stack_recipe/cloth_recipes = list ( \ - new/datum/stack_recipe("grey jumpsuit", /obj/item/clothing/under/color/grey, 3), \ - new/datum/stack_recipe("black shoes", /obj/item/clothing/shoes/black, 2), \ + new/datum/stack_recipe("white jumpsuit", /obj/item/clothing/under/color/white, 3), \ + new/datum/stack_recipe("white shoes", /obj/item/clothing/shoes/white, 2), \ + new/datum/stack_recipe("white scarf", /obj/item/clothing/accessory/scarf/white, 1), \ null, \ new/datum/stack_recipe("backpack", /obj/item/storage/backpack, 4), \ new/datum/stack_recipe("dufflebag", /obj/item/storage/backpack/duffel, 6), \ @@ -216,11 +218,15 @@ var/global/list/datum/stack_recipe/cloth_recipes = list ( \ new/datum/stack_recipe("chemistry bag", /obj/item/storage/bag/chemistry, 4), \ new/datum/stack_recipe("bio bag", /obj/item/storage/bag/bio, 4), \ null, \ + new/datum/stack_recipe("improvised gauze", /obj/item/stack/medical/bruise_pack/improvised, 1, 2, 6), \ new/datum/stack_recipe("rag", /obj/item/reagent_containers/glass/rag, 1), \ new/datum/stack_recipe("bedsheet", /obj/item/bedsheet, 3), \ + new/datum/stack_recipe("empty sandbag", /obj/item/emptysandbag, 4), \ null, \ new/datum/stack_recipe("fingerless gloves", /obj/item/clothing/gloves/fingerless, 1), \ - new/datum/stack_recipe("black gloves", /obj/item/clothing/gloves/color/black, 3), \ + new/datum/stack_recipe("white gloves", /obj/item/clothing/gloves/color/white, 3), \ + new/datum/stack_recipe("white softcap", /obj/item/clothing/head/soft/mime, 2), \ + new/datum/stack_recipe("white beanie", /obj/item/clothing/head/beanie, 2), \ null, \ new/datum/stack_recipe("blindfold", /obj/item/clothing/glasses/sunglasses/blindfold, 3), \ ) @@ -243,6 +249,49 @@ var/global/list/datum/stack_recipe/cloth_recipes = list ( \ /obj/item/stack/sheet/cloth/ten amount = 10 +GLOBAL_LIST_INIT(durathread_recipes, list ( \ + new/datum/stack_recipe("durathread jumpsuit", /obj/item/clothing/under/misc/durathread, 4, time = 40), + new/datum/stack_recipe("durathread beret", /obj/item/clothing/head/beret/durathread, 2, time = 40), \ + new/datum/stack_recipe("durathread beanie", /obj/item/clothing/head/beanie/durathread, 2, time = 40), \ + new/datum/stack_recipe("durathread bandana", /obj/item/clothing/mask/bandana/durathread, 1, time = 25), \ + )) + +/obj/item/stack/sheet/durathread + name = "durathread" + desc = "A fabric sown from incredibly durable threads, known for its usefulness in armor production." + singular_name = "durathread roll" + icon_state = "sheet-durathread" + item_state = "sheet-cloth" + resistance_flags = FLAMMABLE + force = 0 + throwforce = 0 + merge_type = /obj/item/stack/sheet/durathread + +/obj/item/stack/sheet/durathread/Initialize(mapload, new_amount, merge = TRUE) + recipes = GLOB.durathread_recipes + return ..() + +/obj/item/stack/sheet/cotton + name = "raw cotton bundle" + desc = "A bundle of raw cotton ready to be spun on the loom." + singular_name = "raw cotton ball" + icon_state = "sheet-cotton" + resistance_flags = FLAMMABLE + force = 0 + throwforce = 0 + merge_type = /obj/item/stack/sheet/cotton + var/pull_effort = 30 + var/loom_result = /obj/item/stack/sheet/cloth + +/obj/item/stack/sheet/cotton/durathread + name = "raw durathread bundle" + desc = "A bundle of raw durathread ready to be spun on the loom." + singular_name = "raw durathread ball" + icon_state = "sheet-durathreadraw" + merge_type = /obj/item/stack/sheet/cotton/durathread + pull_effort = 70 + loom_result = /obj/item/stack/sheet/durathread + /* * Cardboard */ diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 6fb552654d9..d4e1ed2d7f1 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -1059,6 +1059,15 @@ desc = "A colorful cardboard box for the clown" icon_state = "box_clown" +/obj/item/storage/box/emptysandbags + name = "box of empty sandbags" + +/obj/item/storage/box/emptysandbags/New() + ..() + contents = list() + for(var/i in 1 to 7) + new /obj/item/emptysandbag(src) + /obj/item/storage/box/rndboards name = "the Liberator's legacy" desc = "A box containing a gift for worthy golems." diff --git a/code/game/objects/items/weapons/tanks/jetpack.dm b/code/game/objects/items/weapons/tanks/jetpack.dm index 72394db2733..21f43073b73 100644 --- a/code/game/objects/items/weapons/tanks/jetpack.dm +++ b/code/game/objects/items/weapons/tanks/jetpack.dm @@ -48,38 +48,38 @@ return if(!on) - turn_on() + turn_on(user) to_chat(user, "You turn the jetpack on.") else - turn_off() + turn_off(user) to_chat(user, "You turn the jetpack off.") for(var/X in actions) var/datum/action/A = X A.UpdateButtonIcon() -/obj/item/tank/jetpack/proc/turn_on() +/obj/item/tank/jetpack/proc/turn_on(mob/user) on = TRUE icon_state = "[initial(icon_state)]-on" ion_trail.start() -/obj/item/tank/jetpack/proc/turn_off() +/obj/item/tank/jetpack/proc/turn_off(mob/user) on = FALSE stabilizers = FALSE icon_state = initial(icon_state) ion_trail.stop() -/obj/item/tank/jetpack/proc/allow_thrust(num, mob/living/user as mob) +/obj/item/tank/jetpack/proc/allow_thrust(num, mob/living/user) if(!on) return 0 if((num < 0.005 || air_contents.total_moles() < num)) - turn_off() + turn_off(user) return 0 var/datum/gas_mixture/removed = air_contents.remove(num) if(removed.total_moles() < 0.005) - turn_off() + turn_off(user) return 0 var/turf/T = get_turf(user) @@ -163,15 +163,65 @@ to_chat(user, "The meter on [src] indicates you are almost out of air!") playsound(user, 'sound/effects/alert.ogg', 50, 1) -/obj/item/tank/jetpack/carbondioxide/mining - name = "mining jetpack" +/obj/item/tank/jetpack/suit + name = "hardsuit jetpack upgrade" + desc = "A modular, compact set of thrusters designed to integrate with a hardsuit. It is fueled by a tank inserted into the suit's storage compartment." icon_state = "jetpack-mining" - item_state = "jetpack-mining" + item_state = "jetpack-black" origin_tech = "materials=4;magnets=4;engineering=5" - desc = "A tank of compressed carbon dioxide for miners to use as propulsion in local space. The compact size allows for easy storage at the cost of capacity." - volume = 40 - throw_range = 7 - w_class = WEIGHT_CLASS_NORMAL //same as syndie harness + w_class = WEIGHT_CLASS_NORMAL + actions_types = list(/datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization) + volume = 1 + slot_flags = null + var/datum/gas_mixture/temp_air_contents + var/obj/item/tank/tank = null + var/mob/living/carbon/human/cur_user + +/obj/item/tank/jetpack/suit/New() + ..() + STOP_PROCESSING(SSobj, src) + temp_air_contents = air_contents + +/obj/item/tank/jetpack/suit/attack_self() + return + +/obj/item/tank/jetpack/suit/cycle(mob/user) + if(!istype(loc, /obj/item/clothing/suit/space/hardsuit)) + to_chat(user, "[src] must be connected to a hardsuit!") + return + + var/mob/living/carbon/human/H = user + if(!istype(H.s_store, /obj/item/tank)) + to_chat(user, "You need a tank in your suit storage!") + return + ..() + +/obj/item/tank/jetpack/suit/turn_on(mob/user) + if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc) || loc.loc != user) + return + var/mob/living/carbon/human/H = user + tank = H.s_store + air_contents = tank.air_contents + START_PROCESSING(SSobj, src) + cur_user = user + ..() + +/obj/item/tank/jetpack/suit/turn_off(mob/user) + tank = null + air_contents = temp_air_contents + STOP_PROCESSING(SSobj, src) + cur_user = null + ..() + +/obj/item/tank/jetpack/suit/process() + if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc)) + turn_off(cur_user) + return + var/mob/living/carbon/human/H = loc.loc + if(!tank || tank != H.s_store) + turn_off(cur_user) + return + ..() /obj/item/tank/jetpack/rig name = "jetpack" @@ -182,7 +232,7 @@ to_chat(usr, "It's a jetpack. If you can see this, report it on the bug tracker.") return 0 -/obj/item/tank/jetpack/rig/allow_thrust(num, mob/living/user as mob) +/obj/item/tank/jetpack/rig/allow_thrust(num, mob/living/user) if(!on) return 0 @@ -191,7 +241,7 @@ var/datum/gas_mixture/removed = holder.air_supply.air_contents.remove(num) if(removed.total_moles() < 0.005) - turn_off() + turn_off(user) return 0 var/turf/T = get_turf(user) diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index f42decd4363..501f1780a0b 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -181,16 +181,16 @@ if(prob(10)) visible_message("[owner] Deflects [I] directly back at the thrower! It's a home run!", "You deflect the [I] directly back at the thrower! It's a home run!") playsound(get_turf(owner), 'sound/weapons/homerun.ogg', 100, 1) - do_attack_animation(I, ATTACK_EFFECT_DISARM) + do_attack_animation(I, ATTACK_EFFECT_DISARM) I.throw_at(I.thrownby, 20, 20, owner) deflectmode = FALSE if(!istype(I, /obj/item/beach_ball)) lastdeflect = world.time + 3000 - return TRUE + return TRUE else if(prob(30)) visible_message("[owner] swings! And [p_they()] miss[p_es()]! How embarassing.", "You swing! You miss! Oh no!") playsound(get_turf(owner), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - do_attack_animation(get_step(owner, pick(alldirs)), ATTACK_EFFECT_DISARM) + do_attack_animation(get_step(owner, pick(alldirs)), ATTACK_EFFECT_DISARM) deflectmode = FALSE if(!istype(I, /obj/item/beach_ball)) lastdeflect = world.time + 3000 @@ -198,7 +198,7 @@ else visible_message("[owner] swings and deflects [I]!", "You swing and deflect the [I]!") playsound(get_turf(owner), 'sound/weapons/baseball_hit.ogg', 50, 1, -1) - do_attack_animation(I, ATTACK_EFFECT_DISARM) + do_attack_animation(I, ATTACK_EFFECT_DISARM) I.throw_at(get_edge_target_turf(owner, pick(cardinal)), rand(8,10), 14, owner) deflectmode = FALSE if(!istype(I, /obj/item/beach_ball)) @@ -239,7 +239,7 @@ playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, 1) homerun_ready = 0 return - else + else if(!target.anchored) target.throw_at(throw_target, rand(1,2), 7, user) /obj/item/melee/baseball_bat/ablative diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 43f45647985..d7900d82e38 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -34,6 +34,15 @@ LINEN BINS add_fingerprint(user) return +/obj/item/bedsheet/attackby(obj/item/I, mob/user, params) + if(I.sharp) + var/obj/item/stack/sheet/cloth/C = new (get_turf(src), 3) + transfer_fingerprints_to(C) + C.add_fingerprint(user) + qdel(src) + to_chat(user, "You tear [src] up.") + else + return ..() /obj/item/bedsheet/blue icon_state = "sheetblue" diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 2037293d734..dba81195e6e 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -105,7 +105,7 @@ continue if(istype(M, /mob/living/simple_animal/bot/mulebot)) continue - if(M.buckled) + if(M.buckled || M.anchored) continue M.forceMove(src) diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm index 19e08c15bde..f642960e52e 100644 --- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm +++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm @@ -15,15 +15,19 @@ var/move_delay = 0 var/egged = 0 -/obj/structure/closet/cardboard/relaymove(mob/user, direction) - if(opened || move_delay || user.stat || user.stunned || user.weakened || user.paralysis || !isturf(loc) || !has_gravity(loc)) +/obj/structure/closet/cardboard/relaymove(mob/living/user, direction) + if(!istype(user) || opened || move_delay || user.incapacitated() || !isturf(loc) || !has_gravity(loc)) return - move_delay = 1 - if(step(src, direction)) - spawn(config.walk_speed) - move_delay = 0 + move_delay = TRUE + var/oldloc = loc + step(src, direction) + if(oldloc != loc) + addtimer(CALLBACK(src, .proc/ResetMoveDelay), config.walk_speed) else - move_delay = 0 + move_delay = FALSE + +/obj/structure/closet/cardboard/proc/ResetMoveDelay() + move_delay = FALSE /obj/structure/closet/cardboard/open() if(opened || !can_open()) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index 0cd6e541398..0608eb64cbb 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -25,6 +25,7 @@ new /obj/item/clothing/glasses/welding/superior(src) new /obj/item/clothing/gloves/color/yellow(src) new /obj/item/clothing/shoes/brown(src) + new /obj/item/tank/jetpack/suit(src) new /obj/item/cartridge/ce(src) new /obj/item/radio/headset/heads/ce(src) new /obj/item/storage/toolbox/mechanical(src) @@ -147,3 +148,4 @@ new /obj/item/clothing/suit/fire/atmos(src) new /obj/item/clothing/head/hardhat/atmos(src) new /obj/item/rpd(src) + new /obj/item/destTagger(src) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index fe6b0082207..2501c32c2a6 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -251,7 +251,7 @@ new /obj/item/melee/baton/loaded(src) new /obj/item/clothing/glasses/sunglasses(src) new /obj/item/clothing/glasses/hud/security/sunglasses/read_only(src) - new /obj/item/clothing/glasses/hud/health/health_advanced + new /obj/item/clothing/glasses/hud/health/sunglasses new /obj/item/clothing/head/beret/centcom/officer(src) new /obj/item/clothing/head/beret/centcom/officer/navy(src) new /obj/item/clothing/suit/armor/vest/blueshield(src) diff --git a/code/game/objects/structures/ladders.dm b/code/game/objects/structures/ladders.dm index 97bd986ceb9..14ee2765d02 100644 --- a/code/game/objects/structures/ladders.dm +++ b/code/game/objects/structures/ladders.dm @@ -1,33 +1,59 @@ +// Basic ladder. By default links to the z-level above/below. /obj/structure/ladder name = "ladder" desc = "A sturdy metal ladder." icon = 'icons/obj/structures.dmi' icon_state = "ladder11" - anchored = 1 - var/id = null - var/height = 0 //the 'height' of the ladder. higher numbers are considered physically higher - var/obj/structure/ladder/down = null //the ladder below this one - var/obj/structure/ladder/up = null //the ladder above this one - var/use_verb = "climbs" + anchored = TRUE + var/obj/structure/ladder/down //the ladder below this one + var/obj/structure/ladder/up //the ladder above this one + var/use_verb = "climb" -/obj/structure/ladder/New() - spawn(8) - for(var/obj/structure/ladder/L in world) - if(L.id == id) - if(L.height == (height - 1)) - down = L - if(isnull(L.up)) - L.up = src - continue - if(L.height == (height + 1)) - up = L - if(isnull(L.down)) - L.down = src - continue +/obj/structure/ladder/Initialize(mapload, obj/structure/ladder/up, obj/structure/ladder/down) + . = ..() + if (up) + src.up = up + up.down = src + up.update_icon() + if (down) + src.down = down + down.up = src + down.update_icon() + return INITIALIZE_HINT_LATELOAD - if(up && down) //if both our connections are filled - break - update_icon() +/obj/structure/ladder/Destroy(force) + if((resistance_flags & INDESTRUCTIBLE) && !force) + return QDEL_HINT_LETMELIVE + disconnect() + return ..() + +/obj/structure/ladder/LateInitialize() + // By default, discover ladders above and below us vertically + var/turf/T = get_turf(src) + + if(!down) + for(var/obj/structure/ladder/L in locate(T.x, T.y, T.z - 1)) + down = L + L.up = src // Don't waste effort looping the other way + L.update_icon() + break + if(!up) + for (var/obj/structure/ladder/L in locate(T.x, T.y, T.z + 1)) + up = L + L.down = src // Don't waste effort looping the other way + L.update_icon() + break + + update_icon() + +/obj/structure/ladder/proc/disconnect() + if(up && up.down == src) + up.down = null + up.update_icon() + if(down && down.up == src) + down.up = null + down.update_icon() + up = down = null /obj/structure/ladder/update_icon() if(up && down) @@ -42,61 +68,134 @@ else //wtf make your ladders properly assholes icon_state = "ladder00" -/obj/structure/ladder/attack_hand(mob/user as mob) +/obj/structure/ladder/singularity_pull() + if(!(resistance_flags & INDESTRUCTIBLE)) + visible_message("[src] is torn to pieces by the gravitational pull!") + qdel(src) + +/obj/structure/ladder/proc/travel(going_up, mob/user, is_ghost, obj/structure/ladder/ladder) + if(!is_ghost) + show_fluff_message(going_up, user) + ladder.add_fingerprint(user) + + var/turf/T = get_turf(ladder) + var/atom/movable/AM + if(user.pulling) + AM = user.pulling + AM.forceMove(T) + user.forceMove(T) + if(AM) + user.start_pulling(AM) + +/obj/structure/ladder/proc/use(mob/user, is_ghost = FALSE) + if(!is_ghost && !in_range(src, user)) + return + if(up && down) - switch( alert("Go up or down the ladder?", "Ladder", "Up", "Down", "Cancel") ) + var/result = alert("Go up or down [src]?", "[name]", "Up", "Down", "Cancel") + if (!is_ghost && !in_range(src, user)) + return // nice try + switch(result) if("Up") - user.visible_message("[user] climbs up \the [src]!", \ - "You climb up \the [src]!") - user.forceMove(get_turf(up)) - up.add_fingerprint(user) + travel(TRUE, user, is_ghost, up) if("Down") - user.visible_message("[user] climbs down \the [src]!", \ - "You climb down \the [src]!") - user.forceMove(get_turf(down)) - down.add_fingerprint(user) + travel(FALSE, user, is_ghost, down) if("Cancel") return - else if(up) - user.visible_message("[user] climbs up \the [src]!", \ - "You climb up \the [src]!") - user.forceMove(get_turf(up)) - up.add_fingerprint(user) - + travel(TRUE, user, is_ghost, up) else if(down) - user.visible_message("[user] climbs down \the [src]!", \ - "You climb down \the [src]!") - user.forceMove(get_turf(down)) - down.add_fingerprint(user) + travel(FALSE, user, is_ghost, down) + else + to_chat(user, "[src] doesn't seem to lead anywhere!") - add_fingerprint(user) + if(!is_ghost) + add_fingerprint(user) -/obj/structure/ladder/attackby(obj/item/W, mob/user as mob, params) - return attack_hand(user) +/obj/structure/ladder/attack_hand(mob/user) + use(user) -/obj/structure/ladder/dive_point/buoy +/obj/structure/ladder/attackby(obj/item/W, mob/user, params) + return use(user) + +/obj/structure/ladder/attack_robot(mob/living/silicon/robot/R) + if(R.Adjacent(src)) + return use(R) + +//ATTACK GHOST IGNORING PARENT RETURN VALUE +/obj/structure/ladder/attack_ghost(mob/dead/observer/user) + use(user, TRUE) + +/obj/structure/ladder/proc/show_fluff_message(going_up, mob/user) + if(going_up) + user.visible_message("[user] climbs up [src].","You [use_verb] up [src].") + else + user.visible_message("[user] climbs down [src].","You [use_verb] down [src].") + + +// Indestructible away mission ladders which link based on a mapped ID and height value rather than X/Y/Z. +/obj/structure/ladder/unbreakable + name = "sturdy ladder" + desc = "An extremely sturdy metal ladder." + resistance_flags = INDESTRUCTIBLE + var/id + var/height = 0 // higher numbers are considered physically higher + +/obj/structure/ladder/unbreakable/Initialize(mapload) + GLOB.ladders += src + return ..() + +/obj/structure/ladder/unbreakable/Destroy() + . = ..() + if(. != QDEL_HINT_LETMELIVE) + GLOB.ladders -= src + +/obj/structure/ladder/unbreakable/LateInitialize() + // Override the parent to find ladders based on being height-linked + if(!id || (up && down)) + update_icon() + return + + for(var/O in GLOB.ladders) + var/obj/structure/ladder/unbreakable/L = O + if(L.id != id) + continue // not one of our pals + if(!down && L.height == height - 1) + down = L + L.up = src + L.update_icon() + if (up) + break // break if both our connections are filled + else if(!up && L.height == height + 1) + up = L + L.down = src + L.update_icon() + if (down) + break // break if both our connections are filled + + update_icon() + +/obj/structure/ladder/unbreakable/dive_point/buoy name = "diving point buoy" desc = "A buoy marking the location of an underwater dive area." icon = 'icons/misc/beach.dmi' icon_state = "buoy" id = "dive" height = 2 - use_verb = "dives" + use_verb = "swim" layer = MOB_LAYER + 0.2 //0.1 higher than the water overlay, this also means people can "swim" behind/under it -/obj/structure/ladder/dive_point/anchor +/obj/structure/ladder/unbreakable/dive_point/anchor name = "diving point anchor" desc = "An anchor tethered to the buoy at the surface, to keep the dive area marked." icon = 'icons/misc/beach.dmi' icon_state = "anchor" id = "dive" height = 1 - use_verb = "ascends" light_range = 5 -/obj/structure/ladder/dive_point/New() - ..() +/obj/structure/ladder/dive_point/Initialize(mapload) + . = ..() set_light(light_range, light_power) //magical glowing anchor /obj/structure/ladder/dive_point/update_icon() diff --git a/code/game/objects/structures/loom.dm b/code/game/objects/structures/loom.dm new file mode 100644 index 00000000000..26bd4136c2a --- /dev/null +++ b/code/game/objects/structures/loom.dm @@ -0,0 +1,38 @@ +#define FABRIC_PER_SHEET 4 + + +///This is a loom. It's usually made out of wood and used to weave fabric like durathread or cotton into their respective cloth types. +/obj/structure/loom + name = "loom" + desc = "A simple device used to weave cloth and other thread-based fabrics together into usable material." + icon = 'icons/obj/hydroponics/equipment.dmi' + icon_state = "loom" + density = TRUE + anchored = TRUE + +/obj/structure/loom/attackby(obj/item/I, mob/user) + if(default_unfasten_wrench(user, I, 5)) + return + if(weave(I, user)) + return + return ..() + +///Handles the weaving. +/obj/structure/loom/proc/weave(obj/item/stack/sheet/cotton/W, mob/user) + if(!istype(W)) + return FALSE + if(!anchored) + user.show_message("The loom needs to be wrenched down.", 1) + return FALSE + if(W.amount < FABRIC_PER_SHEET) + user.show_message("You need at least [FABRIC_PER_SHEET] units of fabric before using this.", 1) + return FALSE + user.show_message("You start weaving \the [W.name] through the loom..", 1) + if(do_after(user, W.pull_effort, target = src)) + if(W.amount >= FABRIC_PER_SHEET) + new W.loom_result(drop_location()) + W.use(FABRIC_PER_SHEET) + user.show_message("You weave \the [W.name] into a workable fabric.", 1) + return TRUE + +#undef FABRIC_PER_SHEET \ No newline at end of file diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index ada70921c99..0958f3cc0e0 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -600,7 +600,7 @@ wateract = (W.wash(user, src)) busy = 0 if(wateract) - W.water_act(20, 310.15, src) + W.water_act(20, COLD_WATER_TEMPERATURE, src) if("Disconnect") user.visible_message("[user] starts disconnecting [src].", "You begin disconnecting [src]...") if(do_after(user, 40 * O.toolspeed, target = src)) @@ -633,7 +633,7 @@ wateract = (O.wash(user, src)) busy = 0 if(wateract) - O.water_act(20, 310.15, src) + O.water_act(20, COLD_WATER_TEMPERATURE, src) /obj/structure/sink/update_icon() ..() diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm index 74d0e216614..6bae5a79d94 100644 --- a/code/game/turfs/simulated/walls_mineral.dm +++ b/code/game/turfs/simulated/walls_mineral.dm @@ -140,7 +140,23 @@ sheet_type = /obj/item/stack/sheet/wood hardness = 70 explosion_block = 0 - canSmoothWith = list(/turf/simulated/wall/mineral/wood, /obj/structure/falsewall/wood) + canSmoothWith = list(/turf/simulated/wall/mineral/wood, /obj/structure/falsewall/wood, /turf/simulated/wall/mineral/wood/nonmetal) + +/turf/simulated/wall/mineral/wood/attackby(obj/item/W, mob/user) + if(W.sharp && W.force) + var/duration = (48 / W.force) * 2 //In seconds, for now. + if(istype(W, /obj/item/hatchet) || istype(W, /obj/item/twohanded/fireaxe)) + duration /= 4 //Much better with hatchets and axes. + if(do_after(user, duration * 10, target = src)) //Into deciseconds. + dismantle_wall(FALSE, FALSE) + return + return ..() + +/turf/simulated/wall/mineral/wood/nonmetal + desc = "A solidly wooden wall. It's a bit weaker than a wall made with metal." + girder_type = /obj/structure/barricade/wooden + hardness = 50 + canSmoothWith = list(/turf/simulated/wall/mineral/wood, /obj/structure/falsewall/wood, /turf/simulated/wall/mineral/wood/nonmetal) /turf/simulated/wall/mineral/iron name = "rough metal wall" diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 51285932f00..0ab9ccbef15 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -516,6 +516,5 @@ /turf/AllowDrop() return TRUE -/turf/proc/water_act(volume, temperature, source) - for(var/mob/living/carbon/slime/M in src) - M.apply_water() +/turf/proc/water_act(volume, temperature, source) + return FALSE diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index a6f186dad73..d32a05eb312 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -784,11 +784,13 @@ var/global/nologevent = 0 log_admin("[key_name(usr)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].") message_admins("[key_name(usr)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1) return //alert("Round end delayed", null, null, null, null, null) - going = !( going ) - if(!( going )) + if(going) + going = FALSE + SSticker.delay_end = TRUE to_chat(world, "The game start has been delayed.") log_admin("[key_name(usr)] delayed the game.") else + going = TRUE to_chat(world, "The game will start soon.") log_admin("[key_name(usr)] removed the delay.") feedback_add_details("admin_verb","DELAY") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm index d52507bee1d..d57c3124f61 100644 --- a/code/modules/antagonists/_common/antag_spawner.dm +++ b/code/modules/antagonists/_common/antag_spawner.dm @@ -210,6 +210,7 @@ var/datum/objective/KillDaCrew = new /datum/objective KillDaCrew.owner = S.mind KillDaCrew.explanation_text = "[objective_verb] everyone else while you're at it." + KillDaCrew.completed = TRUE S.mind.objectives += KillDaCrew to_chat(S, "Objective #[1]: [KillDaWiz.explanation_text]") to_chat(S, "Objective #[2]: [KillDaCrew.explanation_text]") @@ -219,7 +220,8 @@ desc = "A magically infused bottle of clown love, distilled from \ countless hugging attacks. Used in funny rituals to attract \ adorable creatures." - color = "#FF69B4" // HOT PINK + icon = 'icons/obj/wizard.dmi' + icon_state = "vialtickles" veil_msg = "You sense an adorable presence \ lurking just beyond the veil..." objective_verb = "Hug and tickle" @@ -278,6 +280,7 @@ var/datum/objective/KillDaCrew = new /datum/objective KillDaCrew.owner = M.mind KillDaCrew.explanation_text = "[objective_verb] everyone and everything else while you're at it." + KillDaCrew.completed = TRUE M.mind.objectives += KillDaCrew to_chat(M, "Objective #[1]: [KillDaWiz.explanation_text]") to_chat(M, "Objective #[2]: [KillDaCrew.explanation_text]") diff --git a/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm b/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm index 60cedb281fa..9a5bf275abc 100644 --- a/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm +++ b/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm @@ -104,6 +104,11 @@ H.rename_character(null, H.dna.species.get_random_name()) else H.rename_character(null, name) + if(is_species(H, /datum/species/golem/tranquillite) && H.mind) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall(null)) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mime/speak(null)) + H.mind.miming = TRUE + if(has_owner) new_spawn.mind.assigned_role = "Servant Golem" else diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm index 300443714ab..57a6df32ab6 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/client/asset_cache.dm @@ -318,7 +318,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the for(var/D in cardinal) assets["[state]-[dir2text(D)].png"] = icon('icons/obj/pipe-item.dmi', state, D) for(var/state in icon_states('icons/obj/pipes/disposal.dmi')) - if(!(state in list("pipe-c", "pipe-j1", "pipe-s", "pipe-t", "pipe-y", "intake", "outlet"))) //Pipes we want sprites for + if(!(state in list("pipe-c", "pipe-j1", "pipe-s", "pipe-t", "pipe-y", "intake", "outlet", "pipe-j1s"))) //Pipes we want sprites for continue for(var/D in cardinal) assets["[state]-[dir2text(D)].png"] = icon('icons/obj/pipes/disposal.dmi', state, D) diff --git a/code/modules/client/preference/loadout/loadout_cosmetics.dm b/code/modules/client/preference/loadout/loadout_cosmetics.dm index aa7f5f02576..b7ac6c39493 100644 --- a/code/modules/client/preference/loadout/loadout_cosmetics.dm +++ b/code/modules/client/preference/loadout/loadout_cosmetics.dm @@ -21,12 +21,4 @@ /datum/gear/lipstick/lime display_name = "lipstick, lime" - path = /obj/item/lipstick/lime - -/datum/gear/monocle - display_name = "monocle" - path = /obj/item/clothing/glasses/monocle - -/datum/gear/sunglasses - display_name = "cheap sunglasses" - path = /obj/item/clothing/glasses/sunglasses/fake \ No newline at end of file + path = /obj/item/lipstick/lime \ No newline at end of file diff --git a/code/modules/client/preference/loadout/loadout_donor.dm b/code/modules/client/preference/loadout/loadout_donor.dm index 5558a988209..830b10b7055 100644 --- a/code/modules/client/preference/loadout/loadout_donor.dm +++ b/code/modules/client/preference/loadout/loadout_donor.dm @@ -18,12 +18,10 @@ /datum/gear/donor/furcape display_name = "Fur Cape" path = /obj/item/clothing/suit/furcape - cost = 2 /datum/gear/donor/furcoat display_name = "Fur Coat" path = /obj/item/clothing/suit/furcoat - cost = 2 /datum/gear/donor/kamina display_name = "Spiky Orange-tinted Shades" @@ -33,10 +31,6 @@ display_name = "Spiky Green-tinted Shades" path = /obj/item/clothing/glasses/fluff/kamina/green -/datum/gear/donor/hipster - display_name = "Hipster Glasses" - path = /obj/item/clothing/glasses/regular/hipster - /datum/gear/donor/threedglasses display_name = "Threed Glasses" path = /obj/item/clothing/glasses/threedglasses diff --git a/code/modules/client/preference/loadout/loadout_glasses.dm b/code/modules/client/preference/loadout/loadout_glasses.dm new file mode 100644 index 00000000000..94f2555bdba --- /dev/null +++ b/code/modules/client/preference/loadout/loadout_glasses.dm @@ -0,0 +1,24 @@ +/datum/gear/glasses + subtype_path = /datum/gear/glasses + slot = slot_glasses + sort_category = "Glasses" + +/datum/gear/glasses/sunglasses + display_name = "cheap sunglasses" + path = /obj/item/clothing/glasses/sunglasses_fake + +/datum/gear/glasses/eyepatch + display_name = "Eyepatch" + path = /obj/item/clothing/glasses/eyepatch + +/datum/gear/glasses/hipster + display_name = "Hipster glasses" + path = /obj/item/clothing/glasses/regular/hipster + +/datum/gear/glasses/monocle + display_name = "Monocle" + path = /obj/item/clothing/glasses/monocle + +/datum/gear/glasses/prescription + display_name = "Prescription glasses" + path = /obj/item/clothing/glasses/regular \ No newline at end of file diff --git a/code/modules/client/preference/loadout/loadout_gloves.dm b/code/modules/client/preference/loadout/loadout_gloves.dm new file mode 100644 index 00000000000..cd8d5a7c8e1 --- /dev/null +++ b/code/modules/client/preference/loadout/loadout_gloves.dm @@ -0,0 +1,8 @@ +/datum/gear/gloves + subtype_path = /datum/gear/gloves + slot = slot_gloves + sort_category = "Gloves" + +/datum/gear/gloves/fingerless + display_name = "Fingerless Gloves" + path = /obj/item/clothing/gloves/fingerless \ No newline at end of file diff --git a/code/modules/client/preference/loadout/loadout_shoes.dm b/code/modules/client/preference/loadout/loadout_shoes.dm index 519cadcc044..5031f4333fb 100644 --- a/code/modules/client/preference/loadout/loadout_shoes.dm +++ b/code/modules/client/preference/loadout/loadout_shoes.dm @@ -27,25 +27,32 @@ /datum/gear/shoes/cowboyboots display_name = "cowboy boots, brown" - cost = 1 - path = /obj/item/clothing/shoes/cowboyboots + path = /obj/item/clothing/shoes/cowboy /datum/gear/shoes/cowboyboots_black display_name = "cowboy boots, black" - cost = 1 - path = /obj/item/clothing/shoes/cowboyboots/black + path = /obj/item/clothing/shoes/cowboy/black /datum/gear/shoes/cowboyboots/white display_name = "cowboy boots, white" - cost = 1 - path = /obj/item/clothing/shoes/cowboyboots/white + path = /obj/item/clothing/shoes/cowboy/white /datum/gear/shoes/cowboyboots/pink display_name = "cowboy boots, pink" - cost = 1 - path = /obj/item/clothing/shoes/cowboyboots/pink - + path = /obj/item/clothing/shoes/cowboy/pink + /datum/gear/shoes/laceup display_name = "laceup shoes" - cost = 1 path = /obj/item/clothing/shoes/laceup + +/datum/gear/shoes/blackshoes + display_name = "Black shoes" + path = /obj/item/clothing/shoes/black + +/datum/gear/shoes/brownshoes + display_name = "Brown shoes" + path = /obj/item/clothing/shoes/brown + +/datum/gear/shoes/whiteshoes + display_name = "White shoes" + path = /obj/item/clothing/shoes/white \ No newline at end of file diff --git a/code/modules/client/preference/loadout/loadout_suit.dm b/code/modules/client/preference/loadout/loadout_suit.dm index 3d6b5ded994..32a9bae99e7 100644 --- a/code/modules/client/preference/loadout/loadout_suit.dm +++ b/code/modules/client/preference/loadout/loadout_suit.dm @@ -1,7 +1,6 @@ /datum/gear/suit subtype_path = /datum/gear/suit slot = slot_wear_suit - cost = 2 sort_category = "External Wear" //WINTER COATS @@ -105,6 +104,10 @@ path = /obj/item/clothing/suit/armor/secjacket allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer", "Security Pod Pilot") +/datum/gear/suit/ianshirt + display_name = "Ian Shirt" + path = /obj/item/clothing/suit/ianshirt + /datum/gear/suit/poncho display_name = "poncho, classic" path = /obj/item/clothing/suit/poncho diff --git a/code/modules/client/preference/loadout/loadout_uniform.dm b/code/modules/client/preference/loadout/loadout_uniform.dm index f4a5c465aba..eb5264a0975 100644 --- a/code/modules/client/preference/loadout/loadout_uniform.dm +++ b/code/modules/client/preference/loadout/loadout_uniform.dm @@ -2,7 +2,6 @@ /datum/gear/uniform subtype_path = /datum/gear/uniform slot = slot_w_uniform - cost = 2 sort_category = "Uniforms and Casual Dress" /datum/gear/uniform/skirt diff --git a/code/modules/client/preference/preferences_toggles.dm b/code/modules/client/preference/preferences_toggles.dm index e164a2ab843..c1ad8d6d103 100644 --- a/code/modules/client/preference/preferences_toggles.dm +++ b/code/modules/client/preference/preferences_toggles.dm @@ -201,6 +201,19 @@ to_chat(src, "You will no longer hear musical instruments.") feedback_add_details("admin_verb","TInstru") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/client/verb/Toggle_disco() //to toggle off the disco machine locally, in case it gets too annoying + set name = "Hear/Silence Dance Machine" + set category = "Preferences" + set desc = "Toggles hearing and dancing to the radiant dance machine" + prefs.sound ^= SOUND_DISCO + prefs.save_preferences(src) + if(prefs.sound & SOUND_DISCO) + to_chat(src, "You will now hear and dance to the radiant dance machine.") + else + to_chat(src, "You will no longer hear or dance to the radiant dance machine.") + usr.stop_sound_channel(CHANNEL_JUKEBOX) + feedback_add_details("admin_verb","Tdd") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + /client/verb/setup_character() set name = "Game Preferences" set category = "Preferences" diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 27fa269ae29..96cff51ec4d 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -596,7 +596,7 @@ BLIND // can't see anything min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT heat_protection = HEAD max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT - species_restricted = list("exclude","Diona","Vox","Wryn") + species_restricted = list("exclude","Vox","Wryn") flash_protect = 2 strip_delay = 50 put_on_delay = 50 @@ -624,7 +624,7 @@ BLIND // can't see anything put_on_delay = 80 burn_state = FIRE_PROOF hide_tail_by_species = null - species_restricted = list("exclude","Diona","Vox","Wryn") + species_restricted = list("exclude","Vox","Wryn") //Under clothing /obj/item/clothing/under diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index ac6c3b6dd0b..81ab79adbc4 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -265,9 +265,11 @@ "Grey" = 'icons/mob/species/grey/eyes.dmi' ) -/obj/item/clothing/glasses/sunglasses/fake +/obj/item/clothing/glasses/sunglasses_fake desc = "Cheap, plastic sunglasses. They don't even have UV protection." name = "cheap sunglasses" + icon_state = "sun" + item_state = "sunglasses" see_in_dark = 0 flash_protect = 0 tint = 0 diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index 1e639beb5de..27cd78afad3 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -38,12 +38,6 @@ "Grey" = 'icons/mob/species/grey/eyes.dmi' ) -/obj/item/clothing/glasses/hud/health/health_advanced - name = "\improper Advanced Health Scanner HUD" - desc = "A heads-up display that scans the humans in view and provides accurate data about their health status. Includes anti-flash filter." - icon_state = "advmedhud" - flash_protect = 1 - /obj/item/clothing/glasses/hud/health/night name = "\improper Night Vision Health Scanner HUD" desc = "An advanced medical head-up display that allows doctors to find patients in complete darkness." @@ -54,6 +48,14 @@ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE prescription_upgradable = 0 +/obj/item/clothing/glasses/hud/health/sunglasses + name = "medical HUDSunglasses" + desc = "Sunglasses with a medical HUD." + icon_state = "sunhudmed" + see_in_dark = 1 + flash_protect = 1 + tint = 1 + /obj/item/clothing/glasses/hud/diagnostic name = "Diagnostic HUD" desc = "A heads-up display capable of analyzing the integrity and status of robotics and exosuits." @@ -77,6 +79,14 @@ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE prescription_upgradable = 0 +/obj/item/clothing/glasses/hud/diagnostic/sunglasses + name = "diagnostic sunglasses" + desc = "Sunglasses with a diagnostic HUD." + icon_state = "sunhuddiag" + item_state = "glasses" + flash_protect = 1 + tint = 1 + /obj/item/clothing/glasses/hud/security name = "\improper Security HUD" desc = "A heads-up display that scans the humans in view and provides accurate data about their ID status and security records." diff --git a/code/modules/clothing/head/beanie.dm b/code/modules/clothing/head/beanie.dm new file mode 100644 index 00000000000..af7e805b232 --- /dev/null +++ b/code/modules/clothing/head/beanie.dm @@ -0,0 +1,96 @@ + +//BeanieStation13 Redux + +//Plus a bobble hat, lets be inclusive!! + +/obj/item/clothing/head/beanie //Default is white, this is meant to be seen + name = "white beanie" + desc = "A stylish beanie. The perfect winter accessory for those with a keen fashion sense, and those who just can't handle a cold breeze on their heads." + icon_state = "beanie" //Default white + item_color = "beanie" + +/obj/item/clothing/head/beanie/black + name = "black beanie" + icon_state = "beanie" + color = "#4A4A4B" //Grey but it looks black + +/obj/item/clothing/head/beanie/red + name = "red beanie" + icon_state = "beanie" + color = "#D91414" //Red + +/obj/item/clothing/head/beanie/green + name = "green beanie" + icon_state = "beanie" + color = "#5C9E54" //Green + +/obj/item/clothing/head/beanie/darkblue + name = "dark blue beanie" + icon_state = "beanie" + color = "#1E85BC" //Blue + +/obj/item/clothing/head/beanie/purple + name = "purple beanie" + icon_state = "beanie" + color = "#9557C5" //purple + +/obj/item/clothing/head/beanie/yellow + name = "yellow beanie" + icon_state = "beanie" + color = "#E0C14F" //Yellow + +/obj/item/clothing/head/beanie/orange + name = "orange beanie" + icon_state = "beanie" + color = "#C67A4B" //orange + +/obj/item/clothing/head/beanie/cyan + name = "cyan beanie" + icon_state = "beanie" + color = "#54A3CE" //Cyan (Or close to it) + +//Striped Beanies have unique sprites + +/obj/item/clothing/head/beanie/christmas + name = "christmas beanie" + icon_state = "beaniechristmas" + item_color = "beaniechristmas" + +/obj/item/clothing/head/beanie/striped + name = "striped beanie" + icon_state = "beaniestriped" + item_color = "beaniestriped" + +/obj/item/clothing/head/beanie/stripedred + name = "red striped beanie" + icon_state = "beaniestripedred" + item_color = "beaniestripedred" + +/obj/item/clothing/head/beanie/stripedblue + name = "blue striped beanie" + icon_state = "beaniestripedblue" + item_color = "beaniestripedblue" + +/obj/item/clothing/head/beanie/stripedgreen + name = "green striped beanie" + icon_state = "beaniestripedgreen" + item_color = "beaniestripedgreen" + +/obj/item/clothing/head/beanie/durathread + name = "durathread beanie" + desc = "A beanie made from durathread, its resilient fibres provide some protection to the wearer." + icon_state = "beaniedurathread" + item_color = null + armor = list(melee = 15, bullet = 5, laser = 15, energy = 5, bomb = 10, bio = 0, rad = 0) + +/obj/item/clothing/head/beanie/waldo + name = "red striped bobble hat" + desc = "If you're going on a worldwide hike, you'll need some cold protection." + icon_state = "waldo_hat" + item_color = "waldo_hat" + +/obj/item/clothing/head/beanie/rasta + name = "rastacap" + desc = "Perfect for tucking in those dreadlocks." + icon_state = "beanierasta" + item_color = "beanierasta" \ No newline at end of file diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 4c915e5fc9c..13826e53ea1 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -227,6 +227,24 @@ obj/item/clothing/head/blob item_state = "knight_templar" armor = list(melee = 20, bullet = 7, laser = 2, energy = 2, bomb = 2, bio = 2, rad = 0) +/obj/item/clothing/head/helmet/skull + name = "skull helmet" + desc = "An intimidating tribal helmet, it doesn't look very comfortable." + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + flags_cover = HEADCOVERSEYES + armor = list(melee = 25, bullet = 25, laser = 25, energy = 10, bomb = 10, bio = 5, rad = 20) + icon_state = "skull" + item_state = "skull" + strip_delay = 100 + +/obj/item/clothing/head/helmet/durathread + name = "durathread helmet" + desc = "A helmet made from durathread and leather." + icon_state = "durathread" + item_state = "durathread" + armor = list(melee = 25, bullet = 10, laser = 20, energy = 10, bomb = 30, bio = 15, rad = 20) + strip_delay = 60 + //Commander /obj/item/clothing/head/helmet/ert/command name = "emergency response team commander helmet" diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index adcc828d8d5..19ab1569d19 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -82,6 +82,13 @@ desc = "A beret, an artists favorite headwear." icon_state = "beret" +/obj/item/clothing/head/beret/durathread + name = "durathread beret" + desc = "A beret made from durathread, its resilient fibres provide some protection to the wearer." + icon_state = "beretdurathread" + item_color = null + armor = list(melee = 15, bullet = 5, laser = 15, energy = 5, bomb = 10, bio = 0, rad = 0) + //Security /obj/item/clothing/head/HoS name = "head of security cap" diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index 3151ddca083..a60e4b2c2a6 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -483,6 +483,11 @@ item_color = "black" desc = "It's a black bandana." +/obj/item/clothing/mask/bandana/durathread + name = "durathread bandana" + desc = "A bandana made from durathread, you wish it would provide some protection to its wearer, but it's far too thin..." + icon_state = "banddurathread" + /obj/item/clothing/mask/cursedclown name = "cursed clown mask" desc = "This is a very, very odd looking mask." diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index bca650a30b1..3a94118e538 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -243,30 +243,55 @@ icon_state = "bsing" put_on_delay = 50 -/obj/item/clothing/shoes/cowboyboots +/obj/item/clothing/shoes/cowboy name = "cowboy boots" desc = "A pair a' brown boots." - icon_state = "cowboyboots" - item_color = "cowboyboots" + icon_state = "cowboy_brown" + item_color = "cowboy_brown" -/obj/item/clothing/shoes/cowboyboots/black +/obj/item/clothing/shoes/cowboy/black name = "black cowboy boots" desc = "A pair a' black rustlers' boots" - icon_state = "cowboyboots_black" - item_color = "cowboyboots_black" + icon_state = "cowboy_black" + item_color = "cowboy_black" -/obj/item/clothing/shoes/cowboyboots/white +/obj/item/clothing/shoes/cowboy/white name = "white cowboy boots" desc = "For the rancher in us all." - icon_state = "cowboyboots_white" - item_color = "cowboyboots_white" + icon_state = "cowboy_white" + item_color = "cowboy_white" -/obj/item/clothing/shoes/cowboyboots/pink +/obj/item/clothing/shoes/cowboy/fancy + name = "bilton wrangler boots" + desc = "A pair of authentic haute couture boots from Japanifornia. You doubt they have ever been close to cattle." + icon_state = "cowboy_fancy" + item_color = "cowboy_fancy" + +/obj/item/clothing/shoes/cowboy/pink name = "pink cowgirl boots" desc = "For a Rustlin' tustlin' cowgirl." icon_state = "cowboyboots_pink" item_color = "cowboyboots_pink" +/obj/item/clothing/shoes/cowboy/lizard + name = "lizard skin boots" + desc = "You can hear a faint hissing from inside the boots; you hope it is just a mournful ghost." + icon_state = "lizardboots_green" + +/obj/item/clothing/shoes/cowboy/lizardmasterwork + name = "\improper Hugs-The-Feet lizard skin boots" + desc = "A pair of masterfully crafted lizard skin boots. Finally a good application for the station's most bothersome inhabitants." + icon_state = "lizardboots_blue" + +/obj/effect/spawner/lootdrop/lizardboots + name = "random lizard boot quality" + desc = "Which ever gets picked, the lizard race loses" + icon = 'icons/obj/clothing/shoes.dmi' + icon_state = "lizardboots_green" + loot = list( + /obj/item/clothing/shoes/cowboy/lizard = 7, + /obj/item/clothing/shoes/cowboy/lizardmasterwork = 1) + /obj/item/clothing/shoes/footwraps name = "cloth footwraps" desc = "A roll of treated canvas used for wrapping claws or paws." diff --git a/code/modules/clothing/spacesuits/ert.dm b/code/modules/clothing/spacesuits/ert.dm index e97f220bd8e..60523d6c0e8 100644 --- a/code/modules/clothing/spacesuits/ert.dm +++ b/code/modules/clothing/spacesuits/ert.dm @@ -190,7 +190,7 @@ max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT sprite_sheets = null actions_types = list() - has_camera = 0 + has_camera = FALSE /obj/item/clothing/suit/space/hardsuit/ert/paranormal name = "paranormal response team suit" @@ -208,20 +208,26 @@ name = "inquisitor's helmet" icon_state = "hardsuit0-inquisitor" item_color = "inquisitor" + armor = list(melee = 65, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 100, rad = 100) /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor name = "inquisitor's hardsuit" icon_state = "hardsuit-inquisitor" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor + armor = list(melee = 65, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 100, rad = 100) + slowdown = 0 /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/berserker name = "champion's helmet" desc = "Peering into the eyes of the helmet is enough to seal damnation." icon_state = "hardsuit0-berserker" item_color = "berserker" + armor = list(melee = 65, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 100, rad = 100) /obj/item/clothing/suit/space/hardsuit/ert/paranormal/berserker name = "champion's hardsuit" desc = "Voices echo from the hardsuit, driving the user insane." icon_state = "hardsuit-berserker" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/berserker + armor = list(melee = 65, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 100, rad = 100) + slowdown = 0 \ No newline at end of file diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index 4c74aba8c93..466fb2fc2fd 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -14,7 +14,7 @@ actions_types = list(/datum/action/item_action/toggle_helmet_light) //Species-specific stuff. - species_restricted = list("exclude","Diona","Wryn") + species_restricted = list("exclude","Wryn") sprite_sheets = list( "Unathi" = 'icons/mob/species/unathi/helmet.dmi', "Tajaran" = 'icons/mob/species/tajaran/helmet.dmi', @@ -93,9 +93,10 @@ var/obj/item/clothing/head/helmet/space/hardsuit/helmet actions_types = list(/datum/action/item_action/toggle_helmet) var/helmettype = /obj/item/clothing/head/helmet/space/hardsuit + var/obj/item/tank/jetpack/suit/jetpack = null hide_tail_by_species = list("Vox" , "Vulpkanin" , "Unathi" , "Tajaran") - species_restricted = list("exclude","Diona","Wryn") + species_restricted = list("exclude", "Wryn") sprite_sheets = list( "Unathi" = 'icons/mob/species/unathi/suit.dmi', "Tajaran" = 'icons/mob/species/tajaran/suit.dmi', @@ -112,10 +113,59 @@ "Vulpkanin" = 'icons/obj/clothing/species/vulpkanin/suits.dmi' ) +/obj/item/clothing/suit/space/hardsuit/New() + if(jetpack && ispath(jetpack)) + jetpack = new jetpack(src) + ..() + /obj/item/clothing/suit/space/hardsuit/attack_self(mob/user) user.changeNext_move(CLICK_CD_MELEE) ..() +/obj/item/clothing/suit/space/hardsuit/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/tank/jetpack/suit)) + if(jetpack) + to_chat(user, "[src] already has a jetpack installed.") + return + if(src == user.get_item_by_slot(slot_wear_suit)) //Make sure the player is not wearing the suit before applying the upgrade. + to_chat(user, "You cannot install the upgrade to [src] while wearing it.") + return + + if(user.unEquip(I)) + I.forceMove(src) + jetpack = I + to_chat(user, "You successfully install the jetpack into [src].") + return + else if(isscrewdriver(I)) + if(!jetpack) + to_chat(user, "[src] has no jetpack installed.") + return + if(src == user.get_item_by_slot(slot_wear_suit)) + to_chat(user, "You cannot remove the jetpack from [src] while wearing it.") + return + + jetpack.turn_off(user) + jetpack.forceMove(drop_location()) + jetpack = null + to_chat(user, "You successfully remove the jetpack from [src].") + return + return ..() + +/obj/item/clothing/suit/space/hardsuit/equipped(mob/user, slot) + ..() + if(jetpack) + if(slot == slot_wear_suit) + for(var/X in jetpack.actions) + var/datum/action/A = X + A.Grant(user) + +/obj/item/clothing/suit/space/hardsuit/dropped(mob/user) + ..() + if(jetpack) + for(var/X in jetpack.actions) + var/datum/action/A = X + A.Remove(user) + /obj/item/clothing/suit/space/hardsuit/item_action_slot_check(slot) if(slot == slot_wear_suit) //we only give the mob the ability to toggle the helmet if he's wearing the hardsuit. return 1 @@ -178,6 +228,7 @@ heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine/elite + jetpack = /obj/item/tank/jetpack/suit //Mining hardsuit /obj/item/clothing/head/helmet/space/hardsuit/mining @@ -291,6 +342,7 @@ armor = list(melee = 40, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 50) allowed = list(/obj/item/gun, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/energy/sword, /obj/item/restraints/handcuffs, /obj/item/tank) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi + jetpack = /obj/item/tank/jetpack/suit /obj/item/clothing/suit/space/hardsuit/syndi/update_icon() icon_state = "hardsuit[on]-[item_color]" @@ -438,6 +490,7 @@ icon_state = "hardsuit-hos" armor = list(melee = 45, bullet = 25, laser = 30, energy = 10, bomb = 25, bio = 100, rad = 50) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/security/hos + jetpack = /obj/item/tank/jetpack/suit sprite_sheets = null //Singuloth armor @@ -522,6 +575,7 @@ allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs,/obj/item/tank) slowdown = 0 helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi + jetpack = /obj/item/tank/jetpack/suit sprite_sheets = list( "Unathi" = 'icons/mob/species/unathi/suit.dmi', "Tajaran" = 'icons/mob/species/tajaran/suit.dmi', diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index 9706b254fa8..1e5c9ad6dcb 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -7,7 +7,7 @@ flags_inv = HIDEFACE permeability_coefficient = 0.01 armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50) - species_restricted = list("exclude", "Diona", "Wryn") + species_restricted = list("exclude", "Wryn") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/helmet.dmi', @@ -31,7 +31,7 @@ w_class = WEIGHT_CLASS_BULKY allowed = list(/obj/item/tank, /obj/item/flashlight,/obj/item/gun/energy, /obj/item/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton,/obj/item/restraints/handcuffs) armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50) - species_restricted = list("exclude", "Diona", "Wryn") + species_restricted = list("exclude", "Wryn") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/suit.dmi' @@ -72,7 +72,7 @@ allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/tank,/obj/item/kitchen/knife/combat) armor = list(melee = 40, bullet = 30, laser = 30, energy = 30, bomb = 50, bio = 90, rad = 20) strip_delay = 120 - species_restricted = list("exclude", "Diona", "Wryn") + species_restricted = list("exclude", "Wryn") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/suit.dmi' @@ -159,7 +159,7 @@ icon_state = "paramedic-eva-helmet" item_state = "paramedic-eva-helmet" armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20) - species_restricted = list("exclude", "Diona", "Wryn") + species_restricted = list("exclude", "Wryn") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/helmet.dmi', @@ -180,7 +180,7 @@ item_state = "paramedic-eva" desc = "A brand new paramedic EVA suit. The nitrile seems a bit too thin to be space proof. Used for retrieving bodies in space." armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20) - species_restricted = list("exclude", "Diona", "Wryn") + species_restricted = list("exclude", "Wryn") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/suit.dmi', @@ -200,7 +200,7 @@ item_state = "s_suit" desc = "A lightweight space suit with the basic ability to protect the wearer from the vacuum of space during emergencies." armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20) - species_restricted = list("exclude", "Diona", "Wryn") + species_restricted = list("exclude", "Wryn") sprite_sheets = list( "Tajaran" = 'icons/mob/species/tajaran/suit.dmi', @@ -223,7 +223,7 @@ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20) flash_protect = 0 - species_restricted = list("exclude", "Diona", "Wryn") + species_restricted = list("exclude", "Wryn") sprite_sheets = list( "Tajaran" = 'icons/mob/species/tajaran/helmet.dmi', @@ -244,7 +244,7 @@ desc = ". . ." icon_state = "spacemimehelmet" item_state = "spacemimehelmet" - species_restricted = list("exclude","Diona","Vox","Wryn") + species_restricted = list("exclude","Vox","Wryn") sprite_sheets = null sprite_sheets_obj = null @@ -254,7 +254,7 @@ desc = ". . ." icon_state = "spacemime_suit" item_state = "spacemime_items" - species_restricted = list("exclude","Diona","Vox","Wryn") + species_restricted = list("exclude","Vox","Wryn") sprite_sheets = null sprite_sheets_obj = null @@ -264,7 +264,7 @@ desc = "An EVA helmet specifically designed for the clown. SPESSHONK!" icon_state = "clownhelmet" item_state = "clownhelmet" - species_restricted = list("exclude","Diona","Vox","Wryn") + species_restricted = list("exclude","Vox","Wryn") sprite_sheets = null sprite_sheets_obj = null @@ -274,7 +274,6 @@ desc = "An EVA suit specifically designed for the clown. SPESSHONK!" icon_state = "spaceclown_suit" item_state = "spaceclown_items" - species_restricted = list("exclude","Diona","Vox","Wryn") + species_restricted = list("exclude","Vox","Wryn") sprite_sheets = null sprite_sheets_obj = null - \ No newline at end of file diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index ae8502f7246..e27b3b8ef1f 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -209,6 +209,15 @@ allowed = list(/obj/item/nullrod/claymore) armor = list(melee = 25, bullet = 5, laser = 5, energy = 5, bomb = 0, bio = 0, rad = 0) +/obj/item/clothing/suit/armor/vest/durathread + name = "durathread vest" + desc = "A vest made of durathread with strips of leather acting as trauma plates." + icon_state = "durathread" + item_state = "durathread" + strip_delay = 60 + burn_state = FLAMMABLE + armor = list(melee = 20, bullet = 10, laser = 30, energy = 5, bomb = 15, bio = 0, rad = 0) + /obj/item/clothing/suit/armor/bulletproof name = "Bulletproof Vest" desc = "A bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent." @@ -528,14 +537,4 @@ item_state = "bonearmor" blood_overlay_type = "armor" armor = list(melee = 35, bullet = 25, laser = 25, energy = 10, bomb = 25, bio = 0, rad = 0) - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS - -/obj/item/clothing/head/helmet/skull - name = "skull helmet" - desc = "An intimidating tribal helmet, it doesn't look very comfortable." - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - flags_cover = HEADCOVERSEYES - armor = list(melee = 25, bullet = 25, laser = 25, energy = 10, bomb = 10, bio = 5, rad = 20) - icon_state = "skull" - item_state = "skull" - strip_delay = 100 \ No newline at end of file + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS \ No newline at end of file diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index c1c60f3a67d..b87e7d8233a 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -1005,3 +1005,14 @@ icon_state = "old_mantle" item_state = "old_mantle" +/obj/item/clothing/suit/ghost_sheet + name = "ghost sheet" + desc = "The hands float by themselves, so it's extra spooky." + icon_state = "ghost_sheet" + item_state = "ghost_sheet" + throwforce = 0 + throw_speed = 1 + throw_range = 2 + w_class = WEIGHT_CLASS_TINY + flags = BLOCKHAIR + flags_inv = HIDEGLOVES|HIDEEARS|HIDEFACE \ No newline at end of file diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm index 871eab23d3b..576b3e6c552 100644 --- a/code/modules/clothing/suits/toggles.dm +++ b/code/modules/clothing/suits/toggles.dm @@ -6,7 +6,8 @@ /obj/item/clothing/suit/space/hardsuit/Destroy() if(helmet) helmet.suit = null - qdel(helmet) + QDEL_NULL(helmet) + QDEL_NULL(jetpack) return ..() /obj/item/clothing/head/helmet/space/hardsuit/Destroy() diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 91527f2dd19..c277345a440 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -890,3 +890,10 @@ item_color = "hawaiianblue" flags_size = ONESIZEFITSALL +/obj/item/clothing/under/misc/durathread + name = "durathread jumpsuit" + desc = "A jumpsuit made from durathread, its resilient fibres provide some protection to the wearer." + icon_state = "durathread" + item_state = "durathread" + item_color = "durathread" + armor = list(melee = 10, bullet = 0, laser = 10, energy = 0, bomb = 5, bio = 0, rad = 0) \ No newline at end of file diff --git a/code/modules/crafting/craft.dm b/code/modules/crafting/craft.dm index ea5e4a652aa..77cef31ed55 100644 --- a/code/modules/crafting/craft.dm +++ b/code/modules/crafting/craft.dm @@ -1,7 +1,7 @@ /datum/personal_crafting var/busy var/viewing_category = 1 //typical powergamer starting on the Weapons tab - var/list/categories = list(CAT_WEAPON,CAT_AMMO,CAT_ROBOT,CAT_FOOD,CAT_MISC,CAT_PRIMAL) + var/list/categories = list(CAT_WEAPON,CAT_AMMO,CAT_ROBOT,CAT_FOOD,CAT_CLOTHING,CAT_MISC,CAT_PRIMAL) var/display_craftable_only = FALSE var/display_compact = TRUE diff --git a/code/modules/crafting/tailoring.dm b/code/modules/crafting/tailoring.dm new file mode 100644 index 00000000000..a46e509001c --- /dev/null +++ b/code/modules/crafting/tailoring.dm @@ -0,0 +1,145 @@ +/datum/crafting_recipe/durathread_vest + name = "Durathread Vest" + result = /obj/item/clothing/suit/armor/vest/durathread + reqs = list(/obj/item/stack/sheet/durathread = 5, + /obj/item/stack/sheet/leather = 4) + time = 50 + category = CAT_CLOTHING + +/datum/crafting_recipe/durathread_helmet + name = "Durathread Helmet" + result = /obj/item/clothing/head/helmet/durathread + reqs = list(/obj/item/stack/sheet/durathread = 4, + /obj/item/stack/sheet/leather = 5) + time = 40 + category = CAT_CLOTHING + +/datum/crafting_recipe/durathread_jumpsuit + name = "Durathread Jumpsuit" + result = /obj/item/clothing/under/misc/durathread + reqs = list(/obj/item/stack/sheet/durathread = 4) + time = 40 + category = CAT_CLOTHING + +/datum/crafting_recipe/durathread_beret + name = "Durathread Beret" + result = /obj/item/clothing/head/beret/durathread + reqs = list(/obj/item/stack/sheet/durathread = 2) + time = 40 + category = CAT_CLOTHING + +/datum/crafting_recipe/durathread_beanie + name = "Durathread Beanie" + result = /obj/item/clothing/head/beanie/durathread + reqs = list(/obj/item/stack/sheet/durathread = 2) + time = 40 + category = CAT_CLOTHING + +/datum/crafting_recipe/durathread_bandana + name = "Durathread Bandana" + result = /obj/item/clothing/mask/bandana/durathread + reqs = list(/obj/item/stack/sheet/durathread = 1) + time = 25 + category = CAT_CLOTHING + +/datum/crafting_recipe/fannypack + name = "Fannypack" + result = /obj/item/storage/belt/fannypack + reqs = list(/obj/item/stack/sheet/cloth = 2, + /obj/item/stack/sheet/leather = 1) + time = 20 + category = CAT_CLOTHING + +/datum/crafting_recipe/hudsunsec + name = "Security HUDsunglasses" + result = /obj/item/clothing/glasses/hud/security/sunglasses + time = 20 + tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + reqs = list(/obj/item/clothing/glasses/hud/security = 1, + /obj/item/clothing/glasses/sunglasses = 1, + /obj/item/stack/cable_coil = 5) + category = CAT_CLOTHING + +/datum/crafting_recipe/hudsunsecremoval + name = "Security HUD removal" + result = /obj/item/clothing/glasses/sunglasses + time = 20 + tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + reqs = list(/obj/item/clothing/glasses/hud/security/sunglasses = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/hudsunmed + name = "Medical HUDsunglasses" + result = /obj/item/clothing/glasses/hud/health/sunglasses + time = 20 + tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + reqs = list(/obj/item/clothing/glasses/hud/health = 1, + /obj/item/clothing/glasses/sunglasses = 1, + /obj/item/stack/cable_coil = 5) + category = CAT_CLOTHING + +/datum/crafting_recipe/hudsunmedremoval + name = "Medical HUD removal" + result = /obj/item/clothing/glasses/sunglasses + time = 20 + tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + reqs = list(/obj/item/clothing/glasses/hud/health/sunglasses = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/hudsundiag + name = "Diagnostic HUDsunglasses" + result = /obj/item/clothing/glasses/hud/diagnostic/sunglasses + time = 20 + tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + reqs = list(/obj/item/clothing/glasses/hud/diagnostic = 1, + /obj/item/clothing/glasses/sunglasses = 1, + /obj/item/stack/cable_coil = 5) + category = CAT_CLOTHING + +/datum/crafting_recipe/hudsundiagremoval + name = "Diagnostic HUD removal" + result = /obj/item/clothing/glasses/sunglasses + time = 20 + tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + reqs = list(/obj/item/clothing/glasses/hud/diagnostic/sunglasses = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/beergoggles + name = "Beer Goggles" + result = /obj/item/clothing/glasses/sunglasses/reagent + time = 20 + tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + reqs = list(/obj/item/clothing/glasses/science = 1, + /obj/item/clothing/glasses/sunglasses = 1, + /obj/item/stack/cable_coil = 5) + category = CAT_CLOTHING + +/datum/crafting_recipe/beergogglesremoval + name = "Beer Goggles removal" + result = /obj/item/clothing/glasses/sunglasses + time = 20 + tools = list(/obj/item/screwdriver, /obj/item/wirecutters) + reqs = list(/obj/item/clothing/glasses/sunglasses/reagent = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/ghostsheet + name = "Ghost Sheet" + result = /obj/item/clothing/suit/ghost_sheet + time = 5 + tools = list(/obj/item/wirecutters) + reqs = list(/obj/item/bedsheet = 1) + category = CAT_CLOTHING + +/datum/crafting_recipe/cowboyboots + name = "Cowboy Boots" + result = /obj/item/clothing/shoes/cowboy + reqs = list(/obj/item/stack/sheet/leather = 2) + time = 45 + category = CAT_CLOTHING + +/datum/crafting_recipe/lizardboots + name = "Lizard Skin Boots" + result = /obj/effect/spawner/lootdrop/lizardboots + reqs = list(/obj/item/stack/sheet/animalhide/lizard = 1, /obj/item/stack/sheet/leather = 1) + time = 60 + category = CAT_CLOTHING diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index b7f395afce0..d95d7b5d4fe 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -178,7 +178,7 @@ icon = 'icons/obj/custom_items.dmi' icon_state = "book_berner_1" -/obj/item/clothing/glasses/sunglasses/fake/fluff/kaki //Rapidvalj: Kakicharakiti +/obj/item/clothing/glasses/sunglasses_fake/fluff/kaki //Rapidvalj: Kakicharakiti name = "broken thermonocle" desc = "A weathered Vox thermonocle, doesn't seem to work anymore." icon_state = "thermoncle" @@ -1212,16 +1212,16 @@ //////////// Sets //////////// // Fox P McCloud: Fox McCloud -/obj/item/clothing/suit/jacket/fluff/fox +/obj/item/clothing/suit/storage/fox name = "Aeronautics Jacket" desc = "An aviator styled jacket made from a peculiar material; this one seems very old." icon = 'icons/obj/custom_items.dmi' icon_state = "fox_jacket" item_state = "fox_jacket" - ignore_suitadjust = TRUE - actions_types = list() - adjust_flavour = null - sprite_sheets = null + allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/gun/projectile/automatic/pistol, /obj/item/gun/projectile/revolver, /obj/item/gun/projectile/revolver/detective) + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT /obj/item/clothing/under/fluff/fox name = "Aeronautics Jumpsuit" @@ -1232,6 +1232,12 @@ item_color = "fox_suit" displays_id = FALSE //still appears on examine; this is pure fluff. +/obj/item/clothing/suit/storage/fox/miljacket_desert + name = "rugged military jacket" + desc = "A rugged brown military jacket with a stylized 'A' embroidered on the back. It seems very old, yet is in near mint condition. Has a tag on the inside collar signed 'Fox McCloud'." + icon_state = "fox_coat" + item_color = "fox_coat" + /obj/item/toy/plushie/fluff/fox name = "orange fox plushie" desc = "A cute, soft, fuzzy, fluffy, and cuddly plushie. This has a small tag on it that is signed 'Fox McCloud'." @@ -1262,12 +1268,6 @@ /obj/item/toy/plushie/fluff/fox/ui_action_click() change_color() -/obj/item/clothing/suit/jacket/miljacket/desert/fox - name = "rugged military jacket" - desc = "A rugged brown military jacket with a stylized 'A' embroidered on the back. It seems very old, yet is in near mint condition. Has a tag on the inside collar signed 'Fox McCloud'." - icon = 'icons/obj/custom_items.dmi' - icon_state = "fox_coat" - item_color = "fox_coat" // TheFlagbearer: Willow Walker /obj/item/clothing/under/fluff/arachno_suit diff --git a/code/modules/hydroponics/grown/cotton.dm b/code/modules/hydroponics/grown/cotton.dm new file mode 100644 index 00000000000..3fa4247f578 --- /dev/null +++ b/code/modules/hydroponics/grown/cotton.dm @@ -0,0 +1,79 @@ +/obj/item/seeds/cotton + name = "pack of cotton seeds" + desc = "A pack of seeds that'll grow into a cotton plant. Assistants make good free labor if neccesary." + icon_state = "seed-cotton" + species = "cotton" + plantname = "Cotton" + icon_harvest = "cotton-harvest" + product = /obj/item/grown/cotton + lifespan = 35 + endurance = 25 + maturation = 15 + production = 1 + yield = 2 + potency = 50 + growthstages = 3 + growing_icon = 'icons/obj/hydroponics/growing.dmi' + icon_dead = "cotton-dead" + mutatelist = list(/obj/item/seeds/cotton/durathread) + +/obj/item/grown/cotton + seed = /obj/item/seeds/cotton + name = "cotton bundle" + desc = "A fluffy bundle of cotton." + icon_state = "cotton" + force = 0 + throwforce = 0 + w_class = WEIGHT_CLASS_TINY + throw_speed = 2 + throw_range = 3 + attack_verb = list("pomfed") + var/cotton_type = /obj/item/stack/sheet/cotton + var/cotton_name = "raw cotton" + +/obj/item/grown/cotton/attack_self(mob/user) + user.show_message("You pull some [cotton_name] out of the [name]!", 1) + var/seed_modifier = 0 + if(seed) + seed_modifier = round(seed.potency / 25) + var/obj/item/stack/cotton = new cotton_type(user.loc, 1 + seed_modifier) + var/old_cotton_amount = cotton.amount + for(var/obj/item/stack/ST in user.loc) + if(ST != cotton && istype(ST, cotton_type) && ST.amount < ST.max_amount) + ST.attackby(cotton, user) + if(cotton.amount > old_cotton_amount) + to_chat(user, "You add the newly-formed [cotton_name] to the stack. It now contains [cotton.amount] [cotton_name].") + qdel(src) + +//reinforced mutated variant +/obj/item/seeds/cotton/durathread + name = "pack of durathread seeds" + desc = "A pack of seeds that'll grow into an extremely durable thread that could easily rival plasteel if woven properly." + icon_state = "seed-durathread" + species = "durathread" + plantname = "Durathread" + icon_harvest = "durathread-harvest" + product = /obj/item/grown/cotton/durathread + lifespan = 80 + endurance = 50 + maturation = 15 + production = 1 + yield = 2 + potency = 50 + growthstages = 3 + growing_icon = 'icons/obj/hydroponics/growing.dmi' + icon_dead = "cotton-dead" + +/obj/item/grown/cotton/durathread + seed = /obj/item/seeds/cotton/durathread + name = "durathread bundle" + desc = "A tough bundle of durathread, good luck unraveling this." + icon_state = "durathread" + force = 5 + throwforce = 5 + w_class = WEIGHT_CLASS_NORMAL + throw_speed = 2 + throw_range = 3 + attack_verb = list("bashed", "battered", "bludgeoned", "whacked") + cotton_type = /obj/item/stack/sheet/cotton/durathread + cotton_name = "raw durathread" \ No newline at end of file diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index c8145033545..3aaa8d87041 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -88,7 +88,7 @@ make_podman = 0 if(make_podman) //all conditions met! - var/mob/living/carbon/human/diona/podman = new /mob/living/carbon/human/diona(parent.loc) + var/mob/living/carbon/human/pod_diona/podman = new /mob/living/carbon/human/pod_diona(parent.loc) if(realName) podman.real_name = realName mind.transfer_to(podman) diff --git a/code/modules/hydroponics/grown/root.dm b/code/modules/hydroponics/grown/root.dm index e7cdcee2cad..56fee727a20 100644 --- a/code/modules/hydroponics/grown/root.dm +++ b/code/modules/hydroponics/grown/root.dm @@ -95,7 +95,7 @@ /obj/item/seeds/redbeet name = "pack of redbeet seeds" desc = "These seeds grow into red beet producing plants." - icon_state = "seedredbeet" + icon_state = "seed-redbeet" species = "redbeet" plantname = "Red Beet Plants" product = /obj/item/reagent_containers/food/snacks/grown/redbeet diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index 47b3fb01501..d340e6069cc 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -209,7 +209,7 @@ if(istype(T, denied_type) || istype(src, T.denied_type)) to_chat(user, "You can't seem to attach [src] to [H]. Maybe remove a few trophies?") return FALSE - if(!user.drop_item()) + if(!user.unEquip(src)) return forceMove(H) H.trophies += src diff --git a/code/modules/mining/equipment/lazarus_injector.dm b/code/modules/mining/equipment/lazarus_injector.dm index dcd0916d876..0f174ff748f 100644 --- a/code/modules/mining/equipment/lazarus_injector.dm +++ b/code/modules/mining/equipment/lazarus_injector.dm @@ -73,9 +73,10 @@ icon = 'icons/obj/mobcap.dmi' icon_state = "mobcap0" w_class = WEIGHT_CLASS_TINY - throw_range = 20 + throw_range = 7 var/mob/living/simple_animal/captured = null var/colorindex = 0 + var/capture_type = SENTIENCE_ORGANIC //So you can't capture boss monsters or robots with it /obj/item/mobcapsule/Destroy() if(captured) @@ -83,26 +84,25 @@ QDEL_NULL(captured) return ..() -/obj/item/mobcapsule/attack(var/atom/A, mob/user, prox_flag) - if(!istype(A, /mob/living/simple_animal) || isbot(A)) - return ..() - capture(A, user) - return 1 +/obj/item/mobcapsule/attack(mob/living/simple_animal/S, mob/user, prox_flag) + if(istype(S) && S.sentience_type == capture_type) + capture(S, user) + return TRUE + return ..() -/obj/item/mobcapsule/proc/capture(var/mob/target, var/mob/U as mob) - var/mob/living/simple_animal/T = target +/obj/item/mobcapsule/proc/capture(mob/living/simple_animal/S, mob/living/M) if(captured) - to_chat(U, "Capture failed!: The capsule already has a mob registered to it!") + to_chat(M, "Capture failed!: The capsule already has a mob registered to it!") else - if(istype(T) && "neutral" in T.faction) - T.forceMove(src) - T.name = "[U.name]'s [initial(T.name)]" - T.cancel_camera() - name = "Lazarus Capsule: [initial(T.name)]" - to_chat(U, "You placed a [T.name] inside the Lazarus Capsule!") - captured = T + if("neutral" in S.faction) + S.forceMove(src) + S.name = "[M.name]'s [initial(S.name)]" + S.cancel_camera() + name = "Lazarus Capsule: [initial(S.name)]" + to_chat(M, "You placed a [S.name] inside the Lazarus Capsule!") + captured = S else - to_chat(U, "You can't capture that mob!") + to_chat(M, "You can't capture that mob!") /obj/item/mobcapsule/throw_impact(atom/A, mob/user) ..() diff --git a/code/modules/mining/lavaland/loot/tendril_loot.dm b/code/modules/mining/lavaland/loot/tendril_loot.dm index c8579fbec65..3727c103a64 100644 --- a/code/modules/mining/lavaland/loot/tendril_loot.dm +++ b/code/modules/mining/lavaland/loot/tendril_loot.dm @@ -77,6 +77,21 @@ add_fingerprint(M) +//Book of Babel + +/obj/item/book_of_babel + name = "Book of Babel" + desc = "An ancient tome written in countless tongues." + icon = 'icons/obj/library.dmi' + icon_state = "book1" + w_class = 2 + +/obj/item/book_of_babel/attack_self(mob/user) + to_chat(user, "You flip through the pages of the book, quickly and conveniently learning every language in existence. Somewhat less conveniently, the aging book crumbles to dust in the process. Whoops.") + user.grant_all_languages() + new /obj/effect/decal/cleanable/ash(get_turf(user)) + qdel(src) + //Potion of Flight: as we do not have the "Angel" species this currently does not work. /obj/item/reagent_containers/glass/bottle/potion @@ -117,6 +132,30 @@ H.emote("scream") ..()*/ +/obj/item/jacobs_ladder + name = "jacob's ladder" + desc = "A celestial ladder that violates the laws of physics." + icon = 'icons/obj/structures.dmi' + icon_state = "ladder00" + +/obj/item/jacobs_ladder/attack_self(mob/user) + var/turf/T = get_turf(src) + var/ladder_x = T.x + var/ladder_y = T.y + to_chat(user, "You unfold the ladder. It extends much farther than you were expecting.") + var/last_ladder = null + for(var/i in 1 to world.maxz) + if(is_admin_level(i) || is_away_level(i)) + continue + var/turf/T2 = locate(ladder_x, ladder_y, i) + last_ladder = new /obj/structure/ladder/unbreakable/jacob(T2, null, last_ladder) + qdel(src) + +// Inherit from unbreakable but don't set ID, to suppress the default Z linkage +/obj/structure/ladder/unbreakable/jacob + name = "jacob's ladder" + desc = "An indestructible celestial ladder that violates the laws of physics." + //Boat /obj/vehicle/lavaboat diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index a2ee237c659..1a0a063e33f 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -18,7 +18,7 @@ if(!add_loot) return - var/loot = rand(1,25) + var/loot = rand(1, 26) switch(loot) if(1) new /obj/item/shared_storage/red(src) @@ -48,7 +48,7 @@ if(11) new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/berserker(src) if(12) - new /obj/item/sord(src) + new /obj/item/jacobs_ladder(src) if(13) new /obj/item/nullrod/scythe/talking(src) if(14) @@ -78,6 +78,8 @@ if(24) new /obj/item/spellbook/oneuse/summonitem(src) if(25) + new /obj/item/book_of_babel(src) + if(26) new /obj/item/borg/upgrade/modkit/lifesteal(src) new /obj/item/bedsheet/cult(src) diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index 229b9053ae6..4de84bb70c4 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -37,7 +37,7 @@ new /datum/data/mining_equipment("Lazarus Injector", /obj/item/lazarus_injector, 1000), new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/pickaxe/silver, 1000), new /datum/data/mining_equipment("Mining Conscription Kit", /obj/item/storage/backpack/duffel/mining_conscript, 1500), - new /datum/data/mining_equipment("Jetpack", /obj/item/tank/jetpack/carbondioxide/mining, 2000), + new /datum/data/mining_equipment("Jetpack Upgrade", /obj/item/tank/jetpack/suit, 2000), new /datum/data/mining_equipment("Mining Hardsuit", /obj/item/clothing/suit/space/hardsuit/mining, 2000), new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/pickaxe/diamond, 2000), new /datum/data/mining_equipment("Super Resonator", /obj/item/resonator/upgraded, 2500), diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index f350633a4c2..b85db884ef5 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -44,8 +44,8 @@ /obj/structure/closet/secure_closet/miner/New() ..() -// new /obj/item/stack/sheet/mineral/sandbags(src, 5) -// new /obj/item/storage/box/emptysandbags(src) + new /obj/item/stack/sheet/mineral/sandbags(src, 5) + new /obj/item/storage/box/emptysandbags(src) new /obj/item/shovel(src) new /obj/item/pickaxe/mini(src) new /obj/item/radio/headset/headset_cargo/mining(src) diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index 57725da8eb2..9391f24035a 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -762,6 +762,8 @@ desc = "Bark bark bark." key = "vu" - +/mob/proc/grant_all_languages() + for(var/la in GLOB.all_languages) + add_language(la) #undef SCRAMBLE_CACHE_LEN diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 7b8790076ce..c583d9873b6 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -16,7 +16,7 @@ /mob/living/carbon/water_act(volume, temperature, source, method = TOUCH) . = ..() - if(volume > 10) //anything over 10 volume will make the mob wetter. + if(volume > 10) // Anything over 10 volume will make the mob wetter. wetlevel = min(wetlevel + 1,5) /mob/living/carbon/attackby(obj/item/I, mob/user, params) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 4aef44444e9..1862fe5cffa 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -390,7 +390,7 @@ S = H.glasses return !istype(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/security) && S && S.read_only if("medical") - return istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(H.glasses, /obj/item/clothing/glasses/hud/health/health_advanced) || istype(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/medical) + return istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/medical) else return 0 else if(isrobot(M) || isAI(M)) //Stand-in/Stopgap to prevent pAIs from freely altering records, pending a more advanced Records system diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 20f40580fb8..561a06c291c 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -106,6 +106,9 @@ /mob/living/carbon/human/diona/Initialize(mapload) ..(mapload, /datum/species/diona) +/mob/living/carbon/human/pod_diona/Initialize(mapload) + ..(mapload, /datum/species/diona/pod) + /mob/living/carbon/human/machine/Initialize(mapload) ..(mapload, /datum/species/machine) @@ -165,7 +168,11 @@ show_stat_emergency_shuttle_eta() if(client.statpanel == "Status") - if(locate(/obj/item/assembly/health) in src) + var/total_user_contents = GetAllContents() // cache it + if(locate(/obj/item/gps) in total_user_contents) + var/turf/T = get_turf(src) + stat(null, "GPS: [COORD(T)]") + if(locate(/obj/item/assembly/health) in total_user_contents) stat(null, "Health: [health]") if(internal) if(!internal.air_contents) @@ -849,7 +856,7 @@ return var/read = 0 var/perpname = get_visible_name(TRUE) - + for(var/datum/data/record/E in data_core.general) if(E.fields["name"] == perpname) for(var/datum/data/record/R in data_core.medical) @@ -1096,17 +1103,22 @@ var/limb_path = organ_data["path"] var/obj/item/organ/external/O = new limb_path(temp_holder) if(H.get_limb_by_name(O.name)) //Check to see if the user already has an limb with the same name as the 'missing limb'. If they do, skip regrowth. - continue //In an example, this will prevent duplication of the mob's right arm if the mob is a Human and they have a Diona right arm, since, - //while the limb with the name 'right_arm' the mob has may not be listed in their species' bodyparts definition, it is still viable and has the appropriate limb name. + continue //In an example, this will prevent duplication of the mob's right arm if the mob is a Human and they have a Diona right arm, since, + //while the limb with the name 'right_arm' the mob has may not be listed in their species' bodyparts definition, it is still viable and has the appropriate limb name. else O = new limb_path(H) //Create the limb on the player. O.owner = H H.bodyparts |= H.bodyparts_by_name[O.limb_name] + if(O.body_part == HEAD) //They're sprouting a fresh head so lets hook them up with their genetic stuff so their new head looks like the original. + H.UpdateAppearance() //Replacing lost organs with the species default. temp_holder = new /mob/living/carbon/human() - for(var/index in H.dna.species.has_organ) - var/organ = H.dna.species.has_organ[index] + var/list/species_organs = H.dna.species.has_organ.Copy() //Compile a list of species organs and tack on the mutantears afterward. + if(H.dna.species.mutantears) + species_organs["ears"] = H.dna.species.mutantears + for(var/index in species_organs) + var/organ = species_organs[index] if(!(organ in types_of_int_organs)) //If the mob is missing this particular organ... var/obj/item/organ/internal/I = new organ(temp_holder) //Create the organ inside our holder so we can check it before implantation. if(H.get_organ_slot(I.slot)) //Check to see if the user already has an organ in the slot the 'missing organ' belongs to. If they do, skip implantation. @@ -1470,12 +1482,12 @@ var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes) var/obj/item/organ/internal/cyberimp/eyes/eye_implant = get_int_organ(/obj/item/organ/internal/cyberimp/eyes) if(istype(dna.species) && dna.species.eyes) - var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', dna.species.eyes) + var/icon/eyes_icon = new /icon('icons/mob/human_face.dmi', dna.species.eyes) if(eye_implant) //Eye implants override native DNA eye colo(u)r eyes_icon = eye_implant.generate_icon() else if(eyes) eyes_icon = eyes.generate_icon() - else + else //Error 404: Eyes not found! eyes_icon.Blend("#800000", ICON_ADD) return eyes_icon @@ -1484,8 +1496,8 @@ var/obj/item/organ/external/head/head_organ = get_organ("head") var/datum/sprite_accessory/hair/hair_style = GLOB.hair_styles_full_list[head_organ.h_style] var/icon/hair = new /icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - var/mutable_appearance/MA = mutable_appearance(get_icon_difference(get_eyecon(), hair), layer = LIGHTING_LAYER + 1) - MA.plane = LIGHTING_PLANE + var/mutable_appearance/MA = mutable_appearance(get_icon_difference(get_eyecon(), hair), layer = ABOVE_LIGHTING_LAYER) + MA.plane = ABOVE_LIGHTING_PLANE return MA //Cut the hair's pixels from the eyes icon so eyes covered by bangs stay hidden even while on a higher layer. /*Used to check if eyes should shine in the dark. Returns the image of the eyes on the layer where they will appear to shine. diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index e106d214fd3..3d4aadf5746 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -202,6 +202,16 @@ amount = amount * dna.species.tox_mod . = ..() +/mob/living/carbon/human/adjustStaminaLoss(amount, updating = TRUE) + if(dna.species && amount > 0) + amount = amount * dna.species.stamina_mod + . = ..() + +/mob/living/carbon/human/setStaminaLoss(amount, updating = TRUE) + if(dna.species && amount > 0) + amount = amount * dna.species.stamina_mod + . = ..() + //////////////////////////////////////////// //Returns a list of damaged organs diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index c574cf3cd53..b6bf5b34bac 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -11,10 +11,11 @@ //Do we have a working jetpack? var/obj/item/tank/jetpack/thrust - if(istype(back,/obj/item/tank/jetpack)) + if(istype(back, /obj/item/tank/jetpack)) thrust = back - else if(istype(s_store,/obj/item/tank/jetpack)) - thrust = s_store + else if(istype(wear_suit, /obj/item/clothing/suit/space/hardsuit)) + var/obj/item/clothing/suit/space/hardsuit/C = wear_suit + thrust = C.jetpack else if(istype(back,/obj/item/rig)) var/obj/item/rig/rig = back for(var/obj/item/rig_module/maneuvering_jets/module in rig.installed_modules) diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm index 438d3386948..3e295eb9b4c 100644 --- a/code/modules/mob/living/carbon/human/species/_species.dm +++ b/code/modules/mob/living/carbon/human/species/_species.dm @@ -50,6 +50,7 @@ var/oxy_mod = 1 // Oxy damage reduction/amplification var/clone_mod = 1 // Clone damage reduction/amplification var/brain_mod = 1 // Brain damage damage reduction/amplification + var/stamina_mod = 1 var/stun_mod = 1 // If a species is more/less impacated by stuns/weakens/paralysis var/blood_damage_type = OXY //What type of damage does this species take if it's low on blood? @@ -733,8 +734,8 @@ It'll return null if the organ doesn't correspond, so include null checks when u H.sync_lighting_plane_alpha() /datum/species/proc/water_act(mob/living/carbon/human/M, volume, temperature, source, method = TOUCH) - if(abs(temperature - M.bodytemperature) > 10) //If our water and mob temperature varies by more than 10K, cool or/ heat them appropriately - M.bodytemperature = (temperature + M.bodytemperature) * 0.5 //Approximation for gradual heating or cooling + if(abs(temperature - M.bodytemperature) > 10) // If our water and mob temperature varies by more than 10K, cool or/ heat them appropriately. + M.bodytemperature = (temperature + M.bodytemperature) * 0.5 // Approximation for gradual heating or cooling. /datum/species/proc/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) //return TRUE if hit, FALSE if stopped/reflected/etc return TRUE diff --git a/code/modules/mob/living/carbon/human/species/diona.dm b/code/modules/mob/living/carbon/human/species/diona.dm index bccbeb6c5a7..518ee94f8f0 100644 --- a/code/modules/mob/living/carbon/human/species/diona.dm +++ b/code/modules/mob/living/carbon/human/species/diona.dm @@ -7,21 +7,11 @@ speech_sounds = list('sound/voice/dionatalk1.ogg') //Credit https://www.youtube.com/watch?v=ufnvlRjsOTI [0:13 - 0:16] speech_chance = 20 unarmed_type = /datum/unarmed_attack/diona - //primitive_form = "Nymph" - slowdown = 5 remains_type = /obj/effect/decal/cleanable/ash - - warning_low_pressure = 50 - hazard_low_pressure = -1 - - cold_level_1 = 50 - cold_level_2 = -1 - cold_level_3 = -1 - - heat_level_1 = 300 - heat_level_2 = 340 - heat_level_3 = 400 + burn_mod = 1.25 + heatmod = 1.5 + var/pod = FALSE //did they come from a pod? If so, they're stronger than normal Diona. blurb = "Commonly referred to (erroneously) as 'plant people', the Dionaea are a strange space-dwelling collective \ species hailing from Epsilon Ursae Minoris. Each 'diona' is a cluster of numerous cat-sized organisms called nymphs; \ @@ -31,16 +21,14 @@ even the simplest concepts of other minds. Their alien physiology allows them survive happily off a diet of nothing but light, \ water and other radiation." - species_traits = list(NO_BREATHE, RADIMMUNE, IS_PLANT, NO_BLOOD, NO_PAIN) - dies_at_threshold = TRUE + species_traits = list(IS_PLANT) clothing_flags = HAS_SOCKS default_hair_colour = "#000000" has_gender = FALSE - dietflags = 0 //Diona regenerate nutrition in light and water, no diet necessary - taste_sensitivity = TASTE_SENSITIVITY_NO_TASTE + dietflags = DIET_HERB //Diona regenerate nutrition in light and water, no diet necessary, but if they must, they eat other plants *scream + taste_sensitivity = TASTE_SENSITIVITY_DULL skinned_type = /obj/item/stack/sheet/wood - body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not blood_color = "#004400" flesh_color = "#907E4A" butt_sprite = "diona" @@ -49,6 +37,7 @@ has_organ = list( "nutrient channel" = /obj/item/organ/internal/liver/diona, + "respiratory vacuoles" = /obj/item/organ/internal/lungs/diona, "neural strata" = /obj/item/organ/internal/heart/diona, "receptor node" = /obj/item/organ/internal/eyes/diona, //Default darksight of 2. "gas bladder" = /obj/item/organ/internal/brain/diona, @@ -85,29 +74,47 @@ ..() H.gender = NEUTER -/datum/species/diona/handle_life(mob/living/carbon/human/H) - H.radiation = Clamp(H.radiation, 0, 100) //We have to clamp this first, then decrease it, or there's a few edge cases of massive heals if we clamp and decrease at the same time. - var/rads = H.radiation / 25 - H.radiation = max(H.radiation-rads, 0) - H.nutrition = min(H.nutrition+rads, NUTRITION_LEVEL_WELL_FED+10) - H.adjustBruteLoss(-(rads)) - H.adjustToxLoss(-(rads)) +/datum/species/diona/handle_reagents(mob/living/carbon/human/H, datum/reagent/R) + if(R.id == "glyphosate" || R.id == "atrazine") + H.adjustToxLoss(3) //Deal aditional damage + return TRUE + return ..() +/datum/species/diona/handle_life(mob/living/carbon/human/H) + if(H.stat == DEAD) + return var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing if(isturf(H.loc)) //else, there's considered to be no light var/turf/T = H.loc - light_amount = min(T.get_lumcount() * 10, 5) //hardcapped so it's not abused by having a ton of flashlights - H.nutrition = min(H.nutrition+light_amount, NUTRITION_LEVEL_WELL_FED+10) + light_amount = min(1, T.get_lumcount()) - 0.5 + if(light_amount > 0) + H.clear_alert("nolight") + else + H.throw_alert("nolight", /obj/screen/alert/nolight) + H.nutrition += light_amount * 10 + if(H.nutrition > NUTRITION_LEVEL_ALMOST_FULL) + H.nutrition = NUTRITION_LEVEL_ALMOST_FULL + if(light_amount > 0.2 && !H.suiciding) //if there's enough light, heal + if(!pod && H.health <= 0) + return + H.adjustBruteLoss(-1) + H.adjustFireLoss(-1) + H.adjustToxLoss(-1) + H.adjustOxyLoss(-1) - if(light_amount > 0) - H.clear_alert("nolight") - else - H.throw_alert("nolight", /obj/screen/alert/nolight) - - if((light_amount >= 5) && !H.suiciding) //if there's enough light, heal - - H.adjustBruteLoss(-(light_amount/2)) - H.adjustFireLoss(-(light_amount/4)) - if(H.nutrition < NUTRITION_LEVEL_STARVING+50) - H.take_overall_damage(10,0) + if(H.nutrition < NUTRITION_LEVEL_STARVING + 50) + H.adjustBruteLoss(2) ..() + +/datum/species/diona/pod //Same name and everything; we want the same limitations on them; we just want their regeneration to kick in at all times and them to have special factions + pod = TRUE + +/datum/species/diona/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species) + . = ..() + C.faction |= "plants" + C.faction |= "vines" + +/datum/species/diona/pod/on_species_loss(mob/living/carbon/C) + . = ..() + C.faction -= "plants" + C.faction -= "vines" \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm index c1e416a8a48..9d74e7e2130 100644 --- a/code/modules/mob/living/carbon/human/species/golem.dm +++ b/code/modules/mob/living/carbon/human/species/golem.dm @@ -251,28 +251,44 @@ attack_verb = list("smash") attack_sound = 'sound/effects/meteorimpact.ogg' -//More resistant to burn damage -//Add ashstorm resistance if we ever port lavaland +//More resistant to burn damage and immune to ashstorm /datum/species/golem/titanium name = "Titanium Golem" golem_colour = rgb(255, 255, 255) skinned_type = /obj/item/stack/ore/titanium - info_text = "As a Titanium Golem, you are resistant to burn damage." + info_text = "As a Titanium Golem, you are resistant to burn damage and immune to ash storms." burn_mod = 0.3 prefix = "Titanium" special_names = list("Dioxide") -//Even more resistant to burn damage -//Add ashstorm and lava resistance if we ever port lavaland +/datum/species/golem/titanium/on_species_gain(mob/living/carbon/C, datum/species/old_species) + . = ..() + C.weather_immunities |= "ash" + +/datum/species/golem/titanium/on_species_loss(mob/living/carbon/C) + . = ..() + C.weather_immunities -= "ash" + +//Even more resistant to burn damage and immune to ashstorms and lava /datum/species/golem/plastitanium name = "Plastitanium Golem" golem_colour = rgb(136, 136, 136) skinned_type = /obj/item/stack/ore/titanium - info_text = "As a Plastitanium Golem, you are very resistant to burn damage." + info_text = "As a Plastitanium Golem, you are very resistant to burn damage and immune to both ash storms and lava." burn_mod = 0.15 prefix = "Plastitanium" special_names = null +/datum/species/golem/plastitanium/on_species_gain(mob/living/carbon/C, datum/species/old_species) + . = ..() + C.weather_immunities |= "lava" + C.weather_immunities |= "ash" + +/datum/species/golem/plastitanium/on_species_loss(mob/living/carbon/C) + . = ..() + C.weather_immunities -= "ash" + C.weather_immunities -= "lava" + //Fast and regenerates... but can only speak like an abductor /datum/species/golem/alloy name = "Alien Alloy Golem" @@ -357,10 +373,12 @@ /datum/species/golem/uranium/handle_life(mob/living/carbon/human/H) for(var/mob/living/L in range(2, H)) - if(isgolem(H)) - continue - to_chat(L, "You are enveloped by a soft green glow emanating from [H].") - L.apply_effect(10, IRRADIATE) + if(ishuman(L)) + var/mob/living/carbon/human/I = L + if(!(RADIMMUNE in I.dna.species.species_traits)) + L.apply_effect(10, IRRADIATE) + if(prob(25)) //reduce spam + to_chat(L, "You are enveloped by a soft green glow emanating from [H].") ..() //Ventcrawler @@ -592,7 +610,7 @@ punchdamagehigh = 0 punchstunthreshold = 1 //Harmless and can't stun skinned_type = /obj/item/stack/ore/bananium - info_text = "As a Bananium Golem, you are made for pranking. Your body emits natural honks, and you can barely even hurt people when punching them. Your skin also bleeds banana peels when damaged." + info_text = "As a Bananium Golem, you are made for pranking. Your body emits natural honks, and punching people will just harmlessly honk them. Your skin also bleeds banana peels when damaged." prefix = "Bananium" special_names = null unarmed_type = /datum/unarmed_attack/golem/bananium @@ -610,6 +628,12 @@ H.mutations.Add(COMIC) H.equip_to_slot_or_del(new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(H), slot_r_store) H.equip_to_slot_or_del(new /obj/item/bikehorn(H), slot_l_store) + H.AddComponent(/datum/component/waddling) + +/datum/species/golem/bananium/on_species_loss(mob/living/carbon/C) + . = ..() + GET_COMPONENT_FROM(waddling, /datum/component/waddling, C) + waddling.Destroy() /datum/species/golem/bananium/get_random_name() var/clown_name = pick(GLOB.clown_names) diff --git a/code/modules/mob/living/carbon/human/species/grey.dm b/code/modules/mob/living/carbon/human/species/grey.dm index 3b8bbe34ffb..fd8fc09fd4d 100644 --- a/code/modules/mob/living/carbon/human/species/grey.dm +++ b/code/modules/mob/living/carbon/human/species/grey.dm @@ -40,15 +40,15 @@ . = ..() if(method == TOUCH) + if(H.wear_mask) + to_chat(H, "Your [H.wear_mask] protects you from the acid!") + return + + if(H.head) + to_chat(H, "Your [H.wear_mask] protects you from the acid!") + return + if(volume > 25) - if(H.wear_mask) - to_chat(H, "Your [H.wear_mask] protects you from the acid!") - return - - if(H.head) - to_chat(H, "Your [H.wear_mask] protects you from the acid!") - return - if(prob(75)) H.take_organ_damage(5, 10) H.emote("scream") @@ -65,9 +65,6 @@ H.adjustFireLoss(min(max(4, (volume - 10) * 2), 20)) H.emote("scream") to_chat(H, "The water stings[volume < 10 ? " you, but isn't concentrated enough to harm you" : null]!") - if(volume >= 10) - H.adjustFireLoss(min(max(4, (volume - 10) * 2), 20)) - H.emote("scream") /datum/species/grey/after_equip_job(datum/job/J, mob/living/carbon/human/H) var/translator_pref = H.client.prefs.speciesprefs diff --git a/code/modules/mob/living/carbon/slime/slime.dm b/code/modules/mob/living/carbon/slime/slime.dm index 38dadbbbfa7..ddab7eae1ee 100644 --- a/code/modules/mob/living/carbon/slime/slime.dm +++ b/code/modules/mob/living/carbon/slime/slime.dm @@ -510,13 +510,15 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 /mob/living/carbon/slime/toggle_throw_mode() return -/mob/living/carbon/slime/proc/apply_water() - adjustToxLoss(rand(15,20)) - if(!client) - if(Target) // Like cats - Target = null - ++Discipline - return +/mob/living/carbon/slime/water_act(volume, temperature, source, method = TOUCH) + . = ..() + + var/water_damage = rand(10, 15) * volume + adjustToxLoss(water_damage) + + if(!client && Target && volume >= 3) + Target = null + ++Discipline /mob/living/carbon/slime/can_use_vents() if(Victim) diff --git a/code/modules/mob/living/silicon/laws.dm b/code/modules/mob/living/silicon/laws.dm index b49aa82625c..2eca24104cd 100644 --- a/code/modules/mob/living/silicon/laws.dm +++ b/code/modules/mob/living/silicon/laws.dm @@ -70,6 +70,13 @@ if(!silent && !isnull(usr)) log_and_message_admins("cleared the supplied laws of [src]") +/mob/living/silicon/proc/clear_zeroth_law(var/silent = FALSE) + throw_alert("newlaw", /obj/screen/alert/newlaw) + laws_sanity_check() + laws.clear_zeroth_laws() + if(!silent && !isnull(usr)) + log_and_message_admins("cleared the zeroth law of [src]") + /mob/living/silicon/proc/statelaws(var/datum/ai_laws/laws) var/prefix = "" if(MAIN_CHANNEL == lawchannel) diff --git a/code/modules/mob/living/simple_animal/hostile/mining/necropolis_tendril.dm b/code/modules/mob/living/simple_animal/hostile/mining/necropolis_tendril.dm index c6bc205627e..e910bac7ca3 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/necropolis_tendril.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/necropolis_tendril.dm @@ -17,6 +17,8 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 maxbodytemp = INFINITY + move_resist = INFINITY + anchored = TRUE loot = list(/obj/effect/collapse, /obj/structure/closet/crate/necropolis/tendril) del_on_death = 1 var/gps = null @@ -76,4 +78,4 @@ mob_types = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/tendril) /mob/living/simple_animal/hostile/spawner/lavaland/legion - mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril) \ No newline at end of file + mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril) diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index 077164be6b7..805d48fdd9f 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -409,12 +409,6 @@ qdel(src) /obj/item/grab/proc/checkvalid(var/mob/attacker, var/mob/prey) //does all the checking for the attack proc to see if a mob can eat another with the grab - if(ishuman(attacker) && (/datum/dna/gene/basic/grant_spell/mattereater in attacker.active_genes)) // MATTER EATER CARES NOT OF YOUR FORM - return 1 - - if(ishuman(attacker) && (FAT in attacker.mutations) && iscarbon(prey) && !isalien(prey)) //Fat people eating carbon mobs but not xenos - return 1 - if(isalien(attacker) && iscarbon(prey)) //Xenomorphs eating carbon mobs return 1 diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 0dc634bd958..fbc29da0391 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -124,12 +124,6 @@ else user.visible_message("[user] fires [src]!", "You fire [src]!", "You hear \a [fire_sound_text]!") - if(weapon_weight >= WEAPON_MEDIUM) - if(user.get_inactive_hand()) - if(prob(15)) - if(user.drop_item()) - user.visible_message("[src] flies out of [user]'s hands!", "[src] kicks out of your grip!") - /obj/item/gun/emp_act(severity) for(var/obj/O in contents) O.emp_act(severity) @@ -174,7 +168,20 @@ to_chat(user, "You need both hands free to fire \the [src]!") return - process_fire(target,user,1,params) + //DUAL WIELDING + var/bonus_spread = 0 + var/loop_counter = 0 + if(ishuman(user) && user.a_intent == INTENT_HARM) + var/mob/living/carbon/human/H = user + for(var/obj/item/gun/G in get_both_hands(H)) + if(G == src || G.weapon_weight >= WEAPON_MEDIUM) + continue + else if(G.can_trigger_gun(user)) + bonus_spread += 24 * G.weapon_weight + loop_counter++ + addtimer(CALLBACK(G, .proc/process_fire, target, user, 1, params, null, bonus_spread), loop_counter) + + process_fire(target,user,1,params, null, bonus_spread) /obj/item/gun/proc/can_trigger_gun(mob/living/user) if(!user.can_use_guns(src)) @@ -187,17 +194,17 @@ /obj/item/gun/proc/newshot() return -/obj/item/gun/proc/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override) +/obj/item/gun/proc/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override, bonus_spread = 0) add_fingerprint(user) if(semicd) return - if(weapon_weight) - if(user.get_inactive_hand()) - recoil = 4 //one-handed kick - else - recoil = initial(recoil) + var/sprd = 0 + var/randomized_gun_spread = 0 + if(spread) + randomized_gun_spread = rand(0,spread) + var/randomized_bonus_spread = rand(0, bonus_spread) if(burst_size > 1) firing_burst = 1 @@ -208,11 +215,10 @@ if( i>1 && !(src in get_both_hands(user))) //for burst firing break if(chambered) - var/sprd = 0 if(randomspread) - sprd = round((rand() - 0.5) * spread) + sprd = round((rand() - 0.5) * (randomized_gun_spread + randomized_bonus_spread)) else - sprd = round((i / burst_size - 0.5) * spread) + sprd = round((i / burst_size - 0.5) * (randomized_gun_spread + randomized_bonus_spread)) if(!chambered.fire(target, user, params, ,suppressed, zone_override, sprd)) shoot_with_empty_chamber(user) break @@ -230,7 +236,8 @@ firing_burst = 0 else if(chambered) - if(!chambered.fire(target, user, params, , suppressed, zone_override, spread)) + sprd = round((pick(1,-1)) * (randomized_gun_spread + randomized_bonus_spread)) + if(!chambered.fire(target, user, params, , suppressed, zone_override, sprd)) shoot_with_empty_chamber(user) return else diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 6e4de3c49fa..3fbfcdaa934 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -21,6 +21,12 @@ /obj/item/gun/energy/emp_act(severity) power_supply.use(round(power_supply.charge / severity)) + if(chambered)//phil235 + if(chambered.BB) + qdel(chambered.BB) + chambered.BB = null + chambered = null + newshot() //phil235 update_icon() /obj/item/gun/energy/get_cell() @@ -34,6 +40,7 @@ power_supply = new(src) power_supply.give(power_supply.maxcharge) update_ammo_types() + on_recharge() if(selfcharge) START_PROCESSING(SSobj, src) update_icon() @@ -67,8 +74,12 @@ if(!external || !external.use(E.e_cost)) //Take power from the borg... return //Note, uses /10 because of shitty mods to the cell system power_supply.give(100) //... to recharge the shot + on_recharge() update_icon() +/obj/item/gun/energy/proc/on_recharge() + newshot() + /obj/item/gun/energy/attack_self(mob/living/user as mob) if(ammo_type.len > 1) select_fire(user) @@ -78,10 +89,6 @@ H.update_inv_l_hand() H.update_inv_r_hand() -/obj/item/gun/energy/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, params) - newshot() //prepare a new shot - ..() - /obj/item/gun/energy/can_shoot() var/obj/item/ammo_casing/energy/shot = ammo_type[select] return power_supply.charge >= shot.e_cost @@ -89,18 +96,20 @@ /obj/item/gun/energy/newshot() if(!ammo_type || !power_supply) return - var/obj/item/ammo_casing/energy/shot = ammo_type[select] - if(power_supply.charge >= shot.e_cost) //if there's enough power in the power_supply cell... - chambered = shot //...prepare a new shot based on the current ammo type selected - chambered.newshot() - return + if(!chambered) + var/obj/item/ammo_casing/energy/shot = ammo_type[select] + if(power_supply.charge >= shot.e_cost) //if there's enough power in the power_supply cell... + chambered = shot //...prepare a new shot based on the current ammo type selected + if(!chambered.BB) + chambered.newshot() /obj/item/gun/energy/process_chamber() if(chambered && !chambered.BB) //if BB is null, i.e the shot has been fired... var/obj/item/ammo_casing/energy/shot = chambered power_supply.use(shot.e_cost)//... drain the power_supply cell + robocharge() chambered = null //either way, released the prepared shot - return + newshot() /obj/item/gun/energy/proc/select_fire(mob/living/user) select++ @@ -111,6 +120,12 @@ fire_delay = shot.delay if(shot.select_name) to_chat(user, "[src] is now set to [shot.select_name].") + if(chambered)//phil235 + if(chambered.BB) + qdel(chambered.BB) + chambered.BB = null + chambered = null + newshot() update_icon() return diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index d214309728e..b93ddefd0d5 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -134,6 +134,7 @@ /obj/item/gun/energy/kinetic_accelerator/proc/reload() power_supply.give(500) + on_recharge() if(!suppressed) playsound(loc, 'sound/weapons/kenetic_reload.ogg', 60, 1) else if(isliving(loc)) diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm index 6cc27a08f09..949ee16fa06 100644 --- a/code/modules/projectiles/guns/energy/nuclear.dm +++ b/code/modules/projectiles/guns/energy/nuclear.dm @@ -79,7 +79,7 @@ slot_flags = null w_class = WEIGHT_CLASS_HUGE ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/laser) - weapon_weight = WEAPON_MEDIUM + weapon_weight = WEAPON_HEAVY can_flashlight = 0 trigger_guard = TRIGGER_GUARD_NONE ammo_x_offset = 2 diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index be60248cded..4499fca3797 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -168,11 +168,13 @@ var/obj/item/stack/sheet/S = A S.use(1) power_supply.give(1000) + on_recharge() to_chat(user, "You insert [A] in [src], recharging it.") else if(istype(A, /obj/item/stack/ore/plasma)) var/obj/item/stack/ore/S = A S.use(1) power_supply.give(500) + on_recharge() to_chat(user, "You insert [A] in [src], recharging it.") else return ..() @@ -251,10 +253,6 @@ /obj/item/gun/energy/printer/emp_act() return -/obj/item/gun/energy/printer/newshot() - ..() - robocharge() - // Instakill Lasers // /obj/item/gun/energy/laser/instakill name = "instakill rifle" diff --git a/code/modules/projectiles/guns/projectile/saw.dm b/code/modules/projectiles/guns/projectile/saw.dm index 9002f12ff35..5b70f2b3282 100644 --- a/code/modules/projectiles/guns/projectile/saw.dm +++ b/code/modules/projectiles/guns/projectile/saw.dm @@ -7,7 +7,7 @@ slot_flags = 0 origin_tech = "combat=6;engineering=3;syndicate=6" mag_type = /obj/item/ammo_box/magazine/mm556x45 - weapon_weight = WEAPON_MEDIUM + weapon_weight = WEAPON_HEAVY fire_sound = 'sound/weapons/gunshots/gunshot_mg.ogg' magin_sound = 'sound/weapons/gun_interactions/lmg_magin.ogg' magout_sound = 'sound/weapons/gun_interactions/lmg_magout.ogg' diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm index 46286bef2af..8b658911b3b 100644 --- a/code/modules/projectiles/guns/projectile/shotgun.dm +++ b/code/modules/projectiles/guns/projectile/shotgun.dm @@ -11,6 +11,7 @@ mag_type = /obj/item/ammo_box/magazine/internal/shot fire_sound = 'sound/weapons/gunshots/gunshot_shotgun.ogg' var/recentpump = 0 // to prevent spammage + weapon_weight = WEAPON_MEDIUM /obj/item/gun/projectile/shotgun/attackby(obj/item/A, mob/user, params) . = ..() diff --git a/code/modules/projectiles/guns/projectile/sniper.dm b/code/modules/projectiles/guns/projectile/sniper.dm index e030c9afb2a..b310ce6d884 100644 --- a/code/modules/projectiles/guns/projectile/sniper.dm +++ b/code/modules/projectiles/guns/projectile/sniper.dm @@ -4,7 +4,7 @@ icon_state = "sniper" item_state = "sniper" recoil = 2 - weapon_weight = WEAPON_MEDIUM + weapon_weight = WEAPON_HEAVY mag_type = /obj/item/ammo_box/magazine/sniper_rounds fire_sound = 'sound/weapons/gunshots/gunshot_sniper.ogg' magin_sound = 'sound/weapons/gun_interactions/batrifle_magin.ogg' diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index d5e26182ecc..5dabd8a9db6 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -184,8 +184,10 @@ var/randomize = pick("robot", "slime", "xeno", "human", "animal") switch(randomize) if("robot") + var/path if(prob(30)) - new_mob = new /mob/living/silicon/robot/syndicate(M.loc) + path = pick(typesof(/mob/living/silicon/robot/syndicate)) + new_mob = new path(M.loc) else new_mob = new /mob/living/silicon/robot(M.loc) new_mob.gender = M.gender @@ -193,6 +195,10 @@ new_mob.job = "Cyborg" var/mob/living/silicon/robot/Robot = new_mob Robot.mmi = new /obj/item/mmi(new_mob) + Robot.lawupdate = FALSE + Robot.connected_ai = null + Robot.clear_inherent_laws() + Robot.clear_zeroth_law() if(ishuman(M)) Robot.mmi.transfer_identity(M) //Does not transfer key/client. if("slime") diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index de11cb557a9..41646c114af 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -143,7 +143,6 @@ M.apply_effect((rand(30,80)),IRRADIATE) M.Weaken(5) M.visible_message("[M] writhes in pain as [M.p_their()] vacuoles boil.", "You writhe in pain as your vacuoles boil!", "You hear the crunching of leaves.") - if(prob(35)) if(prob(80)) randmutb(M) domutcheck(M,null) diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm index 6a65b538788..09ee8cb3948 100644 --- a/code/modules/reagents/chemistry/reagents/medicine.dm +++ b/code/modules/reagents/chemistry/reagents/medicine.dm @@ -668,6 +668,7 @@ color = "#A0E85E" metabolization_rate = 0.2 taste_description = "life" + var/revive_type = SENTIENCE_ORGANIC //So you can't revive boss monsters or robots with it /datum/reagent/medicine/strange_reagent/on_mob_life(mob/living/M) var/update_flags = STATUS_UPDATE_NONE @@ -680,13 +681,14 @@ if(volume < 1) // gotta pay to play return ..() - if(isanimal(M)) - if(method == TOUCH) - var/mob/living/simple_animal/SM = M - if(SM.stat == DEAD) - SM.revive() - SM.loot.Cut() //no abusing strange reagent for unlimited farming of resources - SM.visible_message("[M] seems to rise from the dead!") + if(isanimal(M) && method == TOUCH) + var/mob/living/simple_animal/SM = M + if(SM.sentience_type != revive_type) // No reviving Ash Drakes for you + return + if(SM.stat == DEAD) + SM.revive() + SM.loot.Cut() //no abusing strange reagent for farming unlimited resources + SM.visible_message("[SM] seems to rise from the dead!") if(iscarbon(M)) if(method == INGEST || (method == TOUCH && prob(25))) diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm index 571b2349b62..7ebdb1b6912 100644 --- a/code/modules/reagents/chemistry/reagents/toxins.dm +++ b/code/modules/reagents/chemistry/reagents/toxins.dm @@ -993,10 +993,10 @@ C.adjustToxLoss(lethality) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(IS_PLANT in H.dna.species.species_traits) //plantmen take a LOT of damage - H.adjustToxLoss(50) + if(IS_PLANT in H.dna.species.species_traits) //plantmen take extra damage + H.adjustToxLoss(3) ..() - else if(istype(M, /mob/living/simple_animal/diona)) //plantmen monkeys (diona) take EVEN MORE damage + else if(istype(M, /mob/living/simple_animal/diona)) //nymphs take EVEN MORE damage var/mob/living/simple_animal/diona/D = M D.adjustHealth(100) ..() diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index f7719c4fd54..6a5d85e0631 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -1036,6 +1036,7 @@ if(O.currTag > 0)// Tag set sortType = O.currTag + name = GLOB.TAGGERLOCATIONS[O.currTag] playsound(src.loc, 'sound/machines/twobeep.ogg', 100, 1) var/tag = uppertext(GLOB.TAGGERLOCATIONS[O.currTag]) to_chat(user, "Changed filter to [tag]") diff --git a/code/modules/response_team/ert_outfits.dm b/code/modules/response_team/ert_outfits.dm index 184ce84c50e..f4ab9561bd5 100644 --- a/code/modules/response_team/ert_outfits.dm +++ b/code/modules/response_team/ert_outfits.dm @@ -323,7 +323,7 @@ shoes = /obj/item/clothing/shoes/white gloves = /obj/item/clothing/gloves/color/latex/nitrile suit = /obj/item/clothing/suit/space/hardsuit/ert/medical - glasses = /obj/item/clothing/glasses/hud/health/health_advanced + glasses = /obj/item/clothing/glasses/hud/health/sunglasses suit_store = /obj/item/gun/energy/gun cybernetic_implants = list( /obj/item/organ/internal/cyberimp/arm/surgery, diff --git a/code/modules/ruins/lavalandruin_code/seed_vault.dm b/code/modules/ruins/lavalandruin_code/seed_vault.dm index 21cf86b4a07..db16c7b3a71 100644 --- a/code/modules/ruins/lavalandruin_code/seed_vault.dm +++ b/code/modules/ruins/lavalandruin_code/seed_vault.dm @@ -17,7 +17,7 @@ density = TRUE roundstart = FALSE death = FALSE - mob_species = /datum/species/diona + mob_species = /datum/species/diona/pod flavour_text = "You are a sentient ecosystem, an example of the mastery over life that your creators possessed. Your masters, benevolent as they were, created uncounted \ seed vaults and spread them across the universe to every planet they could chart. You are in one such seed vault. Your goal is to cultivate and spread life wherever it will go while waiting \ for contact from your creators. Estimated time of last contact: Deployment, 5x10^3 millennia ago." diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index 42e710d0cf6..0a11a4397ad 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -65,3 +65,11 @@ . = ..() if(!S1.lock_shuttle_doors && id_tag == "s_docking_airlock") INVOKE_ASYNC(src, .proc/unlock) + +/obj/structure/ladder/onShuttleMove() + if(resistance_flags & INDESTRUCTIBLE) + // simply don't be moved + return FALSE + disconnect() + LateInitialize() + return ..() \ No newline at end of file diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index bda89160be4..8c96837e9d5 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -349,7 +349,7 @@ if(mode != SHUTTLE_CALL) return - invertTimer() + timer = world.time - timeLeft(1) mode = SHUTTLE_RECALL /obj/docking_port/mobile/proc/enterTransit() @@ -650,8 +650,9 @@ create_ripples(destination) /obj/docking_port/mobile/proc/setTimer(wait) - timer = world.time + wait - last_timer_length = wait + if(timer <= 0) + timer = world.time + timer += wait - timeLeft(1) /obj/docking_port/mobile/proc/modTimer(multiple) var/time_remaining = timer - world.time diff --git a/code/modules/surgery/organs/organ_icon.dm b/code/modules/surgery/organs/organ_icon.dm index f291f61c96d..ef2f729811c 100644 --- a/code/modules/surgery/organs/organ_icon.dm +++ b/code/modules/surgery/organs/organ_icon.dm @@ -87,67 +87,68 @@ var/global/list/limb_icon_cache = list() else if(s_col) mob_icon.Blend(s_col, ICON_ADD) + if(owner) //Maintains overlays on disembodied parts. + cut_overlays() + dir = EAST icon = mob_icon return mob_icon /obj/item/organ/external/head/get_icon() - ..() - overlays.Cut() if(!owner) return if(dna.species.has_organ["eyes"]) var/icon/eyes_icon = owner.get_eyecon() if(eyes_icon) - mob_icon.Blend(eyes_icon, ICON_OVERLAY) - overlays |= eyes_icon + mob_icon.Blend(eyes_icon, ICON_OVERLAY) //This is required since update_icons.dm relies on this proc to render non-shining eyes. + add_overlay(eyes_icon) if(owner.lip_style && (LIPS in dna.species.species_traits)) - var/icon/lip_icon = new/icon('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s") - overlays |= lip_icon - mob_icon.Blend(lip_icon, ICON_OVERLAY) + add_overlay(mutable_appearance('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s")) //Hefty icon not necessary. var/head_marking = owner.m_styles["head"] - if(head_marking && head_marking != "None") + if(head_marking) var/datum/sprite_accessory/head_marking_style = GLOB.marking_styles_list[head_marking] if(head_marking_style && head_marking_style.species_allowed && (dna.species.name in head_marking_style.species_allowed) && head_marking_style.marking_location == "head") - var/icon/h_marking_s = new/icon("icon" = head_marking_style.icon, "icon_state" = "[head_marking_style.icon_state]_s") + var/icon/h_marking_s = new /icon("icon" = head_marking_style.icon, "icon_state" = "[head_marking_style.icon_state]_s") if(head_marking_style.do_colouration) h_marking_s.Blend(owner.m_colours["head"], ICON_ADD) - overlays |= h_marking_s + add_overlay(h_marking_s) - if(ha_style) - var/datum/sprite_accessory/head_accessory_style = GLOB.head_accessory_styles_list[ha_style] - if(head_accessory_style && head_accessory_style.species_allowed && (dna.species.name in head_accessory_style.species_allowed)) - var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") - if(head_accessory_style.do_colouration) - head_accessory_s.Blend(headacc_colour, ICON_ADD) - overlays |= head_accessory_s + if(!((owner.head && (owner.head.flags & BLOCKHAIR)) || (owner.wear_mask && (owner.wear_mask.flags & BLOCKHAIR)))) //Common restriction for all the below features. + if(ha_style) + var/datum/sprite_accessory/head_accessory_style = GLOB.head_accessory_styles_list[ha_style] + if(head_accessory_style && head_accessory_style.species_allowed && (dna.species.name in head_accessory_style.species_allowed)) + var/icon/head_accessory_s = new /icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") + if(head_accessory_style.do_colouration) + head_accessory_s.Blend(headacc_colour, ICON_ADD) + add_overlay(head_accessory_s) - if(f_style) - var/datum/sprite_accessory/facial_hair_style = GLOB.facial_hair_styles_list[f_style] - if(facial_hair_style && ((facial_hair_style.species_allowed && (dna.species.name in facial_hair_style.species_allowed)) || (dna.species.bodyflags & ALL_RPARTS))) - var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(istype(dna.species, /datum/species/slime)) // I am el worstos - facial_s.Blend("[owner.skin_colour]A0", ICON_AND) //A0 = 160 alpha. - else if(facial_hair_style.do_colouration) - facial_s.Blend(facial_colour, ICON_ADD) - overlays |= facial_s + if(f_style) + var/datum/sprite_accessory/facial_hair_style = GLOB.facial_hair_styles_list[f_style] + if(facial_hair_style && ((facial_hair_style.species_allowed && (dna.species.name in facial_hair_style.species_allowed)) || (dna.species.bodyflags & ALL_RPARTS))) + var/icon/facial_s = new /icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") + if(istype(dna.species, /datum/species/slime)) // I am el worstos + facial_s.Blend("[owner.skin_colour]A0", ICON_AND) //A0 = 160 alpha. + else if(facial_hair_style.do_colouration) + facial_s.Blend(facial_colour, ICON_ADD) + add_overlay(facial_s) - if(h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR))) - var/datum/sprite_accessory/hair_style = GLOB.hair_styles_full_list[h_style] - if(hair_style && ((dna.species.name in hair_style.species_allowed) || (dna.species.bodyflags & ALL_RPARTS))) - var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - if(istype(dna.species, /datum/species/slime)) // I am el worstos - hair_s.Blend("[owner.skin_colour]A0", ICON_AND) //A0 = 160 alpha. - else if(hair_style.do_colouration) - hair_s.Blend(hair_colour, ICON_ADD) - overlays |= hair_s + if(h_style) + if(!owner.isSynthetic() || (owner.isSynthetic() && ((owner.head && (owner.head.flags & BLOCKHEADHAIR)) || (owner.wear_mask && (owner.wear_mask.flags & BLOCKHEADHAIR))))) + var/datum/sprite_accessory/hair_style = GLOB.hair_styles_full_list[h_style] + if(hair_style && ((dna.species.name in hair_style.species_allowed) || (dna.species.bodyflags & ALL_RPARTS))) + var/icon/hair_s = new /icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") + if(istype(dna.species, /datum/species/slime)) // I am el worstos + hair_s.Blend("[owner.skin_colour]A0", ICON_AND) //A0 = 160 alpha. + else if(hair_style.do_colouration) + hair_s.Blend(hair_colour, ICON_ADD) + add_overlay(hair_s) - return mob_icon + return mob_icon //Don't need to blend the above into this as it's handled in human/update_icons(). The overlays are for rendering stuff on disembodied heads. /obj/item/organ/external/proc/get_icon_state(skeletal) var/gender diff --git a/code/modules/surgery/organs/subtypes/diona.dm b/code/modules/surgery/organs/subtypes/diona.dm index be05b2917c3..0e76c8fe20b 100644 --- a/code/modules/surgery/organs/subtypes/diona.dm +++ b/code/modules/surgery/organs/subtypes/diona.dm @@ -2,7 +2,6 @@ name = "core trunk" max_damage = 200 min_broken_damage = 50 - cannot_break = 1 amputation_point = "trunk" encased = null gendered_icon = 0 @@ -10,7 +9,6 @@ /obj/item/organ/external/groin/diona name = "fork" min_broken_damage = 50 - cannot_break = 1 amputation_point = "lower trunk" gendered_icon = 0 @@ -18,58 +16,49 @@ name = "left upper tendril" max_damage = 35 min_broken_damage = 20 - cannot_break = 1 amputation_point = "upper left trunk" /obj/item/organ/external/arm/right/diona name = "right upper tendril" max_damage = 35 min_broken_damage = 20 - cannot_break = 1 amputation_point = "upper right trunk" /obj/item/organ/external/leg/diona name = "left lower tendril" max_damage = 35 min_broken_damage = 20 - cannot_break = 1 amputation_point = "lower left fork" /obj/item/organ/external/leg/right/diona name = "right lower tendril" max_damage = 35 min_broken_damage = 20 - cannot_break = 1 amputation_point = "lower right fork" /obj/item/organ/external/foot/diona name = "left foot" max_damage = 20 min_broken_damage = 10 - cannot_break = 1 amputation_point = "branch" /obj/item/organ/external/foot/right/diona name = "right foot" max_damage = 20 min_broken_damage = 10 - cannot_break = 1 amputation_point = "branch" /obj/item/organ/external/hand/diona name = "left grasper" - cannot_break = 1 amputation_point = "branch" /obj/item/organ/external/hand/right/diona name = "right grasper" - cannot_break = 1 amputation_point = "branch" /obj/item/organ/external/head/diona max_damage = 50 min_broken_damage = 25 - cannot_break = 1 encased = null amputation_point = "upper trunk" gendered_icon = 0 @@ -82,6 +71,11 @@ icon = 'icons/obj/objects.dmi' icon_state = "nymph" +/obj/item/organ/internal/lungs/diona + name = "respiratory vacuoles" + icon = 'icons/obj/objects.dmi' + icon_state = "nymph" + /obj/item/organ/internal/brain/diona // Turns into a nymph instantly, no transplanting possible. name = "gas bladder" icon = 'icons/obj/objects.dmi' diff --git a/html/changelog.html b/html/changelog.html index 023f1918124..270ef03dd3f 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,6 +56,251 @@ -->
      +

      30 August 2019

      +

      AffectedArc07 updated:

      +
        +
      • Fixes the changelog
      • +
      +

      Arkatos updated:

      +
        +
      • Added new icon for Charge spell
      • +
      • Added new icon for No Clothes spell
      • +
      • Added new icon for Wizard spellbook
      • +
      • Added new animations to 10 single-use spellbooks
      • +
      • Added new sprite for Bottle of Tickles
      • +
      • Added refunding functionality to the Bottle of Ooze akin to the other summoning bottles. Click with the bottle in hand on a wizard spellbook to refund its cost and limit slot.
      • +
      • Fixed an issue where Bottle of Tickles did not properly refund
      • +
      • Fixed an issue with alpha layering on Bottle of Ooze sprite
      • +
      • Very slightly adjusted brightness of the Boo! ghost spell icon
      • +
      • Wizard spellbook was completely reorganized, and new appropriate categories were added, each category is sorted by price, and if price of the two or more spells is the same, they are sorted alphabetically
      • +
      • Polymorph can now turn a mob into Syndicate medical or saboteur modules
      • +
      • Mobs made via polymorph into borgs are now unbounded free borgs
      • +
      • Repulse spell cost decreased from 2 to 1
      • +
      • Lighting bolt spell cost decreased from 2 to 1
      • +
      • Slaughter/Laughter demons and Magical Morphs now always have their second fluff objective considered as complete no matter the circumstances
      • +
      • Laughter Demons very slightly buffed, they are still a bit weaker than Slaughter Demons
      • +
      • Improved descriptions and wording regarding Wizard spellbook and Wizard spells
      • +
      • Traitor AI now uses action buttons for its malfunction abilities
      • +
      +

      AzuleUtama updated:

      +
        +
      • Adds false-bottomed briefcase from VG.
      • +
      +

      Couls updated:

      +
        +
      • Rechargers can now be crafted from science using one capacitor and a recharger board tweak:Smaller machines like microwaves and cell chargers can now be placed on tables(Fax machines included) tweak:can screwdriver open rechargers and then apply a crowbar to deconstruct them
      • +
      • Blood spread now depends on volume of the blood, requires more drips of blood to create a pool
      • +
      • DUAL WIELDING
      • +
      • new chatsubsystem from TG!
      • +
      • Update issue templates to latest version and clean up the current template
      • +
      • mining shuttle warning message and delay before launching
      • +
      • cardboard boxes are no longer sonic speed
      • +
      • shuttle timers now get set properly
      • +
      +

      EmanTheAlmighty updated:

      +
        +
      • Blobbernauts can now be controlled by players through a prompt which appears when they are spawned by blobs.
      • +
      • Blobbernauts and blobs can now communicate with each other.
      • +
      • Blobbernauts now regenerate health overtime when standing on blob structures.
      • +
      • Blobbernauts will slowly lose health if they are not standing on blob structures while not at full health. balance: Blobbernauts have been nerfed, they now have less health, deal less damage and cannot break walls anymore. balance: Blob's "Produce Blobbernaut" ability has been made more expensive to use, now costing 60 resources instead of 20.
      • +
      +

      Emanthealmighty updated:

      +
        +
      • The poll to play as a blobbernaut now lasts 10 seconds from 15.
      • +
      • Blobbernauts no longer chase after people while players are being polled to play as one.
      • +
      +

      Fox McCloud updated:

      +
        +
      • Plasmamen dramatically overhauled.
      • +
      • Plasmamen can be cloned without burning to death in the clonepod
      • +
      • Plasmamen no longer start with spacesuits
      • +
      • Plasmamen start off with jumpsuits that seal to protect against oxygen. This allows for you to customize their appearance more
      • +
      • Plasmamen helmets now allow you to see a Plasmaman's actual face; should be able to see their eye color and mouth color now
      • +
      • Plasmamen take 50% extra brute and burn
      • +
      • Plasmamen are immune to radiation
      • +
      • Plasmamen start out with a small tank that can fit on a belt or in a pocket; it should be enough to last an entire shift
      • +
      • Plasmaman helmets now have built in welding goggles
      • +
      • Plasmaman karma cost lowered from 100 to 45
      • +
      • Reworks Diona
      • +
      • Diona bleed (call it chlorophy; it's green)
      • +
      • Diona Breathe (plants do need to exchange gas after all)
      • +
      • Rad Immunity Removed
      • +
      • Diona regenerate 1 OXY, 1 BURN, 1 BRUTE, and 1 TOX if they are in a bright area; this effect does not kick in if they're in crit
      • +
      • Diona no longer have unbreakable bones (wood can crack ya know!)
      • +
      • Diona are no longer space proof
      • +
      • Diona are more vulnerable to fire and heat damage
      • +
      • Diona weakness to weedkiller dramatically nerfed
      • +
      • Diona now use Newcrit
      • +
      • Diona are no longer slow
      • +
      • Diona can wear spacesuits
      • +
      • Fixes stun absorbing not working
      • +
      • Fixes parallax insane setting not doing anything
      • +
      • Ores can be destroyed by devastating explosions
      • +
      • silver, gold, and diamond pickaxes do a bit more damage and mine faster than before
      • +
      • drills slightly slower, but diamond drills slightly faster
      • +
      • Spade is the same speed as a shovel
      • +
      • Hivelord stabilizer will now make a hivelord core/legion soul stabilize and be preserved, even if it was previously inert
      • +
      • can use a hivelord core in your active hand to apply it to yourself
      • +
      • soulstone in the abandoned locked crates can now be used by anyone
      • +
      • Adds firelemon seeds to the abandoned locked crates as potential loot
      • +
      • Hardsuits have an integrated helmet; you no longer have to attach helmets
      • +
      • Toggling up/down helmets is now done with an action button
      • +
      • can no longer attach magboots to a hardsuit
      • +
      • Hardsuit base melee armor increased from 10 to 30
      • +
      • Security and HoS hardsuit melee armor increased by 5
      • +
      • HoS hardsuit helmet armor matches his hardsuit
      • +
      • CE's hardsuit helmet armor for rads increased by 10 (should be fully rad proof now)
      • +
      • Elite syndicate suits can't be acided
      • +
      • Fixes stuns and weakens related to reagents
      • +
      • Fixes the displayed cost of Plasmamen
      • +
      • Adds jetpack hardsuit upgrades: get yours at mining for 2000 points
      • +
      • Removes mining carbon dioxide jetpack
      • +
      • Can no longer use jetpacks in your suit storage slot
      • +
      • Chief Engineer's hardsuit, Syndicate Hardsuit (normal and elite), and Shielded Syndicate Hardsuit all have built in jetpacks
      • +
      • Fixes random singularity releases from the grid check event
      • +
      • loadout costs for most things cut from 2 to 1
      • +
      • Adds fingerless gloves, eyepatch, prescription glasses, black shoes, brown shoes, white shoes, and ian's shirt to the loadout
      • +
      • moved hipster glasses from donator to general glasses
      • +
      • Adds in sandbags. Use them to deploy destructable barriers; miners start off with a few
      • +
      • Removes access based security barriers
      • +
      • Adds in security barrier grenade. When it goes off, it will deploy up to 3 barriers that will lock into place; should find 4 of these in the armory
      • +
      • can tear up bedsheet and gauze to get cloth--requires a sharp object
      • +
      • Fixes plasmamen atmos techs not getting their proper suit
      • +
      • Adds in a loom, craft one out of 10 wood
      • +
      • Adds in cotton and durathread cotton to botany to grow
      • +
      • Adds in a number of expanded items to create out of cloth, such as improvised gauze, beanies, and softcaps
      • +
      • Adds the ability to use personal crafting to make durathread jumpsuits, bandanas, armor, helmets, beanies and berets. Aside from the bandana, these all have minor armor on them
      • +
      • Adds a number of new items to personally craft, related to clothing: ability to make health, sec, diagnotic, and reagent sunglasses.
      • +
      • Can additionally craft cowboy boots, lizardskin cowboy boots, fannypacks, and a spooky ghost disguise
      • +
      • adds a whole range of beanies, find them in the clothing vendor or make them yourself
      • +
      • Updates the cowboy boots sprites
      • +
      • Unironically fixes about several thousand runtimes
      • +
      • Fixes jackets not keeping you warm
      • +
      • Chefs are now trained in the art of Close Quarters Cooking
      • +
      • Adds the Book of Babel as tendril loot
      • +
      • Adds Jacbo's Ladder as tendril loot
      • +
      • Fixes fungus, blood, and graffiti not showing up on a wall
      • +
      • Fixes the lavaland inquisitor and berserker hardsuits having incorrect armor and slowdown values
      • +
      • Fixes baseball bats throwing anchored things
      • +
      • Fixes blood drunk buff
      • +
      • Fixes using a crusher on a trophy to equip it causing you to drop the crusher
      • +
      • refactors lazarus capsules; no real behavioral change
      • +
      • Fixes being able to revive megafauna with strange reagent
      • +
      +

      Fox McCloud and FullOfSkittles updated:

      +
        +
      • Tweaks the gummy worm, gummy bear, jeallybean, toffee, and bacon sprites
      • +
      • Fixes telebacon not properly acting as...well, a bacon beacon
      • +
      +

      FreeStylaLT updated:

      +
        +
      • Added an Engine Picker, which uses new engine beacons.
      • +
      • Replaced the current two engine generators with one engine beacon.
      • +
      +

      Ionward updated:

      +
        +
      • Drask crewmembers now have properly fitting shoes.
      • +
      • Fixed some minor issues in Drasks uniforms
      • +
      • non-humans now have proper sprites for durathread goods
      • +
      +

      KasparoVy updated:

      +
        +
      • Adds sprites for all Vox & Armalis earwear.
      • +
      • Adds sprites for Armalis default backpack, nitrogen tank (old-style back & new-style belt) & all breath mask variations.
      • +
      • You can now species-fit in-hand icons: Use a single .dmi file and suffix the icon states with _l or _r.
      • +
      • Fixes an issue preventing Vox Armalis from being rendered with the proper in-hand icons for their massive noise cannons.
      • +
      • Fixes an issue preventing the species-fitting of earwear.
      • +
      • Fixes an issue preventing Vox Armalis from wearing the 'Vox' breath mask.
      • +
      • Picking up uniforms no longer renders a default grey jumpsuit on Vox.
      • +
      • Resolves an issue causing shining eyes to be rendered darker than intended.
      • +
      • Resolves an issue preventing appearance features (hair, eyes, etc.) from rendering on disembodied heads.
      • +
      • Resolves an issue preventing Admin-revived decapitated bodies from having appearance features or ears.
      • +
      • Non-shining eyes render the proper colour again.
      • +
      +

      Kurgis updated:

      +
        +
      • Beepsky now bumps around on its wheels when patrolling for crime.
      • +
      +

      Markolie updated:

      +
        +
      • A new outfit manager has been added for admins (under debug). It lets them save and load custom outfits on their computer and use these to equip players.
      • +
      • Upon transforming players into humans or reincarnating them through the player panel, admins will now directly be able to select their equipment.
      • +
      • The select equipment verb now works on observers: it'll create a human with the given equipment under the ghost.
      • +
      • A "Copy Outfit" button has been added to the View Variables dropdown, which lets admins instantly copy an outfit.
      • +
      • Outfits now support accessories and internal boxes.
      • +
      • The separate option to equip ERT members has been removed. It's been integrated into their regular outfits.
      • +
      • Water coming from sinks and certain water effects is now 10C instead of body temperature.
      • +
      +

      Shadow-Quill updated:

      +
        +
      • [Meta] Added buckshot and slugs to armoury.
      • +
      • [Meta] Added surgical tools, robotic first aid kits, and a photocopier to Robotics.
      • +
      • [Meta] R&D doors now has proper access requirements.
      • +
      • [Meta] Added RCS and telepad to cargo.
      • +
      • [Meta] Disposals sheet stacker and conveyor belts now works properly.
      • +
      • [Meta] One-way airlocks added in Medbay/Brig.
      • +
      • [Meta] Disposals sheet stacker disposals chute leads directly to the mailroom.
      • +
      • AIs not being able to restore their own power if in an area with an APC.
      • +
      • Fixed being able to talk in OOC under certain circumstances if it's disabled.
      • +
      • Lockers can no longer move around anchored mobs.
      • +
      +

      SteelSlayer updated:

      +
        +
      • You can no longer spam dismantle a SMES terminal and get 10 cable for every progress bar
      • +
      • The game will properly remove 10 cable from your stack after building a SMES terminal, instead of removing 0
      • +
      • A cable adding sound gets played when you add wires to create a terminal for a SMES
      • +
      • Rapid pipe dispensers can now place disposal sorting pipes
      • +
      • When changing the sort location of a disposal sorting pipe, the name of the pipe now also changes to the desired destination
      • +
      • Added a destination tagger to the atmosheric technician locker
      • +
      • Added atmospherics access to Engi-Vend's and Engineering checkpoint airlocks
      • +
      • Removed some random grey pixels from disposal sorting junction pipe sprites, and certain normal disposal junction pipe sprites
      • +
      • IV bags are able to transfer their contents to other containers by clicking on them with the bag
      • +
      • Adds a handheld defibrillator to the paramedic EVA closet
      • +
      • You can insert magazines into L6 SAWs again
      • +
      • Removed one of the high capacity tanks in hydroponics
      • +
      • Added a disk compartmentalizer to hydroponics
      • +
      • Delaying round start actually delays round start again
      • +
      +

      Terilia updated:

      +
        +
      • added headcrabs
      • +
      • adjusted the path's for headslugs. They are not called headcrab anymore
      • +
      +

      TheSardele updated:

      +
        +
      • Removes the ability of obese people and those with matter eater to swallow others.
      • +
      +

      Ty-Omaha updated:

      +
        +
      • Fixed a bug where hotwiring solar panels would allow for the station to remain powered in the Grid Check power failure event.
      • +
      +

      datlo updated:

      +
        +
      • Added ashstorm immunity to titanium and plastitanium golems.
      • +
      • Added lava immunity to plastitanium golems.
      • +
      • Bananium golems now slowly waddle around.
      • +
      • Uranium golems now properly irradiate nearby mobs that arent rad immune.
      • +
      • Tranquillite golems now properly get their miming powers.
      • +
      • Added the Clown and Winter biodomes as possible lavaland ruins.
      • +
      • Update a changeling error message to be clearer.
      • +
      +

      farie82 updated:

      +
        +
      • Items with NODROP that are dropped now lose the flag if they didn't get created with it
      • +
      • Adds tip text to the examine text of the ambulance trolley about how to attach it
      • +
      • Adds tip text to the nuke when trying to use the NAD before deploying it
      • +
      • Adds tip text to the fire axe cabinet about how to lock/unlock it
      • +
      • Adds tip text to airlocks if they have a note on them about how to remove the note
      • +
      • Can't put the NAD in the nuke now when it has the NODROP flag
      • +
      • Locking a fire axe cabinet is less weird now. No odd 5 seconds sleep
      • +
      • Can't put a nodrop fire axe in fire axe cabinets now. Duping them
      • +
      • Implants like the IPC charging work again. They won't get deleted after first use
      • +
      +

      variableundefined updated:

      +
        +
      • A proc's name got changed. That's it
      • +
      +

      23 August 2019

      AffectedArc07, Keekenox, Floyd/Qustinnus updated:

        diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 647b9735e00..d03050e2258 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -10819,3 +10819,266 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - bugfix: adjusts the hierophant blast layer to make for it to always be below the effect. this should be the case already due to mouse_opacity, though for some unknown reason, it just doesn't work sometimes, so this should fix it. +2019-08-30: + AffectedArc07: + - bugfix: Fixes the changelog + Arkatos: + - imageadd: Added new icon for Charge spell + - imageadd: Added new icon for No Clothes spell + - imageadd: Added new icon for Wizard spellbook + - imageadd: Added new animations to 10 single-use spellbooks + - imageadd: Added new sprite for Bottle of Tickles + - rscadd: Added refunding functionality to the Bottle of Ooze akin to the other + summoning bottles. Click with the bottle in hand on a wizard spellbook to refund + its cost and limit slot. + - bugfix: Fixed an issue where Bottle of Tickles did not properly refund + - bugfix: Fixed an issue with alpha layering on Bottle of Ooze sprite + - tweak: Very slightly adjusted brightness of the Boo! ghost spell icon + - tweak: Wizard spellbook was completely reorganized, and new appropriate categories + were added, each category is sorted by price, and if price of the two or more + spells is the same, they are sorted alphabetically + - tweak: Polymorph can now turn a mob into Syndicate medical or saboteur modules + - tweak: Mobs made via polymorph into borgs are now unbounded free borgs + - tweak: Repulse spell cost decreased from 2 to 1 + - tweak: Lighting bolt spell cost decreased from 2 to 1 + - tweak: Slaughter/Laughter demons and Magical Morphs now always have their second + fluff objective considered as complete no matter the circumstances + - tweak: Laughter Demons very slightly buffed, they are still a bit weaker than + Slaughter Demons + - spellcheck: Improved descriptions and wording regarding Wizard spellbook and Wizard + spells + - rscadd: Traitor AI now uses action buttons for its malfunction abilities + AzuleUtama: + - rscadd: Adds false-bottomed briefcase from VG. + Couls: + - rscadd: Rechargers can now be crafted from science using one capacitor and a recharger + board tweak:Smaller machines like microwaves and cell chargers can now be placed + on tables(Fax machines included) tweak:can screwdriver open rechargers and then + apply a crowbar to deconstruct them + - tweak: Blood spread now depends on volume of the blood, requires more drips of + blood to create a pool + - rscadd: DUAL WIELDING + - rscadd: new chatsubsystem from TG! + - tweak: Update issue templates to latest version and clean up the current template + - rscadd: mining shuttle warning message and delay before launching + - bugfix: cardboard boxes are no longer sonic speed + - bugfix: shuttle timers now get set properly + EmanTheAlmighty: + - rscadd: Blobbernauts can now be controlled by players through a prompt which appears + when they are spawned by blobs. + - rscadd: Blobbernauts and blobs can now communicate with each other. + - rscadd: Blobbernauts now regenerate health overtime when standing on blob structures. + - rscadd: 'Blobbernauts will slowly lose health if they are not standing on blob + structures while not at full health. balance: Blobbernauts have been nerfed, + they now have less health, deal less damage and cannot break walls anymore. + balance: Blob''s "Produce Blobbernaut" ability has been made more expensive + to use, now costing 60 resources instead of 20.' + Emanthealmighty: + - tweak: The poll to play as a blobbernaut now lasts 10 seconds from 15. + - tweak: Blobbernauts no longer chase after people while players are being polled + to play as one. + Fox McCloud: + - tweak: Plasmamen dramatically overhauled. + - rscadd: Plasmamen can be cloned without burning to death in the clonepod + - rscdel: Plasmamen no longer start with spacesuits + - rscadd: Plasmamen start off with jumpsuits that seal to protect against oxygen. + This allows for you to customize their appearance more + - tweak: Plasmamen helmets now allow you to see a Plasmaman's actual face; should + be able to see their eye color and mouth color now + - tweak: Plasmamen take 50% extra brute and burn + - rscadd: Plasmamen are immune to radiation + - tweak: Plasmamen start out with a small tank that can fit on a belt or in a pocket; + it should be enough to last an entire shift + - rscadd: Plasmaman helmets now have built in welding goggles + - tweak: Plasmaman karma cost lowered from 100 to 45 + - tweak: Reworks Diona + - rscadd: Diona bleed (call it chlorophy; it's green) + - rscadd: Diona Breathe (plants do need to exchange gas after all) + - rscdel: Rad Immunity Removed + - tweak: Diona regenerate 1 OXY, 1 BURN, 1 BRUTE, and 1 TOX if they are in a bright + area; this effect does not kick in if they're in crit + - rscdel: Diona no longer have unbreakable bones (wood can crack ya know!) + - rscdel: Diona are no longer space proof + - tweak: Diona are more vulnerable to fire and heat damage + - tweak: Diona weakness to weedkiller dramatically nerfed + - rscadd: Diona now use Newcrit + - tweak: Diona are no longer slow + - rscadd: Diona can wear spacesuits + - bugfix: Fixes stun absorbing not working + - bugfix: Fixes parallax insane setting not doing anything + - tweak: Ores can be destroyed by devastating explosions + - tweak: silver, gold, and diamond pickaxes do a bit more damage and mine faster + than before + - tweak: drills slightly slower, but diamond drills slightly faster + - tweak: Spade is the same speed as a shovel + - tweak: Hivelord stabilizer will now make a hivelord core/legion soul stabilize + and be preserved, even if it was previously inert + - tweak: can use a hivelord core in your active hand to apply it to yourself + - rscadd: soulstone in the abandoned locked crates can now be used by anyone + - rscadd: Adds firelemon seeds to the abandoned locked crates as potential loot + - tweak: Hardsuits have an integrated helmet; you no longer have to attach helmets + - tweak: Toggling up/down helmets is now done with an action button + - rscdel: can no longer attach magboots to a hardsuit + - tweak: Hardsuit base melee armor increased from 10 to 30 + - tweak: Security and HoS hardsuit melee armor increased by 5 + - tweak: HoS hardsuit helmet armor matches his hardsuit + - tweak: CE's hardsuit helmet armor for rads increased by 10 (should be fully rad + proof now) + - tweak: Elite syndicate suits can't be acided + - bugfix: Fixes stuns and weakens related to reagents + - bugfix: Fixes the displayed cost of Plasmamen + - rscadd: 'Adds jetpack hardsuit upgrades: get yours at mining for 2000 points' + - rscdel: Removes mining carbon dioxide jetpack + - tweak: Can no longer use jetpacks in your suit storage slot + - rscadd: Chief Engineer's hardsuit, Syndicate Hardsuit (normal and elite), and + Shielded Syndicate Hardsuit all have built in jetpacks + - bugfix: Fixes random singularity releases from the grid check event + - tweak: loadout costs for most things cut from 2 to 1 + - rscadd: Adds fingerless gloves, eyepatch, prescription glasses, black shoes, brown + shoes, white shoes, and ian's shirt to the loadout + - tweak: moved hipster glasses from donator to general glasses + - rscadd: Adds in sandbags. Use them to deploy destructable barriers; miners start + off with a few + - rscdel: Removes access based security barriers + - rscadd: Adds in security barrier grenade. When it goes off, it will deploy up + to 3 barriers that will lock into place; should find 4 of these in the armory + - rscadd: can tear up bedsheet and gauze to get cloth--requires a sharp object + - bugfix: Fixes plasmamen atmos techs not getting their proper suit + - rscadd: Adds in a loom, craft one out of 10 wood + - rscadd: Adds in cotton and durathread cotton to botany to grow + - rscadd: Adds in a number of expanded items to create out of cloth, such as improvised + gauze, beanies, and softcaps + - rscadd: Adds the ability to use personal crafting to make durathread jumpsuits, + bandanas, armor, helmets, beanies and berets. Aside from the bandana, these + all have minor armor on them + - rscadd: 'Adds a number of new items to personally craft, related to clothing: + ability to make health, sec, diagnotic, and reagent sunglasses.' + - rscadd: Can additionally craft cowboy boots, lizardskin cowboy boots, fannypacks, + and a spooky ghost disguise + - rscadd: adds a whole range of beanies, find them in the clothing vendor or make + them yourself + - tweak: Updates the cowboy boots sprites + - bugfix: Unironically fixes about several thousand runtimes + - bugfix: Fixes jackets not keeping you warm + - rscadd: Chefs are now trained in the art of Close Quarters Cooking + - rscadd: Adds the Book of Babel as tendril loot + - rscadd: Adds Jacbo's Ladder as tendril loot + - bugfix: Fixes fungus, blood, and graffiti not showing up on a wall + - bugfix: Fixes the lavaland inquisitor and berserker hardsuits having incorrect + armor and slowdown values + - bugfix: Fixes baseball bats throwing anchored things + - bugfix: Fixes blood drunk buff + - bugfix: Fixes using a crusher on a trophy to equip it causing you to drop the + crusher + - tweak: refactors lazarus capsules; no real behavioral change + - bugfix: Fixes being able to revive megafauna with strange reagent + Fox McCloud and FullOfSkittles: + - tweak: Tweaks the gummy worm, gummy bear, jeallybean, toffee, and bacon sprites + - bugfix: Fixes telebacon not properly acting as...well, a bacon beacon + FreeStylaLT: + - rscadd: Added an Engine Picker, which uses new engine beacons. + - tweak: Replaced the current two engine generators with one engine beacon. + Ionward: + - imageadd: Drask crewmembers now have properly fitting shoes. + - imageadd: Fixed some minor issues in Drasks uniforms + - imageadd: non-humans now have proper sprites for durathread goods + KasparoVy: + - imageadd: Adds sprites for all Vox & Armalis earwear. + - imageadd: Adds sprites for Armalis default backpack, nitrogen tank (old-style + back & new-style belt) & all breath mask variations. + - rscadd: 'You can now species-fit in-hand icons: Use a single .dmi file and suffix + the icon states with _l or _r.' + - bugfix: Fixes an issue preventing Vox Armalis from being rendered with the proper + in-hand icons for their massive noise cannons. + - bugfix: Fixes an issue preventing the species-fitting of earwear. + - bugfix: Fixes an issue preventing Vox Armalis from wearing the 'Vox' breath mask. + - bugfix: Picking up uniforms no longer renders a default grey jumpsuit on Vox. + - bugfix: Resolves an issue causing shining eyes to be rendered darker than intended. + - bugfix: Resolves an issue preventing appearance features (hair, eyes, etc.) from + rendering on disembodied heads. + - bugfix: Resolves an issue preventing Admin-revived decapitated bodies from having + appearance features or ears. + - bugfix: Non-shining eyes render the proper colour again. + Kurgis: + - rscadd: Beepsky now bumps around on its wheels when patrolling for crime. + Markolie: + - rscadd: A new outfit manager has been added for admins (under debug). It lets + them save and load custom outfits on their computer and use these to equip players. + - rscadd: Upon transforming players into humans or reincarnating them through the + player panel, admins will now directly be able to select their equipment. + - rscadd: 'The select equipment verb now works on observers: it''ll create a human + with the given equipment under the ghost.' + - rscadd: A "Copy Outfit" button has been added to the View Variables dropdown, + which lets admins instantly copy an outfit. + - rscadd: Outfits now support accessories and internal boxes. + - rscdel: The separate option to equip ERT members has been removed. It's been integrated + into their regular outfits. + - tweak: Water coming from sinks and certain water effects is now 10C instead of + body temperature. + Shadow-Quill: + - rscadd: '[Meta] Added buckshot and slugs to armoury.' + - rscadd: '[Meta] Added surgical tools, robotic first aid kits, and a photocopier + to Robotics.' + - bugfix: '[Meta] R&D doors now has proper access requirements.' + - rscadd: '[Meta] Added RCS and telepad to cargo.' + - bugfix: '[Meta] Disposals sheet stacker and conveyor belts now works properly.' + - rscadd: '[Meta] One-way airlocks added in Medbay/Brig.' + - tweak: '[Meta] Disposals sheet stacker disposals chute leads directly to the mailroom.' + - bugfix: AIs not being able to restore their own power if in an area with an APC. + - bugfix: Fixed being able to talk in OOC under certain circumstances if it's disabled. + - bugfix: Lockers can no longer move around anchored mobs. + SteelSlayer: + - bugfix: You can no longer spam dismantle a SMES terminal and get 10 cable for + every progress bar + - bugfix: The game will properly remove 10 cable from your stack after building + a SMES terminal, instead of removing 0 + - rscadd: A cable adding sound gets played when you add wires to create a terminal + for a SMES + - rscadd: Rapid pipe dispensers can now place disposal sorting pipes + - tweak: When changing the sort location of a disposal sorting pipe, the name of + the pipe now also changes to the desired destination + - rscadd: Added a destination tagger to the atmosheric technician locker + - tweak: Added atmospherics access to Engi-Vend's and Engineering checkpoint airlocks + - tweak: Removed some random grey pixels from disposal sorting junction pipe sprites, + and certain normal disposal junction pipe sprites + - tweak: IV bags are able to transfer their contents to other containers by clicking + on them with the bag + - rscadd: Adds a handheld defibrillator to the paramedic EVA closet + - bugfix: You can insert magazines into L6 SAWs again + - rscdel: Removed one of the high capacity tanks in hydroponics + - rscadd: Added a disk compartmentalizer to hydroponics + - bugfix: Delaying round start actually delays round start again + Terilia: + - rscadd: added headcrabs + - tweak: adjusted the path's for headslugs. They are not called headcrab anymore + TheSardele: + - rscdel: Removes the ability of obese people and those with matter eater to swallow + others. + Ty-Omaha: + - bugfix: Fixed a bug where hotwiring solar panels would allow for the station to + remain powered in the Grid Check power failure event. + datlo: + - rscadd: Added ashstorm immunity to titanium and plastitanium golems. + - rscadd: Added lava immunity to plastitanium golems. + - rscadd: Bananium golems now slowly waddle around. + - bugfix: Uranium golems now properly irradiate nearby mobs that arent rad immune. + - bugfix: Tranquillite golems now properly get their miming powers. + - rscadd: Added the Clown and Winter biodomes as possible lavaland ruins. + - tweak: Update a changeling error message to be clearer. + farie82: + - bugfix: Items with NODROP that are dropped now lose the flag if they didn't get + created with it + - rscadd: Adds tip text to the examine text of the ambulance trolley about how to + attach it + - rscadd: Adds tip text to the nuke when trying to use the NAD before deploying + it + - rscadd: Adds tip text to the fire axe cabinet about how to lock/unlock it + - rscadd: Adds tip text to airlocks if they have a note on them about how to remove + the note + - bugfix: Can't put the NAD in the nuke now when it has the NODROP flag + - bugfix: Locking a fire axe cabinet is less weird now. No odd 5 seconds sleep + - bugfix: Can't put a nodrop fire axe in fire axe cabinets now. Duping them + - bugfix: Implants like the IPC charging work again. They won't get deleted after + first use + variableundefined: + - tweak: A proc's name got changed. That's it diff --git a/html/changelogs/AutoChangeLog-pr-11712.yml b/html/changelogs/AutoChangeLog-pr-11712.yml deleted file mode 100644 index ed9937e57c6..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11712.yml +++ /dev/null @@ -1,9 +0,0 @@ -author: "Markolie" -delete-after: True -changes: - - rscadd: "A new outfit manager has been added for admins (under debug). It lets them save and load custom outfits on their computer and use these to equip players." - - rscadd: "Upon transforming players into humans or reincarnating them through the player panel, admins will now directly be able to select their equipment." - - rscadd: "The select equipment verb now works on observers: it'll create a human with the given equipment under the ghost." - - rscadd: "A \"Copy Outfit\" button has been added to the View Variables dropdown, which lets admins instantly copy an outfit." - - rscadd: "Outfits now support accessories and internal boxes." - - rscdel: "The separate option to equip ERT members has been removed. It's been integrated into their regular outfits." diff --git a/html/changelogs/AutoChangeLog-pr-11719.yml b/html/changelogs/AutoChangeLog-pr-11719.yml deleted file mode 100644 index 26164747593..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11719.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Terilia" -delete-after: True -changes: - - rscadd: "added headcrabs" - - tweak: "adjusted the path's for headslugs. They are not called headcrab anymore" diff --git a/html/changelogs/AutoChangeLog-pr-11762.yml b/html/changelogs/AutoChangeLog-pr-11762.yml deleted file mode 100644 index e1aeb4f2529..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11762.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "AzuleUtama" -delete-after: True -changes: - - rscadd: "Adds false-bottomed briefcase from VG." diff --git a/html/changelogs/AutoChangeLog-pr-11772.yml b/html/changelogs/AutoChangeLog-pr-11772.yml deleted file mode 100644 index a59b8791f03..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11772.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "Couls" -delete-after: True -changes: - - rscadd: "Rechargers can now be crafted from science using one capacitor and a recharger board -tweak:Smaller machines like microwaves and cell chargers can now be placed on tables(Fax machines included) -tweak:can screwdriver open rechargers and then apply a crowbar to deconstruct them" diff --git a/html/changelogs/AutoChangeLog-pr-11797.yml b/html/changelogs/AutoChangeLog-pr-11797.yml deleted file mode 100644 index 58464c2997d..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11797.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Couls" -delete-after: True -changes: - - tweak: "Blood spread now depends on volume of the blood, requires more drips of blood to create a pool" diff --git a/html/changelogs/AutoChangeLog-pr-11862.yml b/html/changelogs/AutoChangeLog-pr-11862.yml deleted file mode 100644 index ecd4aa0fa8b..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11862.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Ty-Omaha" -delete-after: True -changes: - - bugfix: "Fixed a bug where hotwiring solar panels would allow for the station to remain powered in the Grid Check power failure event." diff --git a/html/changelogs/AutoChangeLog-pr-11868.yml b/html/changelogs/AutoChangeLog-pr-11868.yml deleted file mode 100644 index 87571fc57e0..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11868.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "SteelSlayer" -delete-after: True -changes: - - bugfix: "You can no longer spam dismantle a SMES terminal and get 10 cable for every progress bar" - - bugfix: "The game will properly remove 10 cable from your stack after building a SMES terminal, instead of removing 0" - - rscadd: "A cable adding sound gets played when you add wires to create a terminal for a SMES" diff --git a/html/changelogs/AutoChangeLog-pr-11921.yml b/html/changelogs/AutoChangeLog-pr-11921.yml deleted file mode 100644 index d55a327c310..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11921.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Couls" -delete-after: True -changes: - - rscadd: "new chatsubsystem from TG!" diff --git a/html/changelogs/AutoChangeLog-pr-11936.yml b/html/changelogs/AutoChangeLog-pr-11936.yml deleted file mode 100644 index bec331efe04..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11936.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "farie82" -delete-after: True -changes: - - bugfix: "Items with NODROP that are dropped now lose the flag if they didn't get created with it" diff --git a/html/changelogs/AutoChangeLog-pr-11940.yml b/html/changelogs/AutoChangeLog-pr-11940.yml deleted file mode 100644 index 412460535f2..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11940.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Couls" -delete-after: True -changes: - - tweak: "Update issue templates to latest version and clean up the current template" diff --git a/html/changelogs/AutoChangeLog-pr-11941.yml b/html/changelogs/AutoChangeLog-pr-11941.yml deleted file mode 100644 index 5654ca5bdcf..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11941.yml +++ /dev/null @@ -1,10 +0,0 @@ -author: "farie82" -delete-after: True -changes: - - rscadd: "Adds tip text to the examine text of the ambulance trolley about how to attach it" - - rscadd: "Adds tip text to the nuke when trying to use the NAD before deploying it" - - rscadd: "Adds tip text to the fire axe cabinet about how to lock/unlock it" - - rscadd: "Adds tip text to airlocks if they have a note on them about how to remove the note" - - bugfix: "Can't put the NAD in the nuke now when it has the NODROP flag" - - bugfix: "Locking a fire axe cabinet is less weird now. No odd 5 seconds sleep" - - bugfix: "Can't put a nodrop fire axe in fire axe cabinets now. Duping them" diff --git a/html/changelogs/AutoChangeLog-pr-11948.yml b/html/changelogs/AutoChangeLog-pr-11948.yml deleted file mode 100644 index a7048eee037..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11948.yml +++ /dev/null @@ -1,9 +0,0 @@ -author: "EmanTheAlmighty" -delete-after: True -changes: - - rscadd: "Blobbernauts can now be controlled by players through a prompt which appears when they are spawned by blobs." - - rscadd: "Blobbernauts and blobs can now communicate with each other." - - rscadd: "Blobbernauts now regenerate health overtime when standing on blob structures." - - rscadd: "Blobbernauts will slowly lose health if they are not standing on blob structures while not at full health. -balance: Blobbernauts have been nerfed, they now have less health, deal less damage and cannot break walls anymore. -balance: Blob's \"Produce Blobbernaut\" ability has been made more expensive to use, now costing 60 resources instead of 20." diff --git a/html/changelogs/AutoChangeLog-pr-11957.yml b/html/changelogs/AutoChangeLog-pr-11957.yml deleted file mode 100644 index 6e23f4bd87f..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11957.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "FreeStylaLT" -delete-after: True -changes: - - rscadd: "Added an Engine Picker, which uses new engine beacons." - - tweak: "Replaced the current two engine generators with one engine beacon." diff --git a/html/changelogs/AutoChangeLog-pr-11978.yml b/html/changelogs/AutoChangeLog-pr-11978.yml deleted file mode 100644 index 6a3cce38167..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11978.yml +++ /dev/null @@ -1,9 +0,0 @@ -author: "KasparoVy" -delete-after: True -changes: - - imageadd: "Adds sprites for all Vox & Armalis earwear." - - imageadd: "Adds sprites for Armalis default backpack, nitrogen tank (old-style back & new-style belt) & all breath mask variations." - - rscadd: "You can now species-fit in-hand icons: Use a single .dmi file and suffix the icon states with _l or _r." - - bugfix: "Fixes an issue preventing Vox Armalis from being rendered with the proper in-hand icons for their massive noise cannons." - - bugfix: "Fixes an issue preventing the species-fitting of earwear." - - bugfix: "Fixes an issue preventing Vox Armalis from wearing the 'Vox' breath mask." diff --git a/html/changelogs/AutoChangeLog-pr-11987.yml b/html/changelogs/AutoChangeLog-pr-11987.yml deleted file mode 100644 index e7ed3c0b338..00000000000 --- a/html/changelogs/AutoChangeLog-pr-11987.yml +++ /dev/null @@ -1,13 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - tweak: "Plasmamen dramatically overhauled." - - rscadd: "Plasmamen can be cloned without burning to death in the clonepod" - - rscdel: "Plasmamen no longer start with spacesuits" - - rscadd: "Plasmamen start off with jumpsuits that seal to protect against oxygen. This allows for you to customize their appearance more" - - tweak: "Plasmamen helmets now allow you to see a Plasmaman's actual face; should be able to see their eye color and mouth color now" - - tweak: "Plasmamen take 50% extra brute and burn" - - rscadd: "Plasmamen are immune to radiation" - - tweak: "Plasmamen start out with a small tank that can fit on a belt or in a pocket; it should be enough to last an entire shift" - - rscadd: "Plasmaman helmets now have built in welding goggles" - - tweak: "Plasmaman karma cost lowered from 100 to 45" diff --git a/html/changelogs/AutoChangeLog-pr-12029.yml b/html/changelogs/AutoChangeLog-pr-12029.yml deleted file mode 100644 index 3677a1afea3..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12029.yml +++ /dev/null @@ -1,10 +0,0 @@ -author: "Shadow-Quill" -delete-after: True -changes: - - rscadd: "[Meta] Added buckshot and slugs to armoury." - - rscadd: "[Meta] Added surgical tools, robotic first aid kits, and a photocopier to Robotics." - - bugfix: "[Meta] R&D doors now has proper access requirements." - - rscadd: "[Meta] Added RCS and telepad to cargo." - - bugfix: "[Meta] Disposals sheet stacker and conveyor belts now works properly." - - rscadd: "[Meta] One-way airlocks added in Medbay/Brig." - - tweak: "[Meta] Disposals sheet stacker disposals chute leads directly to the mailroom." diff --git a/html/changelogs/AutoChangeLog-pr-12030.yml b/html/changelogs/AutoChangeLog-pr-12030.yml deleted file mode 100644 index 8f6dab4fcc7..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12030.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "datlo" -delete-after: True -changes: - - rscadd: "Added the Clown and Winter biodomes as possible lavaland ruins." diff --git a/html/changelogs/AutoChangeLog-pr-12037.yml b/html/changelogs/AutoChangeLog-pr-12037.yml deleted file mode 100644 index 307b70d781f..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12037.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Couls" -delete-after: True -changes: - - rscadd: "mining shuttle warning message and delay before launching" diff --git a/html/changelogs/AutoChangeLog-pr-12038.yml b/html/changelogs/AutoChangeLog-pr-12038.yml deleted file mode 100644 index f241cfc6c23..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12038.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Shadow-Quill" -delete-after: True -changes: - - bugfix: "AIs not being able to restore their own power if in an area with an APC." diff --git a/html/changelogs/AutoChangeLog-pr-12063.yml b/html/changelogs/AutoChangeLog-pr-12063.yml deleted file mode 100644 index 49e805f3dc5..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12063.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - bugfix: "Fixes stun absorbing not working" diff --git a/html/changelogs/AutoChangeLog-pr-12064.yml b/html/changelogs/AutoChangeLog-pr-12064.yml deleted file mode 100644 index 383526fbbb8..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12064.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Fox McCloud and FullOfSkittles" -delete-after: True -changes: - - tweak: "Tweaks the gummy worm, gummy bear, jeallybean, toffee, and bacon sprites" - - bugfix: "Fixes telebacon not properly acting as...well, a bacon beacon" diff --git a/html/changelogs/AutoChangeLog-pr-12065.yml b/html/changelogs/AutoChangeLog-pr-12065.yml deleted file mode 100644 index 865de5c6587..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12065.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - bugfix: "Fixes parallax insane setting not doing anything" diff --git a/html/changelogs/AutoChangeLog-pr-12066.yml b/html/changelogs/AutoChangeLog-pr-12066.yml deleted file mode 100644 index 71c585e6514..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12066.yml +++ /dev/null @@ -1,11 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - tweak: "Ores can be destroyed by devastating explosions" - - tweak: "silver, gold, and diamond pickaxes do a bit more damage and mine faster than before" - - tweak: "drills slightly slower, but diamond drills slightly faster" - - tweak: "Spade is the same speed as a shovel" - - tweak: "Hivelord stabilizer will now make a hivelord core/legion soul stabilize and be preserved, even if it was previously inert" - - tweak: "can use a hivelord core in your active hand to apply it to yourself" - - rscadd: "soulstone in the abandoned locked crates can now be used by anyone" - - rscadd: "Adds firelemon seeds to the abandoned locked crates as potential loot" diff --git a/html/changelogs/AutoChangeLog-pr-12073.yml b/html/changelogs/AutoChangeLog-pr-12073.yml deleted file mode 100644 index a44956c76c2..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12073.yml +++ /dev/null @@ -1,11 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - tweak: "Hardsuits have an integrated helmet; you no longer have to attach helmets" - - tweak: "Toggling up/down helmets is now done with an action button" - - rscdel: "can no longer attach magboots to a hardsuit" - - tweak: "Hardsuit base melee armor increased from 10 to 30" - - tweak: "Security and HoS hardsuit melee armor increased by 5" - - tweak: "HoS hardsuit helmet armor matches his hardsuit" - - tweak: "CE's hardsuit helmet armor for rads increased by 10 (should be fully rad proof now)" - - tweak: "Elite syndicate suits can't be acided" diff --git a/html/changelogs/AutoChangeLog-pr-12075.yml b/html/changelogs/AutoChangeLog-pr-12075.yml deleted file mode 100644 index 8bec6ad2fa3..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12075.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "SteelSlayer" -delete-after: True -changes: - - tweak: "IV bags are able to transfer their contents to other containers by clicking on them with the bag" diff --git a/html/changelogs/AutoChangeLog-pr-12078.yml b/html/changelogs/AutoChangeLog-pr-12078.yml deleted file mode 100644 index d5724a2983f..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12078.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "SteelSlayer" -delete-after: True -changes: - - rscadd: "Adds a handheld defibrillator to the paramedic EVA closet" diff --git a/html/changelogs/AutoChangeLog-pr-12079.yml b/html/changelogs/AutoChangeLog-pr-12079.yml deleted file mode 100644 index 06e129f082d..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12079.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - bugfix: "Fixes stuns and weakens related to reagents" diff --git a/html/changelogs/AutoChangeLog-pr-12080.yml b/html/changelogs/AutoChangeLog-pr-12080.yml deleted file mode 100644 index 14c3e841fd6..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12080.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "SteelSlayer" -delete-after: True -changes: - - bugfix: "You can insert magazines into L6 SAWs again" diff --git a/html/changelogs/AutoChangeLog-pr-12081.yml b/html/changelogs/AutoChangeLog-pr-12081.yml deleted file mode 100644 index 931893453db..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12081.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "farie82" -delete-after: True -changes: - - bugfix: "Implants like the IPC charging work again. They won't get deleted after first use" diff --git a/html/changelogs/AutoChangeLog-pr-12085.yml b/html/changelogs/AutoChangeLog-pr-12085.yml deleted file mode 100644 index 35525e8f5b1..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12085.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "SteelSlayer" -delete-after: True -changes: - - rscdel: "Removed one of the high capacity tanks in hydroponics" - - rscadd: "Added a disk compartmentalizer to hydroponics" diff --git a/html/changelogs/AutoChangeLog-pr-12086.yml b/html/changelogs/AutoChangeLog-pr-12086.yml deleted file mode 100644 index 6158c7794bd..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12086.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - bugfix: "Fixes the displayed cost of Plasmamen" diff --git a/html/changelogs/AutoChangeLog-pr-12087.yml b/html/changelogs/AutoChangeLog-pr-12087.yml deleted file mode 100644 index adab7cd382d..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12087.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "KasparoVy" -delete-after: True -changes: - - bugfix: "Picking up uniforms no longer renders a default grey jumpsuit on Vox." diff --git a/html/changelogs/AutoChangeLog-pr-12088.yml b/html/changelogs/AutoChangeLog-pr-12088.yml deleted file mode 100644 index 69587923bc9..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12088.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Shadow-Quill" -delete-after: True -changes: - - bugfix: "Fixed being able to talk in OOC under certain circumstances if it's disabled." diff --git a/html/changelogs/AutoChangeLog-pr-12089.yml b/html/changelogs/AutoChangeLog-pr-12089.yml deleted file mode 100644 index 8d5f4e12505..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12089.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Kurgis" -delete-after: True -changes: - - rscadd: "Beepsky now bumps around on its wheels when patrolling for crime." diff --git a/html/changelogs/AutoChangeLog-pr-12091.yml b/html/changelogs/AutoChangeLog-pr-12091.yml deleted file mode 100644 index a76858b61d4..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12091.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - bugfix: "Fixes random singularity releases from the grid check event" diff --git a/html/changelogs/AutoChangeLog-pr-12094.yml b/html/changelogs/AutoChangeLog-pr-12094.yml deleted file mode 100644 index 5993c40655a..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12094.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - bugfix: "Fixes plasmamen atmos techs not getting their proper suit" diff --git a/html/changelogs/AutoChangeLog-pr-12095.yml b/html/changelogs/AutoChangeLog-pr-12095.yml deleted file mode 100644 index eb2cbe520c7..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12095.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Ionward" -delete-after: True -changes: - - imageadd: "Drask crewmembers now have properly fitting shoes." - - imageadd: "Fixed some minor issues in Drasks uniforms" diff --git a/html/changelogs/AutoChangeLog-pr-12098.yml b/html/changelogs/AutoChangeLog-pr-12098.yml deleted file mode 100644 index 637f785d4e2..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12098.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - bugfix: "Unironically fixes about several thousand runtimes" diff --git a/html/changelogs/AutoChangeLog-pr-12099.yml b/html/changelogs/AutoChangeLog-pr-12099.yml deleted file mode 100644 index fe12a7a3ade..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12099.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Fox McCloud" -delete-after: True -changes: - - bugfix: "Fixes jackets not keeping you warm" diff --git a/icons/mob/actions/actions.dmi b/icons/mob/actions/actions.dmi index d3976bfff61..66795e14830 100644 Binary files a/icons/mob/actions/actions.dmi and b/icons/mob/actions/actions.dmi differ diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi index 09b1f1f79ba..6f3e3f0ea2e 100644 Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi index fcfef35c38b..e6f132a73a5 100644 Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 4bc39d8f80b..0fe42126ef0 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi index 8027568e31b..99be80fb681 100644 Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ diff --git a/icons/mob/species/drask/helmet.dmi b/icons/mob/species/drask/helmet.dmi index f6ade8dca0d..72b614bd3f2 100644 Binary files a/icons/mob/species/drask/helmet.dmi and b/icons/mob/species/drask/helmet.dmi differ diff --git a/icons/mob/species/drask/mask.dmi b/icons/mob/species/drask/mask.dmi index 096faf15970..27fa4502ad7 100644 Binary files a/icons/mob/species/drask/mask.dmi and b/icons/mob/species/drask/mask.dmi differ diff --git a/icons/mob/species/drask/shoes.dmi b/icons/mob/species/drask/shoes.dmi index 4710f9758c2..e51947fdd35 100644 Binary files a/icons/mob/species/drask/shoes.dmi and b/icons/mob/species/drask/shoes.dmi differ diff --git a/icons/mob/species/drask/uniform.dmi b/icons/mob/species/drask/uniform.dmi index 424d609399d..bb350b0a3d8 100644 Binary files a/icons/mob/species/drask/uniform.dmi and b/icons/mob/species/drask/uniform.dmi differ diff --git a/icons/mob/species/grey/helmet.dmi b/icons/mob/species/grey/helmet.dmi index b81d6617e17..b8942e8fd7f 100644 Binary files a/icons/mob/species/grey/helmet.dmi and b/icons/mob/species/grey/helmet.dmi differ diff --git a/icons/mob/species/grey/mask.dmi b/icons/mob/species/grey/mask.dmi index 6d13b33c4bf..cbbd722ae69 100644 Binary files a/icons/mob/species/grey/mask.dmi and b/icons/mob/species/grey/mask.dmi differ diff --git a/icons/mob/species/grey/uniform.dmi b/icons/mob/species/grey/uniform.dmi index 068ec0be122..c1e21d5fa11 100644 Binary files a/icons/mob/species/grey/uniform.dmi and b/icons/mob/species/grey/uniform.dmi differ diff --git a/icons/mob/species/tajaran/mask.dmi b/icons/mob/species/tajaran/mask.dmi index f73989fe9b0..d579a1c8384 100644 Binary files a/icons/mob/species/tajaran/mask.dmi and b/icons/mob/species/tajaran/mask.dmi differ diff --git a/icons/mob/species/unathi/mask.dmi b/icons/mob/species/unathi/mask.dmi index ba9be383855..535bec089f8 100644 Binary files a/icons/mob/species/unathi/mask.dmi and b/icons/mob/species/unathi/mask.dmi differ diff --git a/icons/mob/species/vox/helmet.dmi b/icons/mob/species/vox/helmet.dmi index a7186d611b6..74bd0762ff8 100644 Binary files a/icons/mob/species/vox/helmet.dmi and b/icons/mob/species/vox/helmet.dmi differ diff --git a/icons/mob/species/vox/mask.dmi b/icons/mob/species/vox/mask.dmi index 7023b2c3247..3e3a074c629 100644 Binary files a/icons/mob/species/vox/mask.dmi and b/icons/mob/species/vox/mask.dmi differ diff --git a/icons/mob/species/vox/shoes.dmi b/icons/mob/species/vox/shoes.dmi index 0a65993e240..99eac81e3a9 100644 Binary files a/icons/mob/species/vox/shoes.dmi and b/icons/mob/species/vox/shoes.dmi differ diff --git a/icons/mob/species/vox/suit.dmi b/icons/mob/species/vox/suit.dmi index 0716073b931..a088466564f 100644 Binary files a/icons/mob/species/vox/suit.dmi and b/icons/mob/species/vox/suit.dmi differ diff --git a/icons/mob/species/vox/uniform.dmi b/icons/mob/species/vox/uniform.dmi index f4d3eda8896..6334c7c7555 100644 Binary files a/icons/mob/species/vox/uniform.dmi and b/icons/mob/species/vox/uniform.dmi differ diff --git a/icons/mob/species/vulpkanin/mask.dmi b/icons/mob/species/vulpkanin/mask.dmi index e50c3421fb0..c839ee98e2d 100644 Binary files a/icons/mob/species/vulpkanin/mask.dmi and b/icons/mob/species/vulpkanin/mask.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index abce25ab86f..1427b5aaf10 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi index 69f9e04895e..1d96c0b9676 100644 Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi index 0f6aa860754..c0501f9bb36 100644 Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index a3d66d4d921..76be29d247d 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index b3a04ce73bf..5650a792d01 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi index b008f3139cc..30cdfae56ef 100644 Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 8371295985f..95e515f9f86 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi index 78586b72dfc..2a9fca9c57e 100644 Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ diff --git a/icons/obj/hydroponics/equipment.dmi b/icons/obj/hydroponics/equipment.dmi index f9e4f6bfbfc..9ad33b40e9d 100644 Binary files a/icons/obj/hydroponics/equipment.dmi and b/icons/obj/hydroponics/equipment.dmi differ diff --git a/icons/obj/hydroponics/growing.dmi b/icons/obj/hydroponics/growing.dmi index 5b63f0553bd..d66cdc2c0dd 100644 Binary files a/icons/obj/hydroponics/growing.dmi and b/icons/obj/hydroponics/growing.dmi differ diff --git a/icons/obj/hydroponics/harvest.dmi b/icons/obj/hydroponics/harvest.dmi index 53033eb8f48..3059eabe629 100644 Binary files a/icons/obj/hydroponics/harvest.dmi and b/icons/obj/hydroponics/harvest.dmi differ diff --git a/icons/obj/hydroponics/seeds.dmi b/icons/obj/hydroponics/seeds.dmi index a2415a71a8a..353d2811e67 100644 Binary files a/icons/obj/hydroponics/seeds.dmi and b/icons/obj/hydroponics/seeds.dmi differ diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi index 23e49287922..03f835232ac 100644 Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi index f28e5f83a33..edb8d7cb2c5 100644 Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ diff --git a/icons/obj/pipes/disposal.dmi b/icons/obj/pipes/disposal.dmi index f2dd62c9393..18d97345686 100644 Binary files a/icons/obj/pipes/disposal.dmi and b/icons/obj/pipes/disposal.dmi differ diff --git a/icons/obj/smooth_structures/sandbags.dmi b/icons/obj/smooth_structures/sandbags.dmi new file mode 100644 index 00000000000..8ac099555a8 Binary files /dev/null and b/icons/obj/smooth_structures/sandbags.dmi differ diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi index f30ecfe94d1..d1b6b267f8a 100644 Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ diff --git a/icons/obj/wizard.dmi b/icons/obj/wizard.dmi index 07c8be38ed9..83a80d2f408 100644 Binary files a/icons/obj/wizard.dmi and b/icons/obj/wizard.dmi differ diff --git a/paradise.dme b/paradise.dme index eef99066ad2..8f24c8a71ff 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1051,6 +1051,7 @@ #include "code\game\objects\structures\ladders.dm" #include "code\game\objects\structures\lamarr_cage.dm" #include "code\game\objects\structures\lattice.dm" +#include "code\game\objects\structures\loom.dm" #include "code\game\objects\structures\mineral_doors.dm" #include "code\game\objects\structures\mirror.dm" #include "code\game\objects\structures\misc.dm" @@ -1323,6 +1324,8 @@ #include "code\modules\client\preference\loadout\loadout_cosmetics.dm" #include "code\modules\client\preference\loadout\loadout_donor.dm" #include "code\modules\client\preference\loadout\loadout_general.dm" +#include "code\modules\client\preference\loadout\loadout_glasses.dm" +#include "code\modules\client\preference\loadout\loadout_gloves.dm" #include "code\modules\client\preference\loadout\loadout_hat.dm" #include "code\modules\client\preference\loadout\loadout_racial.dm" #include "code\modules\client\preference\loadout\loadout_shoes.dm" @@ -1337,6 +1340,7 @@ #include "code\modules\clothing\gloves\color.dm" #include "code\modules\clothing\gloves\miscellaneous.dm" #include "code\modules\clothing\gloves\rings.dm" +#include "code\modules\clothing\head\beanie.dm" #include "code\modules\clothing\head\collectable.dm" #include "code\modules\clothing\head\hardhat.dm" #include "code\modules\clothing\head\helmet.dm" @@ -1414,6 +1418,7 @@ #include "code\modules\crafting\craft.dm" #include "code\modules\crafting\guncrafting.dm" #include "code\modules\crafting\recipes.dm" +#include "code\modules\crafting\tailoring.dm" #include "code\modules\customitems\item_defines.dm" #include "code\modules\customitems\item_spawning.dm" #include "code\modules\detective_work\detective_work.dm" @@ -1584,6 +1589,7 @@ #include "code\modules\hydroponics\grown\citrus.dm" #include "code\modules\hydroponics\grown\cocoa_vanilla.dm" #include "code\modules\hydroponics\grown\corn.dm" +#include "code\modules\hydroponics\grown\cotton.dm" #include "code\modules\hydroponics\grown\eggplant.dm" #include "code\modules\hydroponics\grown\flowers.dm" #include "code\modules\hydroponics\grown\grass_carpet.dm"