diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 2f58d4e9ebb..a8a0459bcb1 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -7,4 +7,4 @@ assignees: '' --- -Please place all features requests here: https://nanotrasen.se/forum/60-suggestions/ +Please place all features requests here: https://www.paradisestation.org/forum/60-suggestions/ diff --git a/README.md b/README.md index d60fe8006c8..eafdb5ffe91 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![forthebadge](http://forthebadge.com/images/badges/contains-technical-debt.svg)](http://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/fuck-it-ship-it.svg)](http://forthebadge.com) -[Website](https://nanotrasen.se/) - [Code](https://github.com/ParadiseSS13/Paradise) - [Discord](https://discordapp.com/invite/YJDsXFE) +[Website](https://www.paradisestation.org/) - [Code](https://github.com/ParadiseSS13/Paradise) - [Discord](https://discordapp.com/invite/YJDsXFE) --- @@ -104,7 +104,7 @@ Your server details go in /config/dbconfig.txt, and the SQL schema is in /SQL/paradise_schema.sql or /SQL/paradise_schema_prefix.sql, depending on if you want table prefixes. More detailed setup instructions are located on our wiki: -https://nanotrasen.se/wiki/index.php/Setting_up_the_Database +https://www.paradisestation.org/wiki/index.php/Setting_up_the_Database --- diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index df957eaa11e..f9fba3ff4a4 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -155,6 +155,7 @@ // /mob/living/carbon signals #define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity)) +#define COMSIG_CARBON_LIFE "carbon_life" //from base of mob/living/carbon/Life() () // /mob/living/simple_animal/hostile signals #define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget" diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 7dd5fc5a609..169a5129eee 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -384,7 +384,7 @@ #define EXPLOSIVE_WALL_GROUP_SYNDICATE_BASE "syndicate_base" // Filters -#define FILTER_AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, border=4, color="#04080FAA") +#define FILTER_AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, color="#04080FAA") //Fullscreen overlay resolution in tiles. #define FULLSCREEN_OVERLAY_RESOLUTION_X 15 diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 49983658d48..5ffe891d95b 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -69,11 +69,6 @@ return list[index] return -/proc/islist(list/list) - if(istype(list)) - return 1 - return 0 - //Return either pick(list) or null if list is not of type /list or is empty /proc/safepick(list/list) if(!islist(list) || !list.len) diff --git a/code/__HELPERS/traits.dm b/code/__HELPERS/traits.dm index 472caea4490..7c1d2257e27 100644 --- a/code/__HELPERS/traits.dm +++ b/code/__HELPERS/traits.dm @@ -62,6 +62,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai //mob traits #define TRAIT_PACIFISM "pacifism" +#define TRAIT_WATERBREATH "waterbreathing" // common trait sources #define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention \ No newline at end of file diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 82295bc9d80..f1611b38fd9 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -540,9 +540,20 @@ Returns 1 if the chain up to the area contains the given typepath /proc/between(var/low, var/middle, var/high) return max(min(middle, high), low) -proc/arctan(x) + + +#if DM_VERSION > 513 +#warn 513 is definitely stable now, remove this +#endif +#if DM_VERSION < 513 +/proc/arctan(x) var/y=arcsin(x/sqrt(1+x*x)) return y +/proc/islist(list/list) + if(istype(list)) + return 1 + return 0 +#endif //returns random gauss number proc/GaussRand(var/sigma) diff --git a/code/_onclick/hud/plane_master.dm b/code/_onclick/hud/plane_master.dm index a5586578b3f..9c0f498cd83 100644 --- a/code/_onclick/hud/plane_master.dm +++ b/code/_onclick/hud/plane_master.dm @@ -16,7 +16,7 @@ filters += filter(type = "outline", size = _size, color = _color) /obj/screen/plane_master/proc/shadow(_size, _border, _offset = 0, _x = 0, _y = 0, _color = "#04080FAA") - filters += filter(type = "drop_shadow", x = _x, y = _y, color = _color, size = _size, offset = _offset, border = _border) + filters += filter(type = "drop_shadow", x = _x, y = _y, color = _color, size = _size, offset = _offset) /obj/screen/plane_master/proc/clear_filters() filters = list() diff --git a/code/controllers/subsystem/jobs.dm b/code/controllers/subsystem/jobs.dm index 166083b36ff..504a2d74a2c 100644 --- a/code/controllers/subsystem/jobs.dm +++ b/code/controllers/subsystem/jobs.dm @@ -421,23 +421,23 @@ SUBSYSTEM_DEF(jobs) to_chat(H, "You are the [alt_title ? alt_title : rank].") to_chat(H, "As the [alt_title ? alt_title : rank] you answer directly to [job.supervisors]. Special circumstances may change this.") - to_chat(H, "For more information on how the station works, see Standard Operating Procedure (SOP)") + to_chat(H, "For more information on how the station works, see Standard Operating Procedure (SOP)") if(job.is_service) - to_chat(H, "As a member of Service, make sure to read up on your Department SOP") + to_chat(H, "As a member of Service, make sure to read up on your Department SOP") if(job.is_supply) - to_chat(H, "As a member of Supply, make sure to read up on your Department SOP") + to_chat(H, "As a member of Supply, make sure to read up on your Department SOP") if(job.is_command) - to_chat(H, "As an important member of Command, read up on your Department SOP") + to_chat(H, "As an important member of Command, read up on your Department SOP") if(job.is_legal) - to_chat(H, "Your job requires complete knowledge of Space Law and Legal Standard Operating Procedure") + to_chat(H, "Your job requires complete knowledge of Space Law and Legal Standard Operating Procedure") if(job.is_engineering) - to_chat(H, "As a member of Engineering, make sure to read up on your Department SOP") + to_chat(H, "As a member of Engineering, make sure to read up on your Department SOP") if(job.is_medical) - to_chat(H, "As a member of Medbay, make sure to read up on your Department SOP") + to_chat(H, "As a member of Medbay, make sure to read up on your Department SOP") if(job.is_science) - to_chat(H, "As a member of Science, make sure to read up on your Department SOP") + to_chat(H, "As a member of Science, make sure to read up on your Department SOP") if(job.is_security) - to_chat(H, "As a member of Security, you are to know Space Law, Legal Standard Operating Procedure, as well as your Department SOP") + to_chat(H, "As a member of Security, you are to know Space Law, Legal Standard Operating Procedure, as well as your Department SOP") if(job.req_admin_notify) to_chat(H, "You are playing a job that is important for the game progression. If you have to disconnect, please notify the admins via adminhelp.") diff --git a/code/datums/spells/area_teleport.dm b/code/datums/spells/area_teleport.dm index 2f07f106d2a..4aa7eafbed6 100644 --- a/code/datums/spells/area_teleport.dm +++ b/code/datums/spells/area_teleport.dm @@ -25,10 +25,13 @@ var/A = null if(!randomise_selection) - A = input("Area to teleport to", "Teleport", A) in teleportlocs + A = input("Area to teleport to", "Teleport", A) as null|anything in teleportlocs else A = pick(teleportlocs) + if(!A) + return + var/area/thearea = teleportlocs[A] if(thearea.tele_proof && !istype(thearea, /area/wizard_station)) diff --git a/code/datums/spells/cluwne.dm b/code/datums/spells/cluwne.dm index 6a87419886c..58a33e31a44 100644 --- a/code/datums/spells/cluwne.dm +++ b/code/datums/spells/cluwne.dm @@ -17,7 +17,7 @@ var/obj/item/organ/internal/brain/cluwne/idiot_brain = new idiot_brain.insert(src, make_cluwne = 0) idiot_brain.dna = dna.Clone() - setBrainLoss(80) + setBrainLoss(80, use_brain_mod = FALSE) set_nutrition(9000) overeatduration = 9000 Confused(30) diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm index b6a0213f82f..a9d1c3bb480 100644 --- a/code/game/gamemodes/changeling/evolution_menu.dm +++ b/code/game/gamemodes/changeling/evolution_menu.dm @@ -383,6 +383,9 @@ var/list/sting_paths var/mob/living/carbon/C = src //only carbons have dna now, so we have to typecaste mind.changeling.absorbed_dna |= C.dna.Clone() mind.changeling.trim_dna() + + RegisterSignal(C, COMSIG_CARBON_LIFE, CALLBACK(C, /mob/living/carbon/.proc/handle_changeling)) + return 1 //Used to dump the languages from the changeling datum into the actual mob. @@ -421,6 +424,8 @@ var/list/sting_paths if(hud_used) hud_used.lingstingdisplay.icon_state = null hud_used.lingstingdisplay.invisibility = 101 + hud_used.lingchemdisplay.invisibility = 101 + UnregisterSignal(src, COMSIG_CARBON_LIFE) /datum/changeling/proc/has_sting(datum/action/power) for(var/datum/action/P in purchasedpowers) diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index d30ac4f8a68..3489a087ec0 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -198,7 +198,7 @@ var/list/blacklisted_pylon_turfs = typecacheof(list( if(last_heal <= world.time) last_heal = world.time + heal_delay for(var/mob/living/L in range(5, src)) - if(iscultist(L) || istype(L, /mob/living/simple_animal/shade) || istype(L, /mob/living/simple_animal/hostile/construct)) + if(iscultist(L) || iswizard(L) || istype(L, /mob/living/simple_animal/shade) || istype(L, /mob/living/simple_animal/hostile/construct)) if(L.health != L.maxHealth) new /obj/effect/temp_visual/heal(get_turf(src), "#960000") if(ishuman(L)) diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm index 908eaa5360f..9fce3cc6e24 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction.dm @@ -184,7 +184,7 @@ var/obj/machinery/abductor/console/con = get_team_console(team_number) var/datum/objective/objective = team_objectives[team_number] if(con.experiment.points >= objective.target_amount) - SSshuttle.emergency.request(null, 0.5) + SSshuttle.emergency.request(null, 0.5, reason = "Large amount of abnormal thought patterns detected. All crew are recalled for mandatory evaluation and reconditioning.") SSshuttle.emergency.canRecall = FALSE finished = 1 return ..() diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index b761af6db92..f86f018757e 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -162,7 +162,7 @@ to_chat(src, "You are invincible and invisible to everyone but other ghosts. Most abilities will reveal you, rendering you vulnerable.") to_chat(src, "To function, you are to drain the life essence from humans. This essence is a resource, as well as your health, and will power all of your abilities.") to_chat(src, "You do not remember anything of your past lives, nor will you remember anything about this one after your death.") - to_chat(src, "Be sure to read the wiki page at http://nanotrasen.se/wiki/index.php/Revenant to learn more.") + to_chat(src, "Be sure to read the wiki page at http://www.paradisestation.org/wiki/index.php/Revenant to learn more.") var/datum/objective/revenant/objective = new objective.owner = mind mind.objectives += objective diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm index b580f88c0b7..b4b4b265711 100644 --- a/code/game/gamemodes/shadowling/shadowling.dm +++ b/code/game/gamemodes/shadowling/shadowling.dm @@ -126,7 +126,7 @@ Made by Xhuis to_chat(shadow.current, "Currently, you are disguised as an employee aboard [world.name].") to_chat(shadow.current, "In your limited state, you have two abilities: Hatch and Shadowling Hivemind (:8).") to_chat(shadow.current, "Any other shadowlings are your allies. You must assist them as they shall assist you.") - to_chat(shadow.current, "If you are new to shadowling, or want to read about abilities, check the wiki page at http://nanotrasen.se/wiki/index.php/Shadowling
") + to_chat(shadow.current, "If you are new to shadowling, or want to read about abilities, check the wiki page at https://www.paradisestation.org/wiki/index.php/Shadowling
") diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index 520e6939b60..2edbb41cb95 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -205,19 +205,19 @@ /obj/item/proc/transfer_soul(var/choice as text, var/target, var/mob/U as mob) switch(choice) if("FORCE") - var/obj/item/soulstone/C = src + var/obj/item/soulstone/SS = src var/mob/living/T = target if(T.client != null) - C.init_shade(T, U) + SS.init_shade(T, U) else to_chat(U, "Capture failed!: The soul has already fled its mortal frame. You attempt to bring it back...") T.Paralyse(20) - if(!C.getCultGhost(T,U)) + if(!SS.getCultGhost(T,U)) T.dust() //If we can't get a ghost, kill the sacrifice anyway. if("VICTIM") var/mob/living/carbon/human/T = target - var/obj/item/soulstone/C = src + var/obj/item/soulstone/SS = src if(T.stat == 0) to_chat(U, "Capture failed!: Kill or maim the victim first!") else @@ -226,92 +226,67 @@ else if(T.client == null) to_chat(U, "Capture failed!: The soul has already fled its mortal frame. You attempt to bring it back...") - C.getCultGhost(T,U) + SS.getCultGhost(T,U) else - if(C.contents.len) + if(SS.contents.len) to_chat(U, "Capture failed!: The soul stone is full! Use or free an existing soul to make room.") else - C.init_shade(T, U, vic = 1) + SS.init_shade(T, U, vic = 1) if("SHADE") var/mob/living/simple_animal/shade/T = target - var/obj/item/soulstone/C = src - if(!C.can_use(U)) + var/obj/item/soulstone/SS = src + if(!SS.can_use(U)) U.Paralyse(5) to_chat(U, "Your body is wracked with debilitating pain!") return if(T.stat == DEAD) to_chat(U, "Capture failed!: The shade has already been banished!") else - if(C.contents.len) + if(SS.contents.len) to_chat(U, "Capture failed!: The soul stone is full! Use or free an existing soul to make room.") else - T.loc = C //put shade in stone + T.loc = SS //put shade in stone T.status_flags |= GODMODE T.canmove = 0 T.health = T.maxHealth T.faction |= "\ref[U]" - C.icon_state = "soulstone2" + SS.icon_state = "soulstone2" to_chat(T, "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form") to_chat(U, "Capture successful!: [T.name]'s has been recaptured and stored within the soul stone.") if("CONSTRUCT") var/obj/structure/constructshell/T = target - var/obj/item/soulstone/C = src - var/mob/living/simple_animal/shade/A = locate() in C - if(A) + var/obj/item/soulstone/SS = src + var/mob/living/simple_animal/shade/SH = locate() in SS + if(SH) var/construct_class = alert(U, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer") switch(construct_class) if("Juggernaut") - var/mob/living/simple_animal/hostile/construct/armoured/Z = new /mob/living/simple_animal/hostile/construct/armoured (get_turf(T.loc)) - Z.key = A.key - Z.faction |= "\ref[U]" - if(iscultist(U)) - if(SSticker.mode.name == "cult") - SSticker.mode:add_cultist(Z.mind) - else - SSticker.mode.cult+=Z.mind - SSticker.mode.update_cult_icons_added(Z.mind) - qdel(T) - to_chat(Z, "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, create shield walls and even deflect energy weapons, and rip apart enemies and walls alike.") - to_chat(Z, "You are still bound to serve your creator, follow [U.p_their()] orders and help [U.p_them()] complete [U.p_their()] goals at all costs.") - Z.cancel_camera() - qdel(C) + var/mob/living/simple_animal/hostile/construct/armoured/C = new /mob/living/simple_animal/hostile/construct/armoured (get_turf(T.loc)) + to_chat(C, "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, create shield walls and even deflect energy weapons, and rip apart enemies and walls alike.") + init_construct(C,SH,SS,T) if("Wraith") - var/mob/living/simple_animal/hostile/construct/wraith/Z = new /mob/living/simple_animal/hostile/construct/wraith (get_turf(T.loc)) - Z.key = A.key - Z.faction |= "\ref[U]" - if(iscultist(U)) - if(SSticker.mode.name == "cult") - SSticker.mode:add_cultist(Z.mind) - else - SSticker.mode.cult+=Z.mind - SSticker.mode.update_cult_icons_added(Z.mind) - qdel(T) - to_chat(Z, "You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.") - to_chat(Z, "You are still bound to serve your creator, follow [U.p_their()] orders and help [U.p_them()] complete [U.p_their()] goals at all costs.") - Z.cancel_camera() - qdel(C) + var/mob/living/simple_animal/hostile/construct/wraith/C = new /mob/living/simple_animal/hostile/construct/wraith (get_turf(T.loc)) + to_chat(C, "You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.") + init_construct(C,SH,SS,T) if("Artificer") - var/mob/living/simple_animal/hostile/construct/builder/Z = new /mob/living/simple_animal/hostile/construct/builder (get_turf(T.loc)) - Z.key = A.key - Z.faction |= "\ref[U]" - if(iscultist(U)) - if(SSticker.mode.name == "cult") - SSticker.mode:add_cultist(Z.mind) - else - SSticker.mode.cult+=Z.mind - SSticker.mode.update_cult_icons_added(Z.mind) - qdel(T) - to_chat(Z, "You are an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, use magic missile, repair allied constructs (by clicking on them), and most important of all create new constructs (Use your Artificer spell to summon a new construct shell and Summon Soulstone to create a new soulstone).") - to_chat(Z, "You are still bound to serve your creator, follow [U.p_their()] orders and help [U.p_them()] complete [U.p_their()] goals at all costs.") - Z.cancel_camera() - qdel(C) + var/mob/living/simple_animal/hostile/construct/builder/C = new /mob/living/simple_animal/hostile/construct/builder (get_turf(T.loc)) + to_chat(C, "You are an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, use magic missile, repair allied constructs (by clicking on them), and most important of all create new constructs (Use your Artificer spell to summon a new construct shell and Summon Soulstone to create a new soulstone).") + init_construct(C,SH,SS,T) else to_chat(U, "Creation failed!: The soul stone is empty! Go kill someone!") return +/proc/init_construct(mob/living/simple_animal/hostile/construct/C, mob/living/simple_animal/shade/SH, obj/item/soulstone/SS, obj/structure/constructshell/T) + SH.mind.transfer_to(C) + qdel(T) + qdel(SH) + to_chat(C, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") + C.cancel_camera() + qdel(SS) + /proc/makeNewConstruct(var/mob/living/simple_animal/hostile/construct/ctype, var/mob/target, var/mob/stoner = null, cultoverride = 0) if(jobban_isbanned(target, "cultist") || jobban_isbanned(target, "Syndicate")) return @@ -325,11 +300,11 @@ SSticker.mode.cult+=newstruct.mind SSticker.mode.update_cult_icons_added(newstruct.mind) if(stoner && iswizard(stoner)) - to_chat(newstruct, "You are still bound to serve your creator, follow [stoner.p_their()] orders and help [stoner.p_them()] complete [stoner.p_their()] goals at all costs.") + to_chat(newstruct, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") else if(stoner && iscultist(stoner)) - to_chat(newstruct, "You are still bound to serve the cult, follow [stoner.p_their()] orders and help [stoner.p_them()] complete [stoner.p_their()] goals at all costs.") + to_chat(newstruct, "You are still bound to serve the cult, follow their orders and help them complete their goals at all costs.") else - to_chat(newstruct, "You are still bound to serve your creator, follow [stoner.p_their()] orders and help [stoner.p_them()] complete [stoner.p_their()] goals at all costs.") + to_chat(newstruct, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") newstruct.cancel_camera() /obj/item/soulstone/proc/init_shade(mob/living/T, mob/U, vic = 0) @@ -348,17 +323,22 @@ S.name = "Shade of [T.real_name]" S.real_name = "Shade of [T.real_name]" S.key = T.key - if(U) - S.faction |= "\ref[U]" //Add the master as a faction, allowing inter-mob cooperation - if(U && iscultist(U)) - SSticker.mode.add_cultist(S.mind, 0) S.cancel_camera() name = "soulstone: Shade of [T.real_name]" icon_state = "soulstone2" - if(U && iswizard(U)) - to_chat(S, "Your soul has been captured! You are now bound to [U.real_name]'s will. Help [U.p_them()] succeed in their goals at all costs.") - else if(U && iscultist(U)) - to_chat(S, "Your soul has been captured! You are now bound to the cult's will. Help [U.p_them()] succeed in their goals at all costs.") + if(U) + S.faction |= "\ref[U]" //Add the master as a faction, allowing inter-mob cooperation + if(iswizard(U)) + SSticker.mode.update_wiz_icons_added(S.mind) + S.mind.special_role = SPECIAL_ROLE_WIZARD_APPRENTICE + if(iscultist(U)) + SSticker.mode.add_cultist(S.mind, 0) + S.mind.special_role = SPECIAL_ROLE_CULTIST + S.mind.store_memory("Serve the cult's will.") + to_chat(S, "Your soul has been captured! You are now bound to the cult's will. Help them succeed in their goals at all costs.") + else + S.mind.store_memory("Serve [U.real_name], your creator.") + to_chat(S, "Your soul has been captured! You are now bound to [U.real_name]'s will. Help them succeed in their goals at all costs.") if(vic && U) to_chat(U, "Capture successful!: [T.real_name]'s soul has been ripped from [U.p_their()] body and stored within the soul stone.") if(isrobot(T))//Robots have to dust or else they spill out an empty robot brain, and unequiping them spills robot components that shouldn't spawn. diff --git a/code/game/machinery/poolcontroller.dm b/code/game/machinery/poolcontroller.dm index 4b512297ffd..12804cfcc88 100644 --- a/code/game/machinery/poolcontroller.dm +++ b/code/game/machinery/poolcontroller.dm @@ -28,21 +28,21 @@ /obj/machinery/poolcontroller/invisible/sea name = "Sea Controller" desc = "A controller for the underwater portion of the sea. Players shouldn't see this." - deep_water = TRUE + deep_water = TRUE -/obj/machinery/poolcontroller/Initialize(mapload) - var/contents_loop = linked_area +/obj/machinery/poolcontroller/Initialize(mapload) + var/contents_loop = linked_area if(!linked_area) contents_loop = range(srange, src) for(var/turf/T in contents_loop) if(istype(T, /turf/simulated/floor/beach/water)) var/turf/simulated/floor/beach/water/W = T - W.linkedcontroller = src + W.linkedcontroller = src linkedturfs += T else if(istype(T, /turf/unsimulated/beach/water)) var/turf/unsimulated/beach/water/W = T - W.linkedcontroller = src + W.linkedcontroller = src linkedturfs += T . = ..() @@ -121,7 +121,7 @@ return //Has internals, no drowning if((NO_BREATHE in drownee.dna.species.species_traits) || (BREATHLESS in drownee.mutations)) return //doesn't breathe, no drowning - if(isskrell(drownee) || isneara(drownee)) + if(HAS_TRAIT(drownee,TRAIT_WATERBREATH)) return //fish things don't drown if(drownee.stat == DEAD) //Dead spacemen don't drown more diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index eb3052dd909..eecdc0e4f4a 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -8,6 +8,7 @@ var/const/SAFETY_COOLDOWN = 100 layer = MOB_LAYER+1 // Overhead anchored = 1 density = 1 + damage_deflection = 10 var/safety_mode = 0 // Temporarily stops machine if it detects a mob var/icon_name = "grinder-o" var/blood = 0 diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 5b5f483b94f..aacd605b730 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -316,40 +316,38 @@ var/mob/originaloccupant = chassis.occupant spawn(0) src = null //if src is deleted, still process the syringe - for(var/i=0, i<6, i++) + var/max_range = 6 + for(var/i=0, i [M] was hit by the syringe!") - if(M.can_inject(null, TRUE)) - if(mechsyringe.reagents) - for(var/datum/reagent/A in mechsyringe.reagents.reagent_list) - R += A.id + " (" - R += num2text(A.volume) + ")," - add_attack_logs(originaloccupant, M, "Shot with [src] containing [R], transferred [mechsyringe.reagents.total_volume] units") - mechsyringe.icon_state = initial(mechsyringe.icon_state) - mechsyringe.icon = initial(mechsyringe.icon) - mechsyringe.reagents.reaction(M, INGEST) - mechsyringe.reagents.trans_to(M, mechsyringe.reagents.total_volume) - M.take_organ_damage(2) - break - else if(mechsyringe.loc == trg) - mechsyringe.icon_state = initial(mechsyringe.icon_state) - mechsyringe.icon = initial(mechsyringe.icon) - mechsyringe.update_icon() - break - else - mechsyringe.icon_state = initial(mechsyringe.icon_state) - mechsyringe.icon = initial(mechsyringe.icon) - mechsyringe.update_icon() + if(!step_towards(mechsyringe,trg)) + break + + var/list/mobs = new + for(var/mob/living/carbon/M in mechsyringe.loc) + mobs += M + var/mob/living/carbon/M = safepick(mobs) + if(M) + var/R + mechsyringe.visible_message(" [M] was hit by the syringe!") + if(M.can_inject(null, TRUE)) + if(mechsyringe.reagents) + for(var/datum/reagent/A in mechsyringe.reagents.reagent_list) + R += A.id + " (" + R += num2text(A.volume) + ")," + add_attack_logs(originaloccupant, M, "Shot with [src] containing [R], transferred [mechsyringe.reagents.total_volume] units") + mechsyringe.reagents.reaction(M, INGEST) + mechsyringe.reagents.trans_to(M, mechsyringe.reagents.total_volume) + M.take_organ_damage(2) + break + else if(mechsyringe.loc == trg) break sleep(1) + if(mechsyringe) + // Revert the syringe icon to normal one once it stops flying. + mechsyringe.icon_state = initial(mechsyringe.icon_state) + mechsyringe.icon = initial(mechsyringe.icon) + mechsyringe.update_icon() return 1 diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 7dc1a97a735..9f8c877aa24 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -12,7 +12,7 @@ var/heal_brute = 0 var/heal_burn = 0 var/self_delay = 20 - var/unique_handling = 0 //some things give a special prompt, do we want to bypass some checks in parent? + var/unique_handling = FALSE //some things give a special prompt, do we want to bypass some checks in parent? var/stop_bleeding = 0 var/healverb = "bandage" @@ -31,28 +31,20 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_selected) if(!H.can_inject(user, TRUE)) - return 1 + return TRUE if(!affecting) to_chat(user, "That limb is missing!") - return 1 + return TRUE if(affecting.is_robotic()) to_chat(user, "This can't be used on a robotic limb.") - return 1 - - if(stop_bleeding) - if(H.bleedsuppress) - to_chat(user, "[H]'s bleeding is already bandaged!") - return 1 - else if(!H.bleed_rate) - to_chat(user, "[H] isn't bleeding!") - return 1 + return TRUE if(M == user && !unique_handling) user.visible_message("[user] starts to apply [src] on [H]...") if(!do_mob(user, H, self_delay)) - return 1 + return TRUE return if(isanimal(M)) @@ -123,6 +115,7 @@ desc = "Some sterile gauze to wrap around bloody stumps." icon_state = "gauze" origin_tech = "biotech=2" + heal_brute = 10 stop_bleeding = 1800 /obj/item/stack/medical/bruise_pack/attackby(obj/item/I, mob/user, params) @@ -140,13 +133,13 @@ /obj/item/stack/medical/bruise_pack/attack(mob/living/M, mob/user) if(..()) - return 1 + return TRUE if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/affecting = H.get_organ(user.zone_selected) - if(affecting.open == 0) + if(affecting.open == FALSE) affecting.germ_level = 0 if(stop_bleeding) @@ -187,6 +180,7 @@ icon_state = "ointment" origin_tech = "biotech=2" healverb = "salve" + heal_burn = 10 /obj/item/stack/medical/ointment/attack(mob/living/M, mob/user) if(..()) @@ -196,7 +190,7 @@ var/mob/living/carbon/human/H = M var/obj/item/organ/external/affecting = H.get_organ(user.zone_selected) - if(affecting.open == 0) + if(affecting.open == FALSE) affecting.germ_level = 0 heal(H, user) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 71d5e36badf..0ad64e24f23 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1069,6 +1069,22 @@ obj/item/toy/cards/deck/syndicate/black name = "tuxedo cat plushie" icon_state = "tuxedocat" +/obj/item/toy/plushie/voxplushie + name = "vox plushie" + desc = "A stitched-together vox, fresh from the skipjack. Press its belly to hear it skree!" + icon_state = "plushie_vox" + item_state = "plushie_vox" + var/cooldown = 0 + +/obj/item/toy/plushie/voxplushie/attack_self(mob/user) + if(!cooldown) + playsound(user, 'sound/voice/shriek1.ogg', 10, 0) + visible_message("Skreee!") + cooldown = 1 + spawn(30) cooldown = 0 + return + ..() + //New generation TG plushies /obj/item/toy/plushie/lizardplushie diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm index 4d36c640784..4cc4cb948ce 100644 --- a/code/game/objects/items/weapons/manuals.dm +++ b/code/game/objects/items/weapons/manuals.dm @@ -18,7 +18,7 @@ - + @@ -164,7 +164,7 @@ - + @@ -805,7 +805,7 @@ - + @@ -828,7 +828,7 @@ - + diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 5560f3b4306..0ebd553fc3b 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -396,7 +396,7 @@ ..() new /obj/item/lightreplacer(src) new /obj/item/holosign_creator(src) - new /obj/item/reagent_containers/spray(src) + new /obj/item/reagent_containers/spray/cleaner(src) new /obj/item/soap(src) new /obj/item/grenade/chem_grenade/cleaner(src) new /obj/item/grenade/chem_grenade/cleaner(src) diff --git a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm index a89bce34396..504d2b29644 100644 --- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm @@ -104,6 +104,7 @@ icon_opened = "toolclosetopen" /obj/structure/closet/toolcloset/New() + ..() if(prob(40)) new /obj/item/clothing/suit/storage/hazardvest(src) if(prob(70)) diff --git a/code/game/objects/structures/reflector.dm b/code/game/objects/structures/reflector.dm index e3ebb0579a4..51738446750 100644 --- a/code/game/objects/structures/reflector.dm +++ b/code/game/objects/structures/reflector.dm @@ -12,9 +12,9 @@ /obj/structure/reflector/bullet_act(obj/item/projectile/P) var/turf/reflector_turf = get_turf(src) var/turf/reflect_turf - var/new_dir = get_reflection(dir, P.dir) if(!istype(P, /obj/item/projectile/beam)) return ..() + var/new_dir = get_reflection(dir, P.dir) if(new_dir) reflect_turf = get_step(reflect_turf, new_dir) else @@ -30,6 +30,10 @@ P.current = reflector_turf P.yo = reflect_turf.y - reflector_turf.y P.xo = reflect_turf.x - reflector_turf.x + P.ignore_source_check = TRUE //If shot by a laser, will now hit the mob that fired it + var/reflect_angle = dir2angle(new_dir) + P.setAngle(reflect_angle) + new_dir = 0 return -1 diff --git a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm index f8c65089324..6a2180efcac 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm @@ -8,6 +8,7 @@ max_integrity = 120 var/image/nest_overlay comfort = 0 + flags = NODECONSTRUCT /obj/structure/bed/nest/New() nest_overlay = image('icons/mob/alien.dmi', "nestoverlay", layer=MOB_LAYER - 0.2) diff --git a/code/modules/admin/verbs/freeze.dm b/code/modules/admin/verbs/freeze.dm index 4d60fb72bee..9b01e94846c 100644 --- a/code/modules/admin/verbs/freeze.dm +++ b/code/modules/admin/verbs/freeze.dm @@ -26,7 +26,7 @@ var/global/list/frozen_mob_list = list() /mob/living/var/frozen = null //used for preventing attacks on admin-frozen mobs /mob/living/var/admin_prev_sleeping = 0 //used for keeping track of previous sleeping value with admin freeze -/mob/living/proc/admin_Freeze(var/client/admin, skip_overlays = FALSE) +/mob/living/proc/admin_Freeze(client/admin, skip_overlays = FALSE) if(istype(admin)) to_chat(src, "You have been frozen by [admin]") message_admins("[key_name_admin(admin)] froze [key_name_admin(src)]") @@ -34,24 +34,27 @@ var/global/list/frozen_mob_list = list() var/obj/effect/overlay/adminoverlay/AO = new if(skip_overlays) - src.overlays += AO + overlays += AO - anchored = 1 - frozen = AO + anchored = TRUE + canmove = FALSE admin_prev_sleeping = sleeping AdjustSleeping(20000) + frozen = AO if(!(src in frozen_mob_list)) frozen_mob_list += src -/mob/living/proc/admin_unFreeze(var/client/admin, skip_overlays = FALSE) +/mob/living/proc/admin_unFreeze(client/admin, skip_overlays = FALSE) if(istype(admin)) to_chat(src, "You have been unfrozen by [admin]") message_admins("[key_name_admin(admin)] unfroze [key_name_admin(src)]") log_admin("[key_name(admin)] unfroze [key_name(src)]") - anchored = 0 if(skip_overlays) overlays -= frozen + + anchored = FALSE + canmove = TRUE frozen = null SetSleeping(admin_prev_sleeping) admin_prev_sleeping = null diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 9c06c94bb5b..9e6f1b79bfa 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -28,6 +28,7 @@ forge_traitor_objectives() if(!silent) greet() + apply_innate_effects() update_traitor_icons_added() finalize_traitor() @@ -54,6 +55,7 @@ assigned_targets.Cut() SSticker.mode.traitors -= owner owner.special_role = null + remove_innate_effects() update_traitor_icons_removed() if(!silent && owner.current) @@ -67,8 +69,10 @@ if(owner.assigned_role == "Clown") var/mob/living/carbon/human/traitor_mob = owner.current if(traitor_mob && istype(traitor_mob)) - to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") + to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") traitor_mob.mutations.Remove(CLUMSY) + var/datum/action/innate/toggle_clumsy/A = new + A.Grant(traitor_mob) /datum/antagonist/traitor/remove_innate_effects() @@ -76,7 +80,11 @@ if(owner.assigned_role == "Clown") var/mob/living/carbon/human/traitor_mob = owner.current if(traitor_mob && istype(traitor_mob)) + to_chat(traitor_mob, "You lose your syndicate training and return to your own clumsy, clownish self.") traitor_mob.mutations.Add(CLUMSY) + for(var/datum/action/innate/A in traitor_mob.actions) + if(istype(A, /datum/action/innate/toggle_clumsy)) + A.Remove(traitor_mob) // Adding/removing objectives in the owner's mind until we can datumize all antags. Then we can use the /datum/antagonist/objectives var to handle them // Change "owner.objectives" to "objectives" once objectives are handled in antag datums instead of the mind diff --git a/code/modules/client/preference/loadout/loadout_racial.dm b/code/modules/client/preference/loadout/loadout_racial.dm index 38d216ae156..2acec90e7b7 100644 --- a/code/modules/client/preference/loadout/loadout_racial.dm +++ b/code/modules/client/preference/loadout/loadout_racial.dm @@ -1,38 +1,40 @@ /datum/gear/racial sort_category = "Racial" subtype_path = /datum/gear/racial + +/datum/gear/racial/taj + slot = slot_glasses cost = 2 - -/datum/gear/racial/tajciv +/datum/gear/racial/taj/civ display_name = "embroidered veil" description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races." path = /obj/item/clothing/glasses/tajblind cost = 1 -/datum/gear/racial/tajsec +/datum/gear/racial/taj/sec display_name = "sleek veil" description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races. This one has an in-built security HUD." path = /obj/item/clothing/glasses/hud/security/tajblind allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot", "Internal Affairs Agent", "Magistrate") -/datum/gear/racial/tajmed +/datum/gear/racial/taj/med display_name = "lightweight veil" description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races. This one has an in-built medical HUD." path = /obj/item/clothing/glasses/hud/health/tajblind allowed_roles = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Psychiatrist", "Paramedic", "Virologist", "Brig Physician" , "Coroner") -/datum/gear/racial/tajsci +/datum/gear/racial/taj/sci display_name = "hi-tech veil" description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races." path = /obj/item/clothing/glasses/tajblind/sci -/datum/gear/racial/tajeng +/datum/gear/racial/taj/eng display_name = "industrial veil" description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races." path = /obj/item/clothing/glasses/tajblind/eng -/datum/gear/racial/tajcargo +/datum/gear/racial/taj/cargo display_name = "khaki veil" description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races. It is light and comfy!" path = /obj/item/clothing/glasses/tajblind/cargo @@ -40,4 +42,5 @@ /datum/gear/racial/footwraps display_name = "cloth footwraps" path = /obj/item/clothing/shoes/footwraps - cost = 1 \ No newline at end of file + slot = slot_shoes + cost = 1 diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 1c99d2d1bc0..ece0b5c607e 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -197,8 +197,8 @@ var/list/event_last_fired = list() new /datum/event_meta/alien(EVENT_LEVEL_MAJOR, "Alien Infestation", /datum/event/alien_infestation, 0, list(ASSIGNMENT_SECURITY = 15), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Traders", /datum/event/traders, 180, is_one_shot = 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Terror Spiders", /datum/event/spider_terror, 0, list(ASSIGNMENT_SECURITY = 15), is_one_shot = 1), - new /datum/event_meta(EVENT_LEVEL_MAJOR, "Slaughter Demon", /datum/event/spawn_slaughter, 15, is_one_shot = 1), - new /datum/event_meta(EVENT_LEVEL_MAJOR, "Floor Cluwne", /datum/event/spawn_floor_cluwne, 15, is_one_shot = 1) + new /datum/event_meta(EVENT_LEVEL_MAJOR, "Slaughter Demon", /datum/event/spawn_slaughter, 15, is_one_shot = 1) + //new /datum/event_meta(EVENT_LEVEL_MAJOR, "Floor Cluwne", /datum/event/spawn_floor_cluwne, 15, is_one_shot = 1) ) diff --git a/code/modules/events/sentience.dm b/code/modules/events/sentience.dm index 52e8918a16c..fb896e9e2a6 100644 --- a/code/modules/events/sentience.dm +++ b/code/modules/events/sentience.dm @@ -36,9 +36,9 @@ SA.universal_speak = 1 SA.sentience_act() SA.can_collar = 1 - SA.maxHealth = max(SA.maxHealth + 200) - SA.melee_damage_lower = max(SA.melee_damage_lower + 15) - SA.melee_damage_upper = max(SA.melee_damage_upper + 15) + SA.maxHealth += 200 + SA.melee_damage_lower += 15 + SA.melee_damage_upper += 15 SA.health = SA.maxHealth SA.del_on_death = FALSE greet_sentient(SA) @@ -50,4 +50,3 @@ to_chat(M, "Due to freak radiation, you have gained \ human level intelligence and the ability to speak and understand \ human language!") - diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index fd60d5d49bd..af6bdb26af5 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -774,11 +774,14 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, spawn(0) resist_muzzle() if(restrained()) + var/obj/item/I = handcuffed + var/breakouttime = I.breakouttime + var/displaytime = breakouttime / 10 changeNext_move(CLICK_CD_BREAKOUT) last_special = world.time + CLICK_CD_BREAKOUT visible_message("[src] attempts to unbuckle [p_them()]self!", \ - "You attempt to unbuckle yourself... (This will take around one minute and you need to stay still.)") - if(do_after(src, 600, 0, target = src)) + "You attempt to unbuckle yourself... (This will take around [displaytime] seconds and you need to stay still.)") + if(do_after(src, breakouttime, 0, target = src)) if(!buckled) return buckled.user_unbuckle_mob(src,src) @@ -836,10 +839,10 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, /mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0) breakouttime = I.breakouttime - var/displaytime = breakouttime / 600 + var/displaytime = breakouttime / 10 if(!cuff_break) visible_message("[src] attempts to remove [I]!") - to_chat(src, "You attempt to remove [I]... (This will take around [displaytime] minutes and you need to stand still.)") + to_chat(src, "You attempt to remove [I]... (This will take around [displaytime] seconds and you need to stand still.)") if(do_after(src, breakouttime, 0, target = src)) if(I.loc != src || buckled) return diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 7a18e881eb6..b859041d02f 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -215,6 +215,12 @@ else if(E.status & ORGAN_SPLINTED) wound_flavor_text["[E.limb_name]"] = "[p_they(TRUE)] [p_have()] a splint on [p_their()] [E.name]!\n" + if(E.open) + if(E.is_robotic()) + msg += "The maintenance hatch on [p_their()] [ignore_limb_branding(E.limb_name)] is open!\n" + else + msg += "[p_their(TRUE)] [ignore_limb_branding(E.limb_name)] has an open incision!\n" + for(var/obj/item/I in E.embedded_objects) msg += "[p_they(TRUE)] [p_have()] \a [bicon(I)] [I] embedded in [p_their()] [E.name]!\n" @@ -403,3 +409,29 @@ return 0 else return 0 + +// Ignores robotic limb branding prefixes like "Morpheus Cybernetics" +/proc/ignore_limb_branding(limb_name) + switch(limb_name) + if("chest") + . = "upper body" + if("groin") + . = "lower body" + if("head") + . = "head" + if("l_arm") + . = "left arm" + if("r_arm") + . = "right arm" + if("l_leg") + . = "left leg" + if("r_leg") + . = "right leg" + if("l_foot") + . = "left foot" + if("r_foot") + . = "right foot" + if("l_hand") + . = "left hand" + if("r_hand") + . = "right hand" diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 71a3ae3e87c..65a75f80e8c 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -22,7 +22,7 @@ med_hud_set_status() handle_hud_icons_health() -/mob/living/carbon/human/adjustBrainLoss(amount, updating = TRUE) +/mob/living/carbon/human/adjustBrainLoss(amount, updating = TRUE, use_brain_mod = TRUE) if(status_flags & GODMODE) return STATUS_UPDATE_NONE //godmode @@ -30,7 +30,8 @@ var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain) if(sponge) if(dna.species && amount > 0) - amount = amount * dna.species.brain_mod + if(use_brain_mod) + amount = amount * dna.species.brain_mod sponge.damage = Clamp(sponge.damage + amount, 0, 120) if(sponge.damage >= 120) visible_message("[src] goes limp, [p_their()] facial expression utterly blank.") @@ -39,7 +40,7 @@ update_stat("adjustBrainLoss") return STATUS_UPDATE_STAT -/mob/living/carbon/human/setBrainLoss(amount, updating = TRUE) +/mob/living/carbon/human/setBrainLoss(amount, updating = TRUE, use_brain_mod = TRUE) if(status_flags & GODMODE) return STATUS_UPDATE_NONE //godmode @@ -47,7 +48,8 @@ var/obj/item/organ/internal/brain/sponge = get_int_organ(/obj/item/organ/internal/brain) if(sponge) if(dna.species && amount > 0) - amount = amount * dna.species.brain_mod + if(use_brain_mod) + amount = amount * dna.species.brain_mod sponge.damage = Clamp(amount, 0, 120) if(sponge.damage >= 120) visible_message("[src] goes limp, [p_their()] facial expression utterly blank.") diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 6c1cfeb7714..037b9fb7d87 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -16,20 +16,8 @@ emp_act if(check_reflect(def_zone)) // Checks if you've passed a reflection% check visible_message("The [P.name] gets reflected by [src]!", \ "The [P.name] gets reflected by [src]!") - // Find a turf near or on the original location to bounce to - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/turf/curloc = get_turf(src) - - // redirect the projectile - P.firer = src - P.original = locate(new_x, new_y, P.z) - P.starting = curloc - P.current = curloc - P.yo = new_y - curloc.y - P.xo = new_x - curloc.x - P.Angle = null + + P.reflect_back(src) return -1 // complete projectile permutation diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm index 7c92d8748bd..f88670fc0c1 100644 --- a/code/modules/mob/living/carbon/human/species/golem.dm +++ b/code/modules/mob/living/carbon/human/species/golem.dm @@ -474,19 +474,9 @@ if(P.is_reflectable) H.visible_message("The [P.name] gets reflected by [H]'s glass skin!", \ "The [P.name] gets reflected by [H]'s glass skin!") - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/turf/curloc = get_turf(H) + + P.reflect_back(H) - // redirect the projectile - P.firer = src - P.original = locate(new_x, new_y, P.z) - P.starting = curloc - P.current = curloc - P.yo = new_y - curloc.y - P.xo = new_x - curloc.x - P.Angle = null return FALSE return TRUE diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm index a0980256718..b357d2c5345 100644 --- a/code/modules/mob/living/carbon/human/species/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/monkey.dm @@ -131,6 +131,13 @@ "appendix" = /obj/item/organ/internal/appendix, "eyes" = /obj/item/organ/internal/eyes/skrell //Tajara monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ.. ) +/datum/species/monkey/skrell/on_species_gain(mob/living/carbon/human/H) + ..() + ADD_TRAIT(H, TRAIT_WATERBREATH, "species") + +/datum/species/monkey/skrell/on_species_loss(mob/living/carbon/human/H) + ..() + REMOVE_TRAIT(H, TRAIT_WATERBREATH, "species") /datum/species/monkey/unathi name = "Stok" diff --git a/code/modules/mob/living/carbon/human/species/skrell.dm b/code/modules/mob/living/carbon/human/species/skrell.dm index 009514f4902..9e21c0bf390 100644 --- a/code/modules/mob/living/carbon/human/species/skrell.dm +++ b/code/modules/mob/living/carbon/human/species/skrell.dm @@ -12,6 +12,7 @@ herbivores on the whole and tend to be co-operative with the other species of the galaxy, although they rarely reveal \ the secrets of their empire to their allies." + species_traits = list(LIPS) clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS bodyflags = HAS_SKIN_COLOR | HAS_BODY_MARKINGS @@ -43,4 +44,12 @@ "is jamming their thumbs into their eye sockets!", "is twisting their own neck!", "makes like a fish and suffocates!", - "is strangling themselves with their own tendrils!") \ No newline at end of file + "is strangling themselves with their own tendrils!") + +/datum/species/skrell/on_species_gain(mob/living/carbon/human/H) + ..() + ADD_TRAIT(H, TRAIT_WATERBREATH, "species") + +/datum/species/skrell/on_species_loss(mob/living/carbon/human/H) + ..() + REMOVE_TRAIT(H, TRAIT_WATERBREATH, "species") \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/slime.dm b/code/modules/mob/living/carbon/human/species/slime.dm index 42a566e450c..e7501486b72 100644 --- a/code/modules/mob/living/carbon/human/species/slime.dm +++ b/code/modules/mob/living/carbon/human/species/slime.dm @@ -72,6 +72,7 @@ grow.Grant(H) recolor = new() recolor.Grant(H) + ADD_TRAIT(H, TRAIT_WATERBREATH, "species") /datum/species/slime/on_species_loss(mob/living/carbon/human/H) ..() @@ -79,6 +80,7 @@ grow.Remove(H) if(recolor) recolor.Remove(H) + REMOVE_TRAIT(H, TRAIT_WATERBREATH, "species") /datum/species/slime/handle_life(mob/living/carbon/human/H) // Slowly shifting to the color of the reagents diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 5352ba525f1..6898b75b485 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -13,13 +13,13 @@ for(var/obj/item/organ/internal/O in internal_organs) O.on_life() - handle_changeling() handle_wetness(times_fired) // Increase germ_level regularly if(germ_level < GERM_LEVEL_AMBIENT && prob(30)) //if you're just standing there, you shouldn't get more germs beyond an ambient level germ_level++ + SEND_SIGNAL(src, COMSIG_CARBON_LIFE, seconds, times_fired) /////////////// // BREATHING // diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index 36f248cd2c2..b4db13f5452 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -129,7 +129,8 @@ var/const/VOX_PATH = "sound/vox_fem/" announcing_vox = world.time + VOX_DELAY - log_game("[key_name_admin(src)] made a vocal announcement with the following message: [message].") + log_game("[key_name(src)] made a vocal announcement: [message].") + message_admins("[key_name_admin(src)] made a vocal announcement: [message].") for(var/word in words) play_vox_word(word, src.z, null) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 0c003b9e3b8..9dce0cecb62 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -47,6 +47,10 @@ if(SSticker.cultdat?.theme == "blood") updateglow() +/mob/living/simple_animal/hostile/construct/death(gibbed) + . = ..() + SSticker.mode.remove_cultist(src.mind, FALSE) + /mob/living/simple_animal/hostile/construct/examine(mob/user) . = ..() @@ -132,19 +136,7 @@ visible_message("The [P.name] gets reflected by [src]'s shell!", \ "The [P.name] gets reflected by [src]'s shell!") - // Find a turf near or on the original location to bounce to - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3) - var/new_y = P.starting.y + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3) - var/turf/curloc = get_turf(src) - - // redirect the projectile - P.original = locate(new_x, new_y, P.z) - P.starting = curloc - P.current = curloc - P.firer = src - P.yo = new_y - curloc.y - P.xo = new_x - curloc.x + P.reflect_back(src, list(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)) return -1 // complete projectile permutation diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm index e48d980c2a4..ece990c7743 100644 --- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm +++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm @@ -19,7 +19,7 @@ attack_sound = 'sound/creatures/headcrab_attack.ogg' speak_emote = list("hisses") var/is_zombie = 0 - stat_attack = DEAD //so they continue to attack when they are on the ground. + stat_attack = DEAD // Necessary for them to attack (zombify) dead humans robust_searching = 1 var/host_species = "" var/list/human_overlays = list() @@ -37,7 +37,7 @@ visible_message("[src] consumes [target] whole!") if(health < maxHealth) health += 10 - qdel(K) + qdel(K) break cycles = 0 cycles++ @@ -71,6 +71,7 @@ melee_damage_lower = 10 melee_damage_upper = 15 ranged = 0 + stat_attack = CONSCIOUS // Disables their targeting of dead mobs once they're already a zombie icon = H.icon speak = list('sound/creatures/zombie_idle1.ogg','sound/creatures/zombie_idle2.ogg','sound/creatures/zombie_idle3.ogg') speak_chance = 50 @@ -118,7 +119,13 @@ I = image('icons/mob/headcrab.dmi', icon_state = "headcrabpod_gray") overlays += I - +/mob/living/simple_animal/hostile/headcrab/CanAttack(atom/the_target) + if(stat_attack == DEAD && isliving(the_target) && !ishuman(the_target)) + var/mob/living/L = the_target + if(L.stat == DEAD) + // Override default behavior of stat_attack, to stop headcrabs targeting dead mobs they cannot infect, such as silicons. + return FALSE + return ..() /mob/living/simple_animal/hostile/headcrab/fast name = "fast headcrab" diff --git a/code/modules/mob/living/simple_animal/hostile/hellhound.dm b/code/modules/mob/living/simple_animal/hostile/hellhound.dm index 201c4c07992..9107aa03457 100644 --- a/code/modules/mob/living/simple_animal/hostile/hellhound.dm +++ b/code/modules/mob/living/simple_animal/hostile/hellhound.dm @@ -1,6 +1,6 @@ // Hellhound /mob/living/simple_animal/hostile/hellhound - // Sprites by FoS: http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 + // Sprites by FoS: https://www.paradisestation.org/forum/profile/335-fos name = "Lesser Hellhound" desc = "A demonic-looking black canine monster with glowing red eyes and sharp teeth. A firey, lava-like substance drips from it." icon_state = "hellhound" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm index c9dc370648a..eae926b88e1 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/black.dm @@ -6,7 +6,7 @@ // -------------: AI: attacks to inject its venom, then retreats. Will inject its enemies multiple times then hang back to ensure they die. // -------------: SPECIAL: venom that does more damage the more of it is in you // -------------: TO FIGHT IT: if bitten once, retreat, get charcoal/etc treatment, and come back with a gun. -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/black name = "Black Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm index 1c6fcdb6e5d..fd30532a7bc 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm @@ -5,7 +5,7 @@ // -------------: AI: none - this is strictly adminspawn-only and intended for RP events, coder testing, and teaching people 'how to queen' // -------------: SPECIAL: Lay Eggs ability that allows laying queen-level eggs. // -------------: TO FIGHT IT: run away screaming? -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/queen/empress name = "Empress of Terror" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm index 14aa2b9299a..c06a7c2fee6 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/gray.dm @@ -6,7 +6,7 @@ // -------------: AI: hides in vents, emerges when prey is near to kill it, then hides again. Intended to scare normal crew. // -------------: SPECIAL: invisible when on top of a vent, emerges when prey approaches or gets trapped in webs. // -------------: TO FIGHT IT: shoot it through a window, or make it regret ambushing you -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/gray name = "Gray Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/green.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/green.dm index 43d21286f8f..e7daced65ff 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/green.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/green.dm @@ -6,7 +6,7 @@ // -------------: AI: after it kills you, it webs you and lays new terror eggs on your body // -------------: SPECIAL: can also create webs, web normal objects, etc // -------------: TO FIGHT IT: kill it however you like - just don't die to it! -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/green name = "Green Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/mother.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/mother.dm index d1e171d2f55..65a3ff3db47 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/mother.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/mother.dm @@ -6,7 +6,7 @@ // -------------: AI: no special ai // -------------: SPECIAL: spawns an ungodly number of spiderlings when killed // -------------: TO FIGHT IT: don't! Just leave it alone! It is harmless by itself... but god help you if you aggro it. -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/mother name = "Mother of Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm index 646e9e50660..e486872abbb 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/prince.dm @@ -6,7 +6,7 @@ // -------------: AI: no special ai // -------------: SPECIAL: massive health // -------------: TO FIGHT IT: a squad of at least 4 people with laser rifles. -// -------------: SPRITES FROM: Travelling Merchant, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=2766 +// -------------: SPRITES FROM: Travelling Merchant, https://www.paradisestation.org/forum/profile/2715-travelling-merchant/ /mob/living/simple_animal/hostile/poison/terror_spider/prince name = "Prince of Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm index 419f2a617f6..828e0e5f8f6 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm @@ -6,7 +6,7 @@ // -------------: AI: as green, but will evolve to queen when it can // -------------: SPECIAL: can evolve into a queen, if fed enough // -------------: TO FIGHT IT: kill it before it evolves -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/princess name = "Princess of Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/purple.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/purple.dm index 62832527293..92c7688e1e1 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/purple.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/purple.dm @@ -6,7 +6,7 @@ // -------------: AI: dies if too far from queen // -------------: SPECIAL: chance to stun on hit // -------------: TO FIGHT IT: shoot it from range, bring friends! -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/purple name = "Purple Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm index 3f16eb44837..a96486e473e 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm @@ -7,7 +7,7 @@ // -------------: AI: uses very powerful fangs to wreck people in melee // -------------: SPECIAL: the more you hurt it, the harder it bites you // -------------: TO FIGHT IT: shoot it from range. Kite it. -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/red name = "Red Terror spider" diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/white.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/white.dm index 8b5010c9d25..f62167792a3 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/white.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/white.dm @@ -5,7 +5,7 @@ // -------------: AI: injects a venom that makes you grow spiders in your body, then retreats // -------------: SPECIAL: stuns you on first attack - vulnerable to groups while it does this // -------------: TO FIGHT IT: blast it before it can get away -// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386 +// -------------: SPRITES FROM: FoS, https://www.paradisestation.org/forum/profile/335-fos /mob/living/simple_animal/hostile/poison/terror_spider/white name = "White Terror spider" diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index 3f7b76c5af0..948c16314c9 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -28,6 +28,9 @@ del_on_death = 1 deathmessage = "lets out a contented sigh as their form unwinds." +/mob/living/simple_animal/shade/death(gibbed) + . = ..() + SSticker.mode.remove_cultist(src.mind, FALSE) /mob/living/simple_animal/shade/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri if(istype(O, /obj/item/soulstone)) diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 0e1a19da662..72f136304d7 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -344,6 +344,8 @@ return SetSleeping(max(sleeping, amount), updating, no_alert) /mob/living/SetSleeping(amount, updating = 1, no_alert = FALSE) + if(frozen) // If the mob has been admin frozen, sleeping should not be changeable + return . = STATUS_UPDATE_STAT if((!!amount) == (!!sleeping)) // We're not changing from + to 0 or vice versa updating = FALSE diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 8847b6fdeed..4d7dafa69bf 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -30,6 +30,11 @@ #define APC_UPDATE_ICON_COOLDOWN 200 // 20 seconds +// APC malf status +#define APC_MALF_NOT_HACKED 1 +#define APC_MALF_HACKED 2 // APC hacked by user, and user is in its core. +#define APC_MALF_SHUNTED_HERE 3 // User is shunted in this APC +#define APC_MALF_SHUNTED_OTHER 4 // User is shunted in another APC // the Area Power Controller (APC), formerly Power Distribution Unit (PDU) // one per area, needs wire conection to power network through a terminal @@ -749,18 +754,22 @@ /obj/machinery/power/apc/proc/get_malf_status(mob/living/silicon/ai/malf) - if(istype(malf) && malf.mind.has_antag_datum(/datum/antagonist/traitor) || malf.malf_picker) // If they're a traitor OR they have the malf picker from the combat module - if(malfai == (malf.parent || malf)) - if(occupier == malf) - return 3 // 3 = User is shunted in this APC - else if(istype(malf.loc, /obj/machinery/power/apc)) - return 4 // 4 = User is shunted in another APC - else - return 2 // 2 = APC hacked by user, and user is in its core. + if(!istype(malf)) + return FALSE + + // Only if they're a traitor OR they have the malf picker from the combat module + if(!malf.mind.has_antag_datum(/datum/antagonist/traitor) && !malf.malf_picker) + return FALSE + + if(malfai == (malf.parent || malf)) + if(occupier == malf) + return APC_MALF_SHUNTED_HERE + else if(istype(malf.loc, /obj/machinery/power/apc)) + return APC_MALF_SHUNTED_OTHER else - return 1 // 1 = APC not hacked. + return APC_MALF_HACKED else - return 0 // 0 = User is not a Malf AI + return APC_MALF_NOT_HACKED /obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) if(!user) @@ -1008,7 +1017,7 @@ /obj/machinery/power/apc/proc/malfhack(mob/living/silicon/ai/malf) if(!istype(malf)) return - if(get_malf_status(malf) != 1) + if(get_malf_status(malf) != APC_MALF_NOT_HACKED) return if(malf.malfhacking) to_chat(malf, "You are already hacking an APC.") diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 8977062c947..82d78e99e53 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -254,6 +254,7 @@ shot_number = 0 P.setDir(dir) P.starting = loc + P.Angle = null P.fire() return P diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index dc798e10830..d31231823f8 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -24,7 +24,7 @@ var/p_x = 16 var/p_y = 16 // the pixel location of the tile that the player clicked. Default is the center var/speed = 1 //Amount of deciseconds it takes for projectile to travel - var/Angle = 0 + var/Angle = null var/spread = 0 //amount (in degrees) of projectile spread var/legacy = FALSE //legacy projectile system animate_movement = 0 @@ -240,8 +240,7 @@ if(!paused) if((!( current ) || loc == current)) current = locate(Clamp(x+xo,1,world.maxx),Clamp(y+yo,1,world.maxy),z) - - if(!Angle) + if(isnull(Angle)) Angle=round(Get_Angle(src,current)) if(spread) Angle += (rand() - 0.5) * spread @@ -302,6 +301,25 @@ Range() sleep(1) +obj/item/projectile/proc/reflect_back(atom/source, list/position_modifiers = list(0, 0, 0, 0, 0, -1, 1, -2, 2)) + if(starting) + var/new_x = starting.x + pick(position_modifiers) + var/new_y = starting.y + pick(position_modifiers) + var/turf/curloc = get_turf(source) + + if(ismob(source)) + firer = source // The reflecting mob will be the new firer + else + firer = null // Reflected by something other than a mob so firer will be null + + // redirect the projectile + original = locate(new_x, new_y, z) + starting = curloc + current = curloc + yo = new_y - curloc.y + xo = new_x - curloc.x + Angle = null // Will be calculated in fire() + obj/item/projectile/Crossed(atom/movable/AM, oldloc) //A mob moving on a tile with a projectile is hit by it. ..() if(isliving(AM) && AM.density && !checkpass(PASSMOB)) diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm index 41a0a747118..9601746443a 100644 --- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm +++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm @@ -134,76 +134,88 @@ icon_state = "juicer0" /obj/machinery/reagentgrinder/attackby(obj/item/I, mob/user, params) - if(default_unfasten_wrench(user, I)) - return + if(default_unfasten_wrench(user, I)) + return - if(exchange_parts(user, I)) - return + if(exchange_parts(user, I)) + return - if(anchored && !beaker) - if(default_deconstruction_screwdriver(user, "juicer_open", "juicer0", I)) - return + if(anchored && !beaker) + if(default_deconstruction_screwdriver(user, "juicer_open", "juicer0", I)) + return - if(panel_open && istype(I, /obj/item/crowbar)) - default_deconstruction_crowbar(I) - return + if(panel_open && istype(I, /obj/item/crowbar)) + default_deconstruction_crowbar(I) + return - if (istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER) ) - if(beaker) - to_chat(user, "There's already a container inside.") - else if(panel_open) - to_chat(user, "Close the maintenance panel first.") - else - if(!user.drop_item()) - return 1 - beaker = I - beaker.loc = src - update_icon() - src.updateUsrDialog() - return 1 //no afterattack + if(istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER) ) + if(beaker) + to_chat(user, "There's already a container inside.") + else if(panel_open) + to_chat(user, "Close the maintenance panel first.") + else + if(!user.drop_item()) + return FALSE + beaker = I + beaker.loc = src + update_icon() + updateUsrDialog() + return TRUE //no afterattack - if(is_type_in_list(I, dried_items)) - if(istype(I, /obj/item/reagent_containers/food/snacks/grown)) - var/obj/item/reagent_containers/food/snacks/grown/G = I - if(!G.dry) - to_chat(user, "You must dry that first!") - return 1 + if(is_type_in_list(I, dried_items)) + if(istype(I, /obj/item/reagent_containers/food/snacks/grown)) + var/obj/item/reagent_containers/food/snacks/grown/G = I + if(!G.dry) + to_chat(user, "You must dry that first!") + return FALSE - if(holdingitems && holdingitems.len >= limit) - to_chat(usr, "The machine cannot hold anymore items.") - return 1 + if(holdingitems && holdingitems.len >= limit) + to_chat(usr, "The machine cannot hold anymore items.") + return FALSE - //Fill machine with a bag! - if(istype(I, /obj/item/storage/bag)) - var/obj/item/storage/bag/B = I - for (var/obj/item/reagent_containers/food/snacks/grown/G in B.contents) - B.remove_from_storage(G, src) - holdingitems += G - if(holdingitems && holdingitems.len >= limit) //Sanity checking so the blender doesn't overfill - to_chat(user, "You fill the All-In-One grinder to the brim.") - break + //Fill machine with a bag! + if(istype(I, /obj/item/storage/bag)) + var/obj/item/storage/bag/B = I + if(!B.contents.len) + to_chat(user, "[B] is empty.") + return FALSE - if(!I.contents.len) - to_chat(user, "You empty the plant bag into the All-In-One grinder.") + var/original_contents_len = B.contents.len - src.updateUsrDialog() - return 1 + for(var/obj/item/G in B.contents) + if(is_type_in_list(G, blend_items) || is_type_in_list(G, juice_items)) + B.remove_from_storage(G, src) + holdingitems += G + if(holdingitems && holdingitems.len >= limit) //Sanity checking so the blender doesn't overfill + to_chat(user, "You fill the All-In-One grinder to the brim.") + break - if (!is_type_in_list(I, blend_items) && !is_type_in_list(I, juice_items)) - if(user.a_intent == INTENT_HARM) - return ..() - else - to_chat(user, "Cannot refine into a reagent!") - return 1 + if(B.contents.len == original_contents_len) + to_chat(user, "Nothing in [B] can be put into the All-In-One grinder.") + return FALSE + else if(!B.contents.len) + to_chat(user, "You empty all of [B]'s contents into the All-In-One grinder.") + else + to_chat(user, "You empty some of [B]'s contents into the All-In-One grinder.") - if(user.drop_item()) - I.loc = src - holdingitems += I - src.updateUsrDialog() - return 0 + updateUsrDialog() + return TRUE + + if(!is_type_in_list(I, blend_items) && !is_type_in_list(I, juice_items)) + if(user.a_intent == INTENT_HARM) + return ..() + else + to_chat(user, "Cannot refine into a reagent!") + return TRUE + + if(user.drop_item()) + I.loc = src + holdingitems += I + src.updateUsrDialog() + return FALSE /obj/machinery/reagentgrinder/attack_ai(mob/user) - return 0 + return FALSE /obj/machinery/reagentgrinder/attack_hand(mob/user) user.set_machine(src) @@ -301,8 +313,8 @@ /obj/machinery/reagentgrinder/proc/is_allowed(obj/item/reagent_containers/O) for (var/i in blend_items) if(istype(O, i)) - return 1 - return 0 + return TRUE + return FALSE /obj/machinery/reagentgrinder/proc/get_allowed_by_id(obj/item/O) for (var/i in blend_items) diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 482b8b20ccd..a4320639f39 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -43,21 +43,22 @@ to_chat(user, "[src] is empty!") return + var/contents_log = reagents.reagent_list.Join(", ") spray(A) playsound(loc, 'sound/effects/spray2.ogg', 50, 1, -6) user.changeNext_move(CLICK_CD_RANGE*2) user.newtonian_move(get_dir(A, user)) - if(reagents.has_reagent("sacid")) - msg_admin_attack("[key_name_admin(user)] fired sulphuric acid from \a [src] at [COORD(user)].", ATKLOG_FEW) - log_game("[key_name(user)] fired sulphuric acid from \a [src] at [COORD(user)].") - if(reagents.has_reagent("facid")) - msg_admin_attack("[key_name_admin(user)] fired fluorosulfuric acid from \a [src] at [COORD(user)].", ATKLOG_FEW) - log_game("[key_name(user)] fired fluorosulfuric Acid from \a [src] at [COORD(user)].") - if(reagents.has_reagent("lube")) - msg_admin_attack("[key_name_admin(user)] fired space lube from \a [src] at [COORD(user)].") - log_game("[key_name(user)] fired space lube from \a [src] at [COORD(user)].") + if(reagents.reagent_list.len == 1 && reagents.has_reagent("cleaner")) // Only show space cleaner logs if it's burning people from being too hot or cold + if(reagents.chem_temp < 300 && reagents.chem_temp > 280) // 280 is the cold threshold for slimes, 300 the hot threshold for drask + return + + var/attack_log_type = ATKLOG_MOST + if(reagents.has_reagent("sacid") || reagents.has_reagent("facid") || reagents.has_reagent("lube")) + attack_log_type = ATKLOG_FEW + msg_admin_attack("[key_name_admin(user)] used a spray bottle at [COORD(user)] - Contents: [contents_log] - Temperature: [reagents.chem_temp]K", attack_log_type) + log_game("[key_name(user)] used a spray bottle at [COORD(user)] - Contents: [contents_log] - Temperature: [reagents.chem_temp]K") return diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 953c0e6682c..5af2d472416 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -174,43 +174,37 @@ /obj/docking_port/mobile/emergency/proc/is_hijacked() for(var/mob/living/player in GLOB.player_list) - if(player.mind) - if(player.stat != DEAD || !iszombie(player)) - if(issilicon(player)) //Borgs are technically dead anyways + if(!player.mind) + continue + if(player.stat == DEAD) // Corpses + continue + if(iszombie(player)) // Walking corpses + continue + if(issilicon(player)) //Borgs are technically dead anyways + continue + if(isanimal(player)) //Poly does not own the shuttle + continue + if(ishuman(player)) //hostages allowed on the shuttle, check for restraints + var/mob/living/carbon/human/H = player + if(!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD) //new crit users who are in hard crit are considered dead + continue + if(H.handcuffed) //cuffs + continue + if(H.wear_suit && H.wear_suit.breakouttime) //straight jacket + continue + if(istype(H.loc, /obj/structure/closet)) //locked/welded locker, all aboard the clown train honk honk + var/obj/structure/closet/C = H.loc + if(C.welded || C.locked) continue - if(isanimal(player)) //Poly does not own the shuttle - continue - if(ishuman(player)) //hostages allowed on the shuttle, check for restraints - var/mob/living/carbon/human/H = player - if(!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD) //new crit users who are in hard crit are considered dead - continue - if(H.handcuffed) //cuffs - continue - if(H.wear_suit && H.wear_suit.breakouttime) //straight jacket - continue - if(istype(H.loc, /obj/structure/closet)) //locked/welded locker, all aboard the clown train honk honk - var/obj/structure/closet/C = H.loc - if(C.welded || C.locked) - continue - var/special_role = player.mind.special_role - if(special_role) - if(special_role == SPECIAL_ROLE_TRAITOR) // traitors can hijack the shuttle - continue + var/special_role = player.mind.special_role + if(special_role) + // There's a long list of special roles, but almost all of them are antags anyway. + // If you manage to escape with a pet slaughter demon - go for it! Greentext well earned! + if(special_role != SPECIAL_ROLE_EVENTMISC && special_role != SPECIAL_ROLE_ERT && special_role != SPECIAL_ROLE_DEATHSQUAD) + continue - if(special_role == SPECIAL_ROLE_CHANGELING) // changelings as well - continue - - if(special_role == SPECIAL_ROLE_VAMPIRE || special_role == SPECIAL_ROLE_VAMPIRE_THRALL) // for traitorvamp - continue - - if(special_role == SPECIAL_ROLE_NUKEOPS) // so can nukeops, for the hell of it - continue - - if(special_role == SPECIAL_ROLE_SYNDICATE_DEATHSQUAD) // and the syndie deathsquad i guess - continue - - if(get_area(player) == areaInstance) - return FALSE + if(get_area(player) == areaInstance) + return FALSE return TRUE diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index c66d95df899..54a9c4c88be 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -83,7 +83,7 @@ /datum/surgery_step/generic/clamp_bleeders/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) var/obj/item/organ/external/affected = target.get_organ(target_zone) - user.visible_message(" [user]'s hand slips, tearing blood vessals and causing massive bleeding in [target]'s [affected.name] with \the [tool]!", \ + user.visible_message(" [user]'s hand slips, tearing blood vessels and causing massive bleeding in [target]'s [affected.name] with \the [tool]!", \ " Your hand slips, tearing blood vessels and causing massive bleeding in [target]'s [affected.name] with \the [tool]!",) affected.receive_damage(10) return 0 diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm index 2c891632770..1fde13e246e 100644 --- a/code/modules/surgery/organs/organ_external.dm +++ b/code/modules/surgery/organs/organ_external.dm @@ -47,7 +47,7 @@ var/damage_msg = "You feel an intense pain" var/broken_description - var/open = 0 + var/open = 0 // If the body part has an open incision from surgery var/sabotaged = 0 //If a prosthetic limb is emagged, it will detonate when it fails. var/encased // Needs to be opened with a saw to access the organs. diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 98ed11672fb..25f87d71104 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -283,7 +283,7 @@ /obj/item/organ/internal/honktumor/cursed/on_life() //No matter what you do, no matter who you are, no matter where you go, you're always going to be a fat, stuttering dimwit. ..() - owner.setBrainLoss(80) + owner.setBrainLoss(80, use_brain_mod = FALSE) owner.set_nutrition(9000) owner.overeatduration = 9000 diff --git a/config/example/motd.txt b/config/example/motd.txt index 106be771704..f39e579a6f7 100644 --- a/config/example/motd.txt +++ b/config/example/motd.txt @@ -1,5 +1,5 @@

Welcome to Space Station 13!

--This server is running Paradise's modification of the Baystation 12 and /tg/station13 SS13 code. +-This server is running Paradise's modification of the Baystation 12 and /tg/station13 SS13 code.

GitHub: https://github.com/ParadiseSS13/Paradise diff --git a/config/example/rules.html b/config/example/rules.html index c7a717aca63..ef37effcea4 100644 --- a/config/example/rules.html +++ b/config/example/rules.html @@ -4,7 +4,7 @@ diff --git a/goon/browserassets/js/browserOutput.js b/goon/browserassets/js/browserOutput.js index 094e8258562..317fc02b9cb 100644 --- a/goon/browserassets/js/browserOutput.js +++ b/goon/browserassets/js/browserOutput.js @@ -1005,7 +1005,7 @@ $(function() { '
' + '
Choose up to '+opts.highlightLimit+' strings that will highlight the line when they appear in chat.
'+ 'Enable Regex'+ - '
See here for details
' + + '
See here for details
' + '
' + termInputs + '
Paradise Station
-

Forum | Wiki | Source

- Visit our Discord channel:-Click Here- +

Forum | Wiki | Source

diff --git a/html/templates/header.html b/html/templates/header.html index fac4d7b280a..5d499bbc347 100644 --- a/html/templates/header.html +++ b/html/templates/header.html @@ -25,7 +25,7 @@
Paradise Station
-

Forum | Wiki | Source

+

Forum | Wiki | Source

Visit our Discord channel:-Click Here- diff --git a/icons/obj/toy.dmi b/icons/obj/toy.dmi index 17ebf4c9219..511b578ad4a 100644 Binary files a/icons/obj/toy.dmi and b/icons/obj/toy.dmi differ