From 538f35c22900834d994620a212f79c50d5dd2cbe Mon Sep 17 00:00:00 2001
From: ExcessiveUseOfCobblestone According to \the [src], you are now in \"[html_encode(A.name)]\". You may make an amendment to the drawing. According to \the [src], you are now in \"[html_encode(A.name)]\". You may make an amendment to the drawing.
"
text += "Teleport
This rune is unique in that it requires a keyword before the scribing can begin. When invoked, it will find any other Teleport runes; \
- If any are found, the user can choose which rune to send to. Upon activation, the rune teleports everything above it to the selected rune.
"
+ If any are found, the user can choose which rune to send to. Upon activation, the rune teleports everything above it to the selected rune, provided the selected rune is unblocked.
"
- text += "Convert
This rune is critical to the success of the cult. It will allow you to convert normal crew members into cultists. \
- To do this, simply place the crew member upon the rune and invoke it. This rune requires two invokers to use. If the target to be converted is mindshield-implanted or a certain assignment, they will \
- be unable to be converted. People the Geometer wishes sacrificed will also be ineligible for conversion, and anyone with a shielding presence like the null rod will not be converted.
\
- Successful conversions will produce a tome for the new cultist.
"
+ text += "Offer
This rune is necessary to achieve your goals. Placing a noncultist above it will convert them if it can and sacrifice them otherwise. \
+ It requires two invokers to convert a target and three to sacrifice a living target or the sacrifice target.
\
+ Successful conversions will produce a tome for the new cultist, in addition to healing them.
\
+ Successful sacrifices will please the Geometer, can complete your objective if it sacrificed the sacrifice target, and will attempt to place the target into a soulstone.
"
- text += "Sacrifice
This rune is necessary to achieve your goals. Simply place any dead creature upon the rune and invoke it (this will not \
- target cultists!). If this creature has a mind, a soulstone will be created and the creature's soul transported to it. Sacrificing the dead can be done alone, but sacrificing living crew or your cult's target will require 3 cultists. \
- Soulstones used on construct shells will move that soul into a powerful construct of your choice.
"
-
- text += "Raise Dead
This rune requires two corpses. To perform the ritual, place the corpse you wish to revive onto \
- the rune and the offering body adjacent to it. When the rune is invoked, the body to be sacrificed will turn to dust, the life force flowing into the revival target. Assuming the target is not moved \
- within a few seconds, they will be brought back to life, healed of all ailments.
"
+ text += "Raise Dead
This rune requires the corpse of a cultist placed upon the rune, and one person sacrificed for each revival you wish to do.\
+ Provided there are remaining revivals from those sacrificed, invoking the rune will revive the cultist placed upon it.
"
text += "Electromagnetic Disruption
Robotic lifeforms have time and time again been the downfall of fledgling cults. This rune may allow you to gain the upper \
hand against these pests. By using the rune, a large electromagnetic pulse will be emitted from the rune's location. The size of the EMP will grow significantly for each additional adjacent cultist when the \
@@ -91,14 +86,14 @@ This file contains the arcane tome files.
The body will also take constant damage while in this form, and may even die. The user's spirit will contain their consciousness, and will allow them to freely wander the station as a ghost. This may \
also be used to commune with the dead.
"
- text += "Form Barrier
While simple, this rune serves an important purpose in defense and hindering passage. When invoked, the \
- rune will draw a small amount of life force from the user and make the space above the rune completely dense, rendering it impassable to all but the most complex means. The rune may be invoked again to \
- undo this effect and allow passage again.
"
+ text += "Form Barrier
While simple, this rune serves an important purpose in defense and hindering passage. When invoked, the rune will draw a small amount of blood from the user \
+ and make the space above the rune completely dense, rendering it impassable for about a minute and a half. This effect will spread to other nearby Barrier Runes. \
+ The rune may be invoked again to undo this effect and allow passage again.
"
text += "Summon Cultist
This rune allows the cult to free other cultists with ease. When invoked, it will allow the user to summon a single cultist to the rune from \
any location. It requires two invokers, and will damage each invoker slightly.
"
- text += "Blood Boil
When invoked, this rune will do a massive amount of damage to all non-cultist viewers, but it will also emit a small explosion upon invocation. \
+ text += "Blood Boil
When invoked, this rune will rapidly do a massive amount of damage to all non-cultist viewers, but it will also emit a burst of flame once it finishes. \
It requires three invokers.
"
text += "Drain Life
This rune will drain the life of every living creature above the rune, healing the invoker for each creature drained by it.
"
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 0b69fc9baba..d42b1bdeaff 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -1,4 +1,4 @@
-/var/list/sacrificed = list()
+/var/list/sacrificed = list() //a mixed list of minds and mobs
var/list/non_revealed_runes = (subtypesof(/obj/effect/rune) - /obj/effect/rune/malformed)
/*
@@ -23,10 +23,11 @@ To draw a rune, use an arcane tome.
icon_state = "1"
unacidable = 1
layer = ABOVE_NORMAL_TURF_LAYER
- color = rgb(255,0,0)
+ color = "#FF0000"
var/invocation = "Aiy ele-mayo!" //This is said by cultists when the rune is invoked.
var/req_cultists = 1 //The amount of cultists required around the rune to invoke it. If only 1, any cultist can invoke it.
+ var/req_cultists_text //if we have a description override for required cultists to invoke
var/rune_in_use = 0 // Used for some runes, this is for when you want a rune to not be usable when in use.
var/scribe_delay = 50 //how long the rune takes to create
@@ -48,7 +49,7 @@ To draw a rune, use an arcane tome.
if(iscultist(user) || user.stat == DEAD) //If they're a cultist or a ghost, tell them the effects
user << "Name: [cultist_name]"
user << "Effects: [capitalize(cultist_desc)]"
- user << "Required Acolytes: [req_cultists]"
+ user << "Required Acolytes: [req_cultists_text ? "[req_cultists_text]":"[req_cultists]"]"
if(req_keyword && keyword)
user << "Keyword: [keyword]"
@@ -137,6 +138,9 @@ structure_check() searches for nearby cultist structures required for the invoca
for(var/M in invokers)
var/mob/living/L = M
L.say(invocation)
+ do_invoke_glow()
+
+/obj/effect/rune/proc/do_invoke_glow()
var/oldtransform = transform
spawn(0) //animate is a delay, we want to avoid being delayed
animate(src, transform = matrix()*2, alpha = 0, time = 5) //fade out
@@ -187,7 +191,7 @@ structure_check() searches for nearby cultist structures required for the invoca
cultist_desc = "transforms paper into powerful magic talismans."
invocation = "H'drak v'loso, mir'kanas verbot!"
icon_state = "3"
- color = rgb(0, 0, 255)
+ color = "#0000FF"
/obj/effect/rune/imbue/invoke(var/list/invokers)
var/mob/living/user = invokers[1] //the first invoker is always the user
@@ -296,6 +300,11 @@ var/list/teleport_runes = list()
return
var/turf/T = get_turf(src)
+ var/turf/target = get_turf(actual_selected_rune)
+ if(is_blocked_turf(target))
+ user << "The target rune is blocked. Attempting to teleport to it would be massively unwise."
+ fail_invoke()
+ return
var/movedsomething = 0
var/moveuserlater = 0
for(var/atom/movable/A in T)
@@ -305,158 +314,134 @@ var/list/teleport_runes = list()
continue
if(!A.anchored)
movedsomething = 1
- A.forceMove(get_turf(actual_selected_rune))
+ A.forceMove(target)
if(movedsomething)
..()
visible_message("There is a sharp crack of inrushing air, and everything above the rune disappears!")
user << "You[moveuserlater ? "r vision blurs, and you suddenly appear somewhere else":" send everything above the rune away"]."
if(moveuserlater)
- user.forceMove(get_turf(actual_selected_rune))
+ user.forceMove(target)
else
fail_invoke()
-//Rite of Enlightenment: Converts a normal crewmember to the cult.
+//Rite of Offering: Converts or sacrifices a target.
/obj/effect/rune/convert
- cultist_name = "Convert"
- cultist_desc = "converts a normal crewmember on top of it to the cult. Does not work on mindshield-implanted crew."
+ cultist_name = "Offer"
+ cultist_desc = "offers a noncultist above it to Nar-Sie, either converting them or sacrificing them."
+ req_cultists_text = "2 for conversion, 3 for living sacrifices and sacrifice targets."
invocation = "Mah'weyh pleggh at e'ntrath!"
icon_state = "3"
- color = rgb(200, 0, 0)
- req_cultists = 2
+ color = "#FFFFFF"
+ req_cultists = 1
+ allow_excess_invokers = 1
+ rune_in_use = FALSE
+
+/obj/effect/rune/convert/do_invoke_glow()
+ return
/obj/effect/rune/convert/invoke(var/list/invokers)
- var/list/convertees = list()
- var/turf/T = get_turf(src)
- for(var/mob/living/M in T)
- if(M.stat != DEAD && !iscultist(M) && is_convertable_to_cult(M.mind))
- convertees |= M
- else if(is_sacrifice_target(M.mind))
- for(var/C in invokers)
- C << "\"I desire this one for myself. SACRIFICE THEM!\""
- else if(is_servant_of_ratvar(M))
- M.visible_message("[M]'s eyes glow a defiant yellow!", \
- "\"Stop resisting. You will be mi-\" \"Give up and you will feel pain unlike anything you've ever felt!\"")
- M.Weaken(4)
- if(!convertees.len)
- fail_invoke()
- log_game("Convert rune failed - no eligible convertees")
- return
- var/mob/living/new_cultist = pick(convertees)
- if(new_cultist.null_rod_check())
- for(var/M in invokers)
- M << "Something is shielding [new_cultist]'s mind!"
- fail_invoke()
- log_game("Convert rune failed - convertee had null rod")
- return
- ..()
- new_cultist.visible_message("[new_cultist] writhes in pain as the markings below them glow a bloody red!", \
- "AAAAAAAAAAAAAA-")
- ticker.mode.add_cultist(new_cultist.mind, 1)
- new /obj/item/weapon/tome(get_turf(src))
- new_cultist.mind.special_role = "Cultist"
- new_cultist << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
- and something evil takes root."
- new_cultist << "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back.\
- "
-
-//Rite of Tribute: Sacrifices a crew member to Nar-Sie. Places them into a soul shard if they're in their body.
-/obj/effect/rune/sacrifice
- cultist_name = "Sacrifice"
- cultist_desc = "sacrifices a crew member to the Geometer. May place them into a soul shard if their spirit remains in their body."
- icon_state = "3"
- allow_excess_invokers = 1
- invocation = "Barhah hra zar'garis!"
- color = rgb(255, 255, 255)
- rune_in_use = 0
-
-/obj/effect/rune/sacrifice/New()
- ..()
- icon_state = "[rand(1,7)]"
-
-/obj/effect/rune/sacrifice/invoke(var/list/invokers)
if(rune_in_use)
return
- rune_in_use = 1
- var/mob/living/user = invokers[1] //the first invoker is always the user
+ var/list/myriad_targets = list()
var/turf/T = get_turf(src)
- var/list/possible_targets = list()
- for(var/mob/living/M in T.contents)
- if(M.mind)
- if(M.mind in sacrificed)
- continue
+ for(var/mob/living/M in T)
if(!iscultist(M))
- possible_targets.Add(M)
- var/mob/offering
- if(possible_targets.len > 1) //If there's more than one target, allow choice
- offering = input(user, "Choose an offering to sacrifice.", "Unholy Tribute") as null|anything in possible_targets
- if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated())
- return
- else if(possible_targets.len) //Otherwise, if there's a target at all, pick the only one
- offering = possible_targets[possible_targets.len]
- if(!offering)
- rune_in_use = 0
- return
- /*var/obj/item/weapon/nullrod/N = offering.null_rod_check()
- if(N)
- user << "Something is blocking the Geometer's magic!"
- log_game("Sacrifice rune failed - target has \a [N]!")
+ myriad_targets |= M
+ if(!myriad_targets.len)
fail_invoke()
- rune_in_use = 0
- return*/
- if(((ishuman(offering) || isrobot(offering)) && offering.stat != DEAD) || is_sacrifice_target(offering.mind)) //Requires three people to sacrifice living targets
- if(invokers.len < 3)
- for(var/M in invokers)
- M << "[offering] is too greatly linked to the world! You need three acolytes!"
- fail_invoke()
- log_game("Sacrifice rune failed - not enough acolytes and target is living")
- rune_in_use = 0
- return
+ log_game("Offer rune failed - no eligible targets")
+ return
+ rune_in_use = TRUE
visible_message("[src] pulses blood red!")
- color = rgb(126, 23, 23)
- ..()
- sac(invokers, offering)
- color = initial(color)
+ color = "#7D1717"
+ var/mob/living/L = pick(myriad_targets)
+ var/is_clock = is_servant_of_ratvar(L)
+ var/is_convertable = is_convertable_to_cult(L.mind)
+ if(L.stat != DEAD && (is_clock || is_convertable))
+ invocation = "Mah'weyh pleggh at e'ntrath!"
+ ..()
+ if(is_clock)
+ L.visible_message("[L]'s eyes glow a defiant yellow!", \
+ "\"Stop resisting. You will be mi-\"\n\
+ \"Give up and you will feel pain unlike anything you've ever felt!\"")
+ L.Weaken(4)
+ else if(is_convertable)
+ do_convert(L, invokers)
+ else
+ invocation = "Barhah hra zar'garis!"
+ ..()
+ do_sacrifice(L, invokers)
+ animate(src, color = initial(color), time = 5)
+ rune_in_use = FALSE
-/obj/effect/rune/sacrifice/proc/sac(var/list/invokers, mob/living/T)
- var/sacrifice_fulfilled
- if(T)
- if(istype(T, /mob/living/simple_animal/pet/dog))
- for(var/M in invokers)
- var/mob/living/L = M
- L << "\"Even I have standards, such as they are!\""
- if(L.reagents)
- L.reagents.add_reagent("hell_water", 2)
- if(T.mind)
- sacrificed.Add(T.mind)
- if(is_sacrifice_target(T.mind))
- sacrifice_fulfilled = 1
- PoolOrNew(/obj/effect/overlay/temp/cult/sac, src.loc)
+/obj/effect/rune/convert/proc/do_convert(mob/living/convertee, list/invokers)
+ if(invokers.len < 2)
for(var/M in invokers)
- if(sacrifice_fulfilled)
- M << "\"Yes! This is the one I desire! You have done well.\""
- else
- if(ishuman(T) || isrobot(T))
- M << "\"I accept this sacrifice.\""
- else
- M << "\"I accept this meager sacrifice.\""
- if(T.mind)
- var/obj/item/device/soulstone/stone = new /obj/item/device/soulstone(get_turf(src))
- stone.invisibility = INVISIBILITY_MAXIMUM //so it's not picked up during transfer_soul()
- if(!stone.transfer_soul("FORCE", T, usr)) //If it cannot be added
- qdel(stone)
- if(stone)
- stone.invisibility = 0
- if(!T)
- rune_in_use = 0
- return
- if(isrobot(T))
- playsound(T, 'sound/magic/Disable_Tech.ogg', 100, 1)
- T.dust() //To prevent the MMI from remaining
+ M << "You need more invokers to convert [convertee]!"
+ log_game("Offer rune failed - tried conversion with one invoker")
+ return 0
+ if(convertee.null_rod_check())
+ for(var/M in invokers)
+ M << "Something is shielding [convertee]'s mind!"
+ log_game("Offer rune failed - convertee had null rod")
+ return 0
+ var/brutedamage = convertee.getBruteLoss()
+ var/burndamage = convertee.getFireLoss()
+ if(brutedamage || burndamage)
+ convertee.adjustBruteLoss(-(brutedamage * 0.75))
+ convertee.adjustFireLoss(-(burndamage * 0.75))
+ convertee.visible_message("[convertee] writhes in pain \
+ [brutedamage || burndamage ? "even as their wounds heal and close" : "as the markings below them glow a bloody red"]!", \
+ "AAAAAAAAAAAAAA-")
+ ticker.mode.add_cultist(convertee.mind, 1)
+ new /obj/item/weapon/tome(get_turf(src))
+ convertee.mind.special_role = "Cultist"
+ convertee << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
+ and something evil takes root."
+ convertee << "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back.\
+ "
+ return 1
+
+/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers)
+ if((((ishuman(sacrificial) || isrobot(sacrificial)) && sacrificial.stat != DEAD) || is_sacrifice_target(sacrificial.mind)) && invokers.len < 3)
+ for(var/M in invokers)
+ M << "[sacrificial] is too greatly linked to the world! You need three acolytes!"
+ log_game("Offer rune failed - not enough acolytes and target is living or sac target")
+ return FALSE
+ var/sacrifice_fulfilled = FALSE
+
+ if(sacrificial.mind)
+ sacrificed += sacrificial.mind
+ if(is_sacrifice_target(sacrificial.mind))
+ sacrifice_fulfilled = TRUE
+ else
+ sacrificed += sacrificial
+
+ PoolOrNew(/obj/effect/overlay/temp/cult/sac, get_turf(src))
+ for(var/M in invokers)
+ if(sacrifice_fulfilled)
+ M << "\"Yes! This is the one I desire! You have done well.\""
else
- playsound(T, 'sound/magic/Disintegrate.ogg', 100, 1)
- T.gib()
- rune_in_use = 0
+ if(ishuman(sacrificial) || isrobot(sacrificial))
+ M << "\"I accept this sacrifice.\""
+ else
+ M << "\"I accept this meager sacrifice.\""
+
+ var/obj/item/device/soulstone/stone = new /obj/item/device/soulstone(get_turf(src))
+ if(sacrificial.mind)
+ stone.invisibility = INVISIBILITY_MAXIMUM //so it's not picked up during transfer_soul()
+ stone.transfer_soul("FORCE", sacrificial, usr)
+ stone.invisibility = 0
+
+ if(sacrificial)
+ if(isrobot(sacrificial))
+ playsound(sacrificial, 'sound/magic/Disable_Tech.ogg', 100, 1)
+ sacrificial.dust() //To prevent the MMI from remaining
+ else
+ playsound(sacrificial, 'sound/magic/Disintegrate.ogg', 100, 1)
+ sacrificial.gib()
+ return TRUE
//Ritual of Dimensional Rending: Calls forth the avatar of Nar-Sie upon the station.
/obj/effect/rune/narsie
@@ -465,7 +450,7 @@ var/list/teleport_runes = list()
invocation = "TOK-LYR RQA-NAP G'OLT-ULOFT!!"
req_cultists = 9
icon = 'icons/effects/96x96.dmi'
- color = rgb(125,23,23)
+ color = "#7D1717"
icon_state = "rune_large"
pixel_x = -32 //So the big ol' 96x96 sprite shows up right
pixel_y = -32
@@ -501,6 +486,7 @@ var/list/teleport_runes = list()
M << "Nar-Sie does not respond!"
fail_invoke()
log_game("Summon Nar-Sie rune failed - gametype is not cult")
+ return
if(locate(/obj/singularity/narsie) in poi_list)
for(var/M in invokers)
@@ -514,7 +500,7 @@ var/list/teleport_runes = list()
var/turf/T = get_turf(src)
sleep(40)
if(src)
- color = rgb(255, 0, 0)
+ color = "#FF0000"
new /obj/singularity/narsie/large(T) //Causes Nar-Sie to spawn even if the rune has been removed
if(cult_mode)
cult_mode.eldergod = 0
@@ -534,50 +520,47 @@ var/list/teleport_runes = list()
..()
return
-//Rite of Resurrection: Requires two corpses. Revives one and gibs the other.
+//Rite of Resurrection: Requires the corpse of a cultist and that there have been less revives than the number of people sacrificed
/obj/effect/rune/raise_dead
cultist_name = "Raise Dead"
- cultist_desc = "requires two corpses, one on the rune and one adjacent to the rune. The one on the rune is brought to life, the other is turned to ash."
+ cultist_desc = "requires the corpse of a cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be revived."
invocation = null //Depends on the name of the user - see below
icon_state = "1"
- color = rgb(200, 0, 0)
+ color = "#C80000"
+ var/static/revives_used = 0
+
+/obj/effect/rune/raise_dead/examine(mob/user)
+ ..()
+ if(iscultist(user) || user.stat == DEAD)
+ var/revive_number = 0
+ if(sacrificed.len)
+ revive_number = sacrificed.len - revives_used
+ user << "Revives Remaining: [revive_number]"
/obj/effect/rune/raise_dead/invoke(var/list/invokers)
var/turf/T = get_turf(src)
- var/mob/living/mob_to_sacrifice
var/mob/living/mob_to_revive
- var/list/potential_sacrifice_mobs = list()
var/list/potential_revive_mobs = list()
var/mob/living/user = invokers[1]
if(rune_in_use)
return
- for(var/mob/living/M in orange(1,T))
- if(M.stat == DEAD && !iscultist(M))
- potential_sacrifice_mobs |= M
- if(!potential_sacrifice_mobs.len)
- user << "There are no eligible sacrifices nearby!"
- log_game("Raise Dead rune failed - no catalyst corpses")
- fail_invoke()
- return
for(var/mob/living/M in T.contents)
- if(M.stat == DEAD)
+ if(iscultist(M) && M.stat == DEAD)
potential_revive_mobs |= M
if(!potential_revive_mobs.len)
- user << "There is no eligible revival target on the rune!"
+ user << "There are no dead cultists on the rune!"
log_game("Raise Dead rune failed - no corpses to revive")
fail_invoke()
return
- if(potential_sacrifice_mobs.len > 1)
- mob_to_sacrifice = input(user, "Choose a corpse to sacrifice.", "Corpse to Sacrifice") as null|anything in potential_sacrifice_mobs
- else
- mob_to_sacrifice = potential_sacrifice_mobs[1]
- if(!src || qdeleted(src) || rune_in_use || !validness_checks(mob_to_sacrifice, user, TRUE))
+ if(!sacrificed.len || sacrificed.len <= revives_used)
+ user << "You have sacrificed too few people to revive a cultist!"
+ fail_invoke()
return
if(potential_revive_mobs.len > 1)
- mob_to_revive = input(user, "Choose a corpse to revive.", "Corpse to Revive") as null|anything in potential_revive_mobs
+ mob_to_revive = input(user, "Choose a cultist to revive.", "Cultist to Revive") as null|anything in potential_revive_mobs
else
mob_to_revive = potential_revive_mobs[1]
- if(!src || qdeleted(src) || rune_in_use || !validness_checks(mob_to_sacrifice, user, TRUE) || !validness_checks(mob_to_revive, user, FALSE))
+ if(!src || qdeleted(src) || rune_in_use || !validness_checks(mob_to_revive, user))
return
rune_in_use = 1
if(user.name == "Herbert West")
@@ -585,19 +568,7 @@ var/list/teleport_runes = list()
else
user.say("Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!")
..()
- mob_to_sacrifice.visible_message("[mob_to_sacrifice]'s body rises into the air, connected to [mob_to_revive] by a glowing tendril!")
- mob_to_revive.Beam(mob_to_sacrifice,icon_state="sendbeam",time=20)
- sleep(20)
- if(!mob_to_sacrifice || !in_range(mob_to_sacrifice, src))
- rune_in_use = 0
- return
- if(!mob_to_revive || mob_to_revive.stat != DEAD)
- visible_message("The glowing tendril snaps against the rune with a shocking crack.")
- rune_in_use = 0
- fail_invoke()
- return
- mob_to_sacrifice.visible_message("[mob_to_sacrifice] disintegrates into a pile of bones.")
- mob_to_sacrifice.dust()
+ revives_used++
mob_to_revive.revive(1, 1) //This does remove disabilities and such, but the rune might actually see some use because of it!
mob_to_revive.grab_ghost()
mob_to_revive << "\"PASNAR SAVRAE YAM'TOTH. Arise.\""
@@ -605,7 +576,7 @@ var/list/teleport_runes = list()
"You awaken suddenly from the void. You're alive!")
rune_in_use = 0
-/obj/effect/rune/raise_dead/proc/validness_checks(mob/living/target_mob, mob/living/user, saccing)
+/obj/effect/rune/raise_dead/proc/validness_checks(mob/living/target_mob, mob/living/user)
var/turf/T = get_turf(src)
if(!user)
return 0
@@ -614,28 +585,28 @@ var/list/teleport_runes = list()
if(!target_mob)
fail_invoke()
return 0
- if(saccing)
- if(!in_range(target_mob, src))
- user << "The sacrificial target has been moved!"
- fail_invoke()
- log_game("Raise Dead rune failed - catalyst corpse moved")
- return 0
- if(target_mob.stat != DEAD)
- user << "The sacrificial target must be dead!"
- fail_invoke()
- log_game("Raise Dead rune failed - catalyst corpse is not dead")
- return 0
- else if(!(target_mob in T.contents))
- user << "The corpse to revive has been moved!"
+ if(!(target_mob in T.contents))
+ user << "The cultist to revive has been moved!"
fail_invoke()
log_game("Raise Dead rune failed - revival target moved")
return 0
+ var/mob/dead/observer/ghost = target_mob.get_ghost(TRUE)
+ if(!ghost)
+ user << "The corpse to revive has no spirit!"
+ fail_invoke()
+ log_game("Raise Dead rune failed - revival target has no ghost")
+ return 0
+ if(!sacrificed.len || sacrificed.len <= revives_used)
+ user << "You have sacrificed too few people to revive a cultist!"
+ fail_invoke()
+ log_game("Raise Dead rune failed - too few sacrificed")
+ return 0
return 1
/obj/effect/rune/raise_dead/fail_invoke()
..()
for(var/mob/living/M in range(1,src))
- if(M.stat == DEAD)
+ if(iscultist(M) && M.stat == DEAD)
M.visible_message("[M] twitches.")
@@ -646,7 +617,7 @@ var/list/teleport_runes = list()
invocation = "Ta'gh fara'qha fel d'amar det!"
icon_state = "5"
allow_excess_invokers = 1
- color = rgb(77, 148, 255)
+ color = "#4D94FF"
/obj/effect/rune/emp/invoke(var/list/invokers)
var/turf/E = get_turf(src)
@@ -676,7 +647,7 @@ var/list/teleport_runes = list()
cultist_desc = "severs the link between one's spirit and body. This effect is taxing and one's physical body will take damage while this is active."
invocation = "Fwe'sh mah erl nyag r'ya!"
icon_state = "7"
- color = rgb(126, 23, 23)
+ color = "#7D1717"
rune_in_use = 0 //One at a time, please!
construct_invoke = 0
var/mob/living/affecting = null
@@ -704,7 +675,7 @@ var/list/teleport_runes = list()
var/turf/T = get_turf(src)
rune_in_use = 1
affecting = user
- user.color = "#7e1717"
+ user.color = "#7D1717"
user.visible_message("[user] freezes statue-still, glowing an unearthly red.", \
"You see what lies beyond. All is revealed. While this is a wondrous experience, your physical form will waste away in this state. Hurry...")
user.ghostize(1)
@@ -742,13 +713,20 @@ var/list/teleport_runes = list()
rune_in_use = 0
+var/list/wall_runes = list()
//Rite of the Corporeal Shield: When invoked, becomes solid and cannot be passed. Invoke again to undo.
/obj/effect/rune/wall
cultist_name = "Form Barrier"
- cultist_desc = "when invoked, makes an invisible wall to block passage. Can be invoked again to reverse this."
+ cultist_desc = "when invoked, makes a temporary invisible wall to block passage. Can be invoked again to reverse this."
invocation = "Khari'd! Eske'te tannin!"
icon_state = "1"
- color = rgb(255, 0, 0)
+ color = "#C80000"
+ var/density_timer
+ var/recharging = FALSE
+
+/obj/effect/rune/wall/New()
+ ..()
+ wall_runes += src
/obj/effect/rune/wall/examine(mob/user)
..()
@@ -757,6 +735,7 @@ var/list/teleport_runes = list()
/obj/effect/rune/wall/Destroy()
density = 0
+ wall_runes -= src
air_update_turf(1)
return ..()
@@ -767,24 +746,55 @@ var/list/teleport_runes = list()
return density
/obj/effect/rune/wall/invoke(var/list/invokers)
+ if(recharging)
+ return
var/mob/living/user = invokers[1]
..()
density = !density
- air_update_turf(1)
+ update_state()
+ if(density)
+ spread_density()
user.visible_message("[user] [iscarbon(user) ? "places their hands on":"stares intently at"] [src], and [density ? "the air above it begins to shimmer" : "the shimmer above it fades"].", \
- "You channel your life energy into [src], [density ? "preventing" : "allowing"] passage above it.")
+ "You channel your life energy into [src], [density ? "temporarily preventing" : "allowing"] passage above it.")
+ if(iscarbon(user))
+ var/mob/living/carbon/C = user
+ C.apply_damage(2, BRUTE, pick("l_arm", "r_arm"))
+
+/obj/effect/rune/wall/proc/spread_density()
+ for(var/R in wall_runes)
+ var/obj/effect/rune/wall/W = R
+ if(W.z == z && get_dist(src, W) <= 2 && !W.density && !W.recharging)
+ W.density = TRUE
+ W.update_state()
+ W.spread_density()
+ density_timer = addtimer(src, "lose_density", 900)
+
+/obj/effect/rune/wall/proc/lose_density()
+ if(density)
+ recharging = TRUE
+ density = FALSE
+ update_state()
+ color = "#696969"
+ animate(src, color = initial(color), time = 50, easing = EASE_IN)
+ addtimer(src, "recharge", 50)
+
+/obj/effect/rune/wall/proc/recharge()
+ recharging = FALSE
+ color = initial(color)
+
+/obj/effect/rune/wall/proc/update_state()
+ deltimer(density_timer)
+ air_update_turf(1)
if(density)
var/image/I = image(layer = ABOVE_MOB_LAYER, icon = 'icons/effects/effects.dmi', icon_state = "barriershimmer")
I.appearance_flags = RESET_COLOR
I.alpha = 60
I.color = "#701414"
- overlays += I
+ add_overlay(I)
+ color = "#FF0000"
else
- overlays.Cut()
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- C.apply_damage(2, BRUTE, pick("l_arm", "r_arm"))
-
+ cut_overlays()
+ color = "#C80000"
//Rite of Joined Souls: Summons a single cultist.
/obj/effect/rune/summon
@@ -794,7 +804,7 @@ var/list/teleport_runes = list()
req_cultists = 2
allow_excess_invokers = 1
icon_state = "5"
- color = rgb(0, 255, 0)
+ color = "#00FF00"
/obj/effect/rune/summon/invoke(var/list/invokers)
var/mob/living/user = invokers[1]
@@ -836,35 +846,67 @@ var/list/teleport_runes = list()
//Rite of Boiling Blood: Deals extremely high amounts of damage to non-cultists nearby
/obj/effect/rune/blood_boil
cultist_name = "Boil Blood"
- cultist_desc = "boils the blood of non-believers who can see the rune, dealing extreme amounts of damage. Requires 3 invokers."
+ cultist_desc = "boils the blood of non-believers who can see the rune, rapidly dealing extreme amounts of damage. Requires 3 invokers."
invocation = "Dedo ol'btoh!"
icon_state = "4"
- color = rgb(200, 0, 0)
+ color = "#C80000"
req_cultists = 3
construct_invoke = 0
+ var/tick_damage = 25
+ rune_in_use = FALSE
+
+/obj/effect/rune/blood_boil/do_invoke_glow()
+ return
/obj/effect/rune/blood_boil/invoke(var/list/invokers)
+ if(rune_in_use)
+ return
..()
+ rune_in_use = TRUE
var/turf/T = get_turf(src)
- visible_message("[src] briefly bubbles before exploding!")
- for(var/mob/living/carbon/C in viewers(T))
- if(!iscultist(C))
- var/obj/item/weapon/nullrod/N = C.null_rod_check()
- if(N)
- C << "\The [N] suddenly burns hotly before returning to normal!"
- continue
- C << "Your blood boils in your veins!"
- C.take_overall_damage(45,45)
- C.Stun(7)
- if(is_servant_of_ratvar(C))
- C << "You feel unholy darkness dimming the Justiciar's light!"
- C.adjustStaminaLoss(30)
+ visible_message("[src] turns a bright, glowing orange!")
+ SetLuminosity(6)
+ color = "#FC9B54"
for(var/M in invokers)
var/mob/living/L = M
- L.apply_damage(15, BRUTE, pick("l_arm", "r_arm"))
+ L.apply_damage(10, BRUTE, pick("l_arm", "r_arm"))
L << "[src] saps your strength!"
+ for(var/mob/living/L in viewers(T))
+ if(!iscultist(L) && L.blood_volume)
+ var/obj/item/weapon/nullrod/N = L.null_rod_check()
+ if(N)
+ L << "\The [N] suddenly burns hotly before returning to normal!"
+ continue
+ L << "Your blood boils in your veins!"
+ if(is_servant_of_ratvar(L))
+ L << "You feel an unholy darkness dimming the Justiciar's light!"
+ animate(src, color = "#FCB56D", time = 4)
+ sleep(4)
+ if(!src)
+ return
+ do_area_burn(T, 0.5)
+ animate(src, color = "#FFDF80", time = 5)
+ sleep(5)
+ if(!src)
+ return
+ do_area_burn(T, 1)
+ animate(src, color = "#FFFDF4", time = 6)
+ sleep(6)
+ if(!src)
+ return
+ do_area_burn(T, 1.5)
+ PoolOrNew(/obj/effect/hotspot, T)
qdel(src)
- explosion(T, -1, 0, 1, 5)
+
+/obj/effect/rune/blood_boil/proc/do_area_burn(turf/T, multiplier)
+ for(var/mob/living/L in viewers(T))
+ if(!iscultist(L) && L.blood_volume)
+ var/obj/item/weapon/nullrod/N = L.null_rod_check()
+ if(N)
+ continue
+ L.take_overall_damage(tick_damage*multiplier, tick_damage*multiplier)
+ if(is_servant_of_ratvar(L))
+ L.adjustStaminaLoss(tick_damage*0.5)
//Deals brute damage to all targets on the rune and heals the invoker for each target drained.
@@ -873,7 +915,7 @@ var/list/teleport_runes = list()
cultist_desc = "drains the life of all targets on the rune, restoring life to the user."
invocation = "Yu'gular faras desdae. Umathar uf'kal thenar!"
icon_state = "3"
- color = rgb(159, 28, 52)
+ color = "#9F1C34"
/obj/effect/rune/leeching/can_invoke(mob/living/user)
if(world.time <= user.next_move)
@@ -912,7 +954,7 @@ var/list/teleport_runes = list()
invocation = "Gal'h'rfikk harfrandid mud'gib!" //how the fuck do you pronounce this
icon_state = "6"
construct_invoke = 0
- color = rgb(200, 0, 0)
+ color = "#C80000"
/obj/effect/rune/manifest/New(loc)
..()
diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm
index 93a2cb6e18a..9a27ad81c6c 100644
--- a/code/game/gamemodes/cult/talisman.dm
+++ b/code/game/gamemodes/cult/talisman.dm
@@ -149,9 +149,13 @@
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
if(!actual_selected_rune)
return ..(user, 0)
+ var/turf/target = get_turf(actual_selected_rune)
+ if(is_blocked_turf(target))
+ user << "The target rune is blocked. Attempting to teleport to it would be massively unwise."
+ return ..(user, 0)
user.visible_message("Dust flows from [user]'s hand, and they disappear in a flash of red light!", \
"You speak the words of the talisman and find yourself somewhere else!")
- user.forceMove(get_turf(actual_selected_rune))
+ user.forceMove(target)
return ..()
@@ -345,8 +349,8 @@
/obj/item/weapon/paper/talisman/construction/afterattack(obj/item/stack/sheet/target, mob/user, proximity_flag, click_parameters)
..()
if(proximity_flag && iscultist(user))
+ var/turf/T = get_turf(target)
if(istype(target, /obj/item/stack/sheet/metal))
- var/turf/T = get_turf(target)
if(target.use(25))
new /obj/structure/constructshell(T)
user << "The talisman clings to the metal and twists it into a construct shell!"
@@ -355,16 +359,16 @@
qdel(src)
else
user << "You need more metal to produce a construct shell!"
- if(istype(target, /obj/item/stack/sheet/plasteel))
- var/quantity = min(target.amount, uses)
- uses -= quantity
- new /obj/item/stack/sheet/runed_metal(T,quantity)
- target.use(quantity)
- user << "The talisman clings to the plasteel, transforming it into runed metal!"
- user << sound('sound/effects/magic.ogg',0,1,25)
- invoke(user, 1)
- if(uses <= 0)
- qdel(src)
+ else if(istype(target, /obj/item/stack/sheet/plasteel))
+ var/quantity = min(target.amount, uses)
+ uses -= quantity
+ new /obj/item/stack/sheet/runed_metal(T,quantity)
+ target.use(quantity)
+ user << "The talisman clings to the plasteel, transforming it into runed metal!"
+ user << sound('sound/effects/magic.ogg',0,1,25)
+ invoke(user, 1)
+ if(uses <= 0)
+ qdel(src)
else
user << "The talisman must be used on metal or plasteel!"
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index b96e2ee6697..e4311624dc5 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -526,7 +526,7 @@
return max(0, enemy_minimum_age - C.player_age)
/datum/game_mode/proc/replace_jobbaned_player(mob/living/M, role_type, pref)
- var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [role_type]?", "[role_type]", null, pref, 100, M)
+ var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [role_type]?", "[role_type]", null, pref, 50, M)
var/mob/dead/observer/theghost = null
if(candidates.len)
theghost = pick(candidates)
@@ -539,7 +539,6 @@
ticker.mode.remove_cultist(newborgie, 0, 0)
ticker.mode.remove_revolutionary(newborgie, 0)
ticker.mode.remove_gangster(newborgie, 0, remove_bosses=1)
- ticker.mode.remove_hog_follower(newborgie, 0)
remove_servant_of_ratvar(newborgie.current, TRUE)
diff --git a/code/game/gamemodes/handofgod/_handofgod.dm b/code/game/gamemodes/handofgod/_handofgod.dm
deleted file mode 100644
index 2de6b0f782d..00000000000
--- a/code/game/gamemodes/handofgod/_handofgod.dm
+++ /dev/null
@@ -1,476 +0,0 @@
-
-var/global/list/global_handofgod_traptypes = list()
-var/global/list/global_handofgod_structuretypes = list()
-
-#define CONDUIT_RANGE 15
-
-
-/datum/game_mode
- var/list/datum/mind/red_deities = list()
- var/list/datum/mind/red_deity_prophets = list()
- var/list/datum/mind/red_deity_followers = list()
-
- var/list/datum/mind/blue_deities = list()
- var/list/datum/mind/blue_deity_prophets = list()
- var/list/datum/mind/blue_deity_followers = list()
-
- var/list/datum/mind/unassigned_followers = list() //for roundstart team assigning
- var/list/datum/mind/assigned_to_red = list()
- var/list/datum/mind/assigned_to_blue = list()
-
-
-/datum/game_mode/hand_of_god
- name = "hand of god"
- config_tag = "handofgod"
- antag_flag = ROLE_HOG_CULTIST //Followers use ROLE_HOG_CULTIST, Gods are picked later on with ROLE_HOG_GOD
-
- required_players = 25
- required_enemies = 8
- recommended_enemies = 8
- restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel")
-
- announce_span = "danger"
- announce_text = "Two cults are trying to overthrow one another!\n\
- Gods: Protect your nexus and eliminate the enemy god.\n\
- Prophets: Lead your cult by your deity's will.\n\
- Followers: Follow your prophet's orders and lead your deity to victory.\n\
- Crew: Destroy both cults before they can grow in strength."
-
-
-/////////////
-//Pre setup//
-/////////////
-
-/datum/game_mode/hand_of_god/pre_setup()
- if(config.protect_roles_from_antagonist)
- restricted_jobs += protected_jobs
-
- if(config.protect_assistant_from_antagonist)
- restricted_jobs += "Assistant"
-
- for(var/F in 1 to recommended_enemies)
- if(!antag_candidates.len)
- break
- var/datum/mind/follower = pick_n_take(antag_candidates)
- unassigned_followers += follower
- follower.restricted_roles = restricted_jobs
- log_game("[follower.key] (ckey) has been selected as a follower, however teams have not been decided yet.")
-
- while(unassigned_followers.len > (required_enemies / 2))
- var/datum/mind/chosen = pick_n_take(unassigned_followers)
- add_hog_follower(chosen,"red")
-
- while(unassigned_followers.len)
- var/datum/mind/chosen = pick_n_take(unassigned_followers)
- add_hog_follower(chosen,"blue")
-
- return 1
-
-
-//////////////
-//Post Setup//
-//////////////
-
-//Pick a follower to uplift into a god
-/datum/game_mode/hand_of_god/post_setup()
-
- //Find viable red god
- var/list/red_god_possibilities = get_players_for_role(ROLE_HOG_GOD)
- red_god_possibilities &= red_deity_followers //followers only
- if(!red_god_possibilities.len) //No candidates? just pick any follower regardless of prefs
- red_god_possibilities = red_deity_followers
-
- //Make red god
- var/datum/mind/red_god = pick_n_take(red_god_possibilities)
- if(red_god)
- red_god.current.become_god("red")
- remove_hog_follower(red_god,0)
- add_god(red_god,"red")
-
- //Find viable blue god
- var/list/blue_god_possibilities = get_players_for_role(ROLE_HOG_GOD)
- blue_god_possibilities &= blue_deity_followers //followers only
- if(!blue_god_possibilities.len) //No candidates? just pick any follower regardless of prefs
- blue_god_possibilities = blue_deity_followers
-
- //Make blue god
- var/datum/mind/blue_god = pick_n_take(blue_god_possibilities)
- if(blue_god)
- blue_god.current.become_god("blue")
- remove_hog_follower(blue_god,0)
- add_god(blue_god,"blue")
-
-
- //Forge objectives
- //This is done here so that both gods exist
- if(red_god)
- ticker.mode.forge_deity_objectives(red_god)
- if(blue_god)
- ticker.mode.forge_deity_objectives(blue_god)
-
-
- ..()
-
-///////////////////
-//Objective Procs//
-///////////////////
-
-/datum/game_mode/proc/forge_deity_objectives(datum/mind/deity)
- switch(rand(1,100))
- if(1 to 30)
- var/datum/objective/deicide/deicide = new
- deicide.owner = deity
- if(deicide.find_target())//Hard to kill the other god if there is none
- deity.objectives += deicide
-
- if(!(locate(/datum/objective/escape_followers) in deity.objectives))
- var/datum/objective/escape_followers/recruit = new
- recruit.owner = deity
- deity.objectives += recruit
- recruit.gen_amount_goal(8, 12)
-
- if(31 to 60)
- var/datum/objective/sacrifice_prophet/sacrifice = new
- sacrifice.owner = deity
- deity.objectives += sacrifice
-
- if(!(locate(/datum/objective/escape_followers) in deity.objectives))
- var/datum/objective/escape_followers/recruit = new
- recruit.owner = deity
- deity.objectives += recruit
- recruit.gen_amount_goal(8, 12)
-
- if(61 to 85)
- var/datum/objective/build/build = new
- build.owner = deity
- deity.objectives += build
- build.gen_amount_goal(8, 16)
-
- var/datum/objective/sacrifice_prophet/sacrifice = new
- sacrifice.owner = deity
- deity.objectives += sacrifice
-
- if(!(locate(/datum/objective/escape_followers) in deity.objectives))
- var/datum/objective/escape_followers/recruit = new
- recruit.owner = deity
- deity.objectives += recruit
- recruit.gen_amount_goal(8, 12)
-
- else
- if (!locate(/datum/objective/follower_block) in deity.objectives)
- var/datum/objective/follower_block/block = new
- block.owner = deity
- deity.objectives += block
-
-///////////////
-//Greet procs//
-///////////////
-
-/datum/game_mode/proc/greet_hog_follower(datum/mind/follower_mind,colour)
- if(follower_mind in blue_deity_prophets || follower_mind in red_deity_prophets)
- follower_mind.current << "You have been appointed as the prophet of the [colour] deity! You are the only one who can communicate with your deity at will. Guide your followers, but be wary, for many will want you dead."
- else if(colour)
- follower_mind.current << "You are a follower of the [colour] cult's deity!"
- else
- follower_mind.current << "You are a follower of a cult's deity!"
-
-
-/////////////////
-//Convert procs//
-/////////////////
-
-/datum/game_mode/proc/add_hog_follower(datum/mind/follower_mind, colour = "No Colour")
- var/mob/living/carbon/human/H = follower_mind.current
- if(isloyal(H))
- H << "Your mindshield implant blocked the influence of the [colour] deity. "
- return 0
- if((follower_mind in red_deity_followers) || (follower_mind in red_deity_prophets) || (follower_mind in blue_deity_followers) || (follower_mind in blue_deity_prophets))
- H << "You already belong to a deity. Your strong faith has blocked out the conversion attempt by the followers of the [colour] deity."
- return 0
- var/obj/item/weapon/nullrod/N = H.null_rod_check()
- if(N)
- H << "Your holy weapon prevented the [colour] deity from brainwashing you."
- return 0
-
- if(colour == "red")
- red_deity_followers += follower_mind
- if(colour == "blue")
- blue_deity_followers += follower_mind
-
- H.faction |= "[colour] god"
- follower_mind.current << "You are now a follower of the [colour] deity! Follow your deity's prophet in order to complete your deity's objectives. Convert crewmembers to your cause by using your deity's nexus. And remember - there is no you, there is only the cult."
- update_hog_icons_added(follower_mind, colour)
- follower_mind.special_role = "Hand of God: [capitalize(colour)] Follower"
- follower_mind.current.attack_log += "\[[time_stamp()]\] Has been converted to the [colour] follower cult!"
- return 1
-
-
-/datum/game_mode/proc/add_god(datum/mind/god_mind, colour = "No Colour")
- remove_hog_follower(god_mind, announce = 0)
- if(colour == "red")
- red_deities += god_mind
- if(colour == "blue")
- blue_deities += god_mind
- god_mind.current.attack_log += "\[[time_stamp()]\] Has been made into a [colour] deity!"
- god_mind.special_role = "Hand of God: [colour] God"
- update_hog_icons_added(god_mind, colour)
-
-//////////////////
-//Deconvert proc//
-//////////////////
-
-/datum/game_mode/proc/remove_hog_follower(datum/mind/follower_mind, announce = 1)//deconverts both
- if(follower_mind.current)
- if(is_handofgod_cultist(follower_mind.current) || is_handofgod_prophet(follower_mind.current))
- follower_mind.remove_hog_follower_prophet()
- update_hog_icons_removed(follower_mind,"red")
- update_hog_icons_removed(follower_mind,"blue")
-
- var/mob/living/carbon/human/H = follower_mind.current
- H.faction -= "red god"
- H.faction -= "blue god"
-
- if(announce)
- follower_mind.current.attack_log += "\[[time_stamp()]\] Has been deconverted from a deity's cult!"
- follower_mind.current << "Your mind has been cleared from the brainwashing the followers have done to you. Now you serve yourself and the crew."
- for(var/mob/living/M in view(follower_mind.current))
- M << "[follower_mind.current] looks like their faith is shattered. They're no longer a cultist!"
-
-
-
-//////////////////////
-// Mob helper procs //
-//////////////////////
-
-/proc/is_handofgod_god(A)
- if(istype(A, /mob/camera/god))
- return 1
- return 0
-
-
-/proc/is_handofgod_bluecultist(A)
- if(ishuman(A))
- var/mob/living/carbon/human/H = A
- if(H.mind)
- if(H.mind in ticker.mode.blue_deity_followers|ticker.mode.blue_deity_prophets)
- return 1
- return 0
-
-
-/proc/is_handofgod_redcultist(A)
- if(ishuman(A))
- var/mob/living/carbon/human/H = A
- if(H.mind)
- if(H.mind in ticker.mode.red_deity_followers|ticker.mode.red_deity_prophets)
- return 1
- return 0
-
-
-/proc/is_handofgod_blueprophet(A)
- if(ishuman(A))
- var/mob/living/carbon/human/H = A
- if(H.mind)
- if(H.mind in ticker.mode.blue_deity_prophets)
- return 1
- return 0
-
-
-/proc/is_handofgod_redprophet(A)
- if(ishuman(A))
- var/mob/living/carbon/human/H = A
- if(H.mind)
- if(H.mind in ticker.mode.red_deity_prophets)
- return 1
- return 0
-
-
-
-/proc/is_handofgod_cultist(A) //any of them what so ever, blue, red, hot pink, whatever.
- if(is_handofgod_redcultist(A))
- return 1
- if(is_handofgod_bluecultist(A))
- return 1
- return 0
-
-
-/proc/is_handofgod_prophet(A) //any of them what so ever, blue, red, hot pink, whatever
- if(ishuman(A))
- var/mob/living/carbon/human/H = A
- if(H.mind)
- if(H.mind in ticker.mode.blue_deity_prophets|ticker.mode.red_deity_prophets)
- return 1
- return 0
-
-
-/mob/camera/god/proc/is_handofgod_myprophet(A)
- if(!ishuman(A))
- return 0
- var/mob/living/carbon/human/H = A
- if(!H.mind)
- return 0
- if(side == "red")
- if(H.mind in ticker.mode.red_deity_prophets)
- return 1
- else if(side == "blue")
- if(H.mind in ticker.mode.blue_deity_prophets)
- return 1
-
-
-/mob/camera/god/proc/is_handofgod_myfollowers(mob/A)
- if(!ishuman(A))
- return 0
- var/mob/living/carbon/human/H = A
- if(!H.mind)
- return 0
- if(side == "red")
- if(H.mind in ticker.mode.red_deity_prophets|ticker.mode.red_deity_followers)
- return 1
- else if(side == "blue")
- if(H.mind in ticker.mode.blue_deity_prophets|ticker.mode.blue_deity_followers)
- return 1
-
-//////////////////////
-//Roundend Reporting//
-//////////////////////
-
-
-/datum/game_mode/hand_of_god/declare_completion()
- if(red_deities.len)
- var/text = "
The red cult:"
- for(var/datum/mind/red_god in red_deities)
- var/godwin = 1
-
- text += "
[red_god.key] was the red deity, [red_god.name] ("
- if(red_god.current)
- if(red_god.current.stat == DEAD)
- text += "died"
- else
- text += "survived"
- else
- text += "ceased existing"
- text += ")"
- if(red_deity_prophets.len)
- for(var/datum/mind/red_prophet in red_deity_prophets)
- text += "
The red prophet was [red_prophet.name] ([red_prophet.key])"
- else
- text += "
the red prophet was killed for their beliefs."
-
- text += "
Red follower count: [red_deity_followers.len]"
- text += "
Red followers: "
- for(var/datum/mind/player in red_deity_followers)
- text += "[player.name] ([player.key]), "
-
- var/objectives = ""
- if(red_god.objectives.len)
- var/count = 1
- for(var/datum/objective/O in red_god.objectives)
- if(O.check_completion())
- objectives += "
Objective #[count]: [O.explanation_text] Success!"
- feedback_add_details("god_objective","[O.type]|SUCCESS")
- else
- objectives += "
Objective #[count]: [O.explanation_text] Fail."
- feedback_add_details("god_objective","[O.type]|FAIL")
- godwin = 0
- count++
-
- text += objectives
-
- if(godwin)
- text += "
The red cult and deity were successful!"
- feedback_add_details("god_success","SUCCESS")
- else
- text += "
The red cult and deity have failed!"
- feedback_add_details("god_success","FAIL")
-
- text += "
"
-
- world << text
-
- if(blue_deities.len)
- var/text = "
The blue cult:"
- for(var/datum/mind/blue_god in blue_deities)
- var/godwin = 1
-
- text += "
[blue_god.key] was the blue deity, [blue_god.name] ("
- if(blue_god.current)
- if(blue_god.current.stat == DEAD)
- text += "died"
- else
- text += "survived"
- else
- text += "ceased existing"
- text += ")"
- if(blue_deity_prophets.len)
- for(var/datum/mind/blue_prophet in blue_deity_prophets)
- text += "
The blue prophet was [blue_prophet.name] ([blue_prophet.key])"
- else
- text += "
the blue prophet was killed for their beliefs."
-
- text += "
Blue follower count: [blue_deity_followers.len]"
- text += "
Blue followers: "
- for(var/datum/mind/player in blue_deity_followers)
- text += "[player.name] ([player.key])"
-
- var/objectives = ""
- if(blue_god.objectives.len)
- var/count = 1
- for(var/datum/objective/O in blue_god.objectives)
- if(O.check_completion())
- objectives += "
Objective #[count]: [O.explanation_text] Success!"
- feedback_add_details("god_objective","[O.type]|SUCCESS")
- else
- objectives += "
Objective #[count]: [O.explanation_text] Fail."
- feedback_add_details("god_objective","[O.type]|FAIL")
- godwin = 0
- count++
-
- text += objectives
-
- if(godwin)
- text += "
The blue cult and deity were successful!"
- feedback_add_details("god_success","SUCCESS")
- else
- text += "
The blue cult and deity have failed!"
- feedback_add_details("god_success","FAIL")
-
- text += "
"
-
- world << text
-
- ..()
- return 1
-
-
-/datum/game_mode/proc/update_hog_icons_added(datum/mind/hog_mind,side)
- var/hud_key
- var/rank = 0
- if(side == "red")
- hud_key = ANTAG_HUD_HOG_RED
- if(is_handofgod_redprophet(hog_mind.current))
- rank = 1
-
- else if(side == "blue")
- hud_key = ANTAG_HUD_HOG_BLUE
- if(is_handofgod_blueprophet(hog_mind.current))
- rank = 1
-
- if(is_handofgod_god(hog_mind.current))
- rank = 2
-
- if(hud_key)
- var/datum/atom_hud/antag/hog_hud = huds[hud_key]
- hog_hud.join_hud(hog_mind.current)
- set_antag_hud(hog_mind.current, "hog-[side]-[rank]")
-
-
-/datum/game_mode/proc/update_hog_icons_removed(datum/mind/hog_mind,side)
- var/hud_key
- if(side == "red")
- hud_key = ANTAG_HUD_HOG_RED
- else if(side == "blue")
- hud_key = ANTAG_HUD_HOG_BLUE
-
- if(hud_key)
- var/datum/atom_hud/antag/hog_hud = huds[hud_key]
- hog_hud.leave_hud(hog_mind.current)
- set_antag_hud(hog_mind.current,null)
diff --git a/code/game/gamemodes/handofgod/actions.dm b/code/game/gamemodes/handofgod/actions.dm
deleted file mode 100644
index 766a2522fde..00000000000
--- a/code/game/gamemodes/handofgod/actions.dm
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Prophet's innate godspeak */
-/datum/action/innate/godspeak
- name = "Godspeak"
- button_icon_state = "godspeak"
- check_flags = AB_CHECK_CONSCIOUS
- var/mob/camera/god/god = null
-
-/datum/action/innate/godspeak/IsAvailable()
- if(..())
- if(god)
- return 1
- return 0
-
-/datum/action/innate/godspeak/Activate()
- var/msg = input(owner,"Speak to your god","Godspeak","") as null|text
- if(!msg)
- return
- var/rendered = "Prophet [owner]: "
- god << rendered
- owner << rendered
- for(var/mob/M in mob_list)
- if(isobserver(M))
- var/link = FOLLOW_LINK(M, owner)
- M << "[link] [rendered]"
-
-/datum/action/innate/godspeak/Destroy()
- god = null
- return ..()
diff --git a/code/game/gamemodes/handofgod/god.dm b/code/game/gamemodes/handofgod/god.dm
deleted file mode 100644
index 5a238736052..00000000000
--- a/code/game/gamemodes/handofgod/god.dm
+++ /dev/null
@@ -1,290 +0,0 @@
-
-/mob/camera/god
- name = "deity" //Auto changes to the player's deity name/random name
- real_name = "deity"
- icon = 'icons/mob/mob.dmi'
- icon_state = "marker"
- invisibility = 60
- see_in_dark = 0
- see_invisible = 55
- sight = SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
- languages_spoken = ALL
- languages_understood = ALL
- hud_possible = list(ANTAG_HUD)
- mouse_opacity = 0 //can't be clicked
-
- var/faith = 100 //For initial prophet appointing/stupid purchase
- var/max_faith = 100
- var/side = "neutral" //Red or Blue for the gamemode
- var/obj/structure/divine/nexus/god_nexus = null //The source of the god's power in this realm, kill it and the god is kill
- var/nexus_required = FALSE //If the god dies from losing it's nexus, defaults to off so that gods don't instantly die at roundstart
- var/followers_required = 0 //Same as above
- var/alive_followers = 0
- var/list/structures = list()
- var/list/conduits = list()
- var/prophets_sacrificed_in_name = 0
- var/image/ghostimage = null //For observer with darkness off visiblity
- var/list/prophets = list()
- var/datum/action/innate/godspeak/speak2god
-
-/mob/camera/god/New()
- ..()
- update_icons()
- build_hog_construction_lists()
-
- //Force nexuses after 15 minutes in hand of god mode
- if(ticker && ticker.mode && ticker.mode.name == "hand of god")
- addtimer(src, "forceplacenexus", 9000, FALSE)
-
-
-//Rebuilds the list based on the gamemode's lists
-//As they are the most accurate each tick
-/mob/camera/god/proc/get_my_followers()
- switch(side)
- if("red")
- . = ticker.mode.red_deity_followers|ticker.mode.red_deity_prophets
- if("blue")
- . = ticker.mode.blue_deity_followers|ticker.mode.blue_deity_prophets
- else
- . = list()
-
-
-/mob/camera/god/Destroy()
- var/list/followers = get_my_followers()
- for(var/datum/mind/F in followers)
- if(F.current)
- F.current << "Your god is DEAD!"
- for(var/X in prophets)
- speak2god.Remove(X)
- ghost_darkness_images -= ghostimage
- updateallghostimages()
- return ..()
-
-
-
-/mob/camera/god/proc/forceplacenexus()
- if(god_nexus)
- return
-
- if(ability_cost(0,1,0))
- place_nexus()
-
- else
- if(blobstart.len) //we're on invalid turf, try to pick from blobstart
- loc = pick(blobstart)
- place_nexus() //if blobstart fails, places on dense turf, but better than nothing
- src << "You failed to place your nexus, and it has been placed for you!"
-
-
-/mob/camera/god/update_icons()
- icon_state = "[initial(icon_state)]-[side]"
-
- if(ghostimage)
- ghost_darkness_images -= ghostimage
-
- ghostimage = image(src.icon,src,src.icon_state)
- ghost_darkness_images |= ghostimage
- updateallghostimages()
-
-
-/mob/camera/god/Stat()
- ..()
- if(statpanel("Status"))
- if(god_nexus)
- stat("Nexus health: ", god_nexus.health)
- stat("Followers: ", alive_followers)
- stat("Faith: ", "[faith]/[max_faith]")
-
-
-/mob/camera/god/Login()
- ..()
- sync_mind()
- src << "You are a deity!"
- src << "You are a deity and are worshipped by a cult! You are rather weak right now, but that will change as you gain more followers."
- src << "You will need to place an anchor to this world, a Nexus, in two minutes. If you don't, one will be placed immediately below you."
- src << "Your Follower count determines how many people believe in you and are a part of your cult."
- src << "Your Nexus Integrity tells you the condition of your nexus. If your nexus is destroyed, you will die. Place your Nexus on a safe, isolated place, that is still accessible to your followers."
- src << "Your Faith is used to interact with the world. This will regenerate on its own, and it goes faster when you have more followers and power pylons."
- src << "The first thing you should do after placing your nexus is to appoint a prophet. Only prophets can hear you talk, unless you use an expensive power."
- update_health_hud()
-
-
-/mob/camera/god/update_health_hud()
- if(god_nexus && hud_used && hud_used.healths)
- hud_used.healths.maptext = "
"
- var/imgstate = initial(apath.autocolours) ? "[initial(apath.icon_state)]-[side]" : "[initial(apath.icon_state)]"
- var/icon/I = icon('icons/obj/hand_of_god_structures.dmi',imgstate)
- var/img_component = lowertext(t)
- //I hate byond, but atleast it autocaches these so it's only 1*number_of_structures worth of actual calls
- user << browse_rsc(I,"hog_structure-[img_component].png")
- dat += "
"
- dat += "
"
-
- var/datum/browser/popup = new(src, "structures","Construct Structure",350,500)
- popup.set_content(dat)
- popup.open()
-
-
-/mob/camera/god/proc/trap_construction_ui(mob/camera/god/user)
- var/dat = ""
- for(var/t in global_handofgod_traptypes)
- if(global_handofgod_traptypes[t])
- var/obj/structure/divine/trap/T = global_handofgod_traptypes[t]
- dat += "
"
- var/icon/I = icon('icons/obj/hand_of_god_structures.dmi',"[initial(T.icon_state)]")
- var/img_component = lowertext(t)
- user << browse_rsc(I,"hog_trap-[img_component].png")
- dat += "
"
- dat += "
"
-
- var/datum/browser/popup = new(src, "traps", "Place Trap",350,500)
- popup.set_content(dat)
- popup.open()
diff --git a/code/game/gamemodes/handofgod/objectives.dm b/code/game/gamemodes/handofgod/objectives.dm
deleted file mode 100644
index dc31d67f46c..00000000000
--- a/code/game/gamemodes/handofgod/objectives.dm
+++ /dev/null
@@ -1,129 +0,0 @@
-
-/datum/objective/build
- dangerrating = 15
- martyr_compatible = 1
-
-
-/datum/objective/build/proc/gen_amount_goal(lower, upper)
- target_amount = rand(lower, upper)
- explanation_text = "Build [target_amount] shrines."
- return target_amount
-
-
-/datum/objective/build/check_completion()
- if(!owner || !owner.current)
- return 0
-
- var/shrines = 0
- if(is_handofgod_god(owner.current))
- var/mob/camera/god/G = owner.current
- for(var/obj/structure/divine/shrine/S in G.structures)
- S++
-
- return (shrines >= target_amount)
-
-
-
-/datum/objective/deicide
- dangerrating = 20
- martyr_compatible = 1
-
-/datum/objective/deicide/check_completion()
- if(target)
- if(target.current) //Gods are deleted when they lose
- return 0
- return 1
-
-
-/datum/objective/deicide/find_target()
- if(!owner || !owner.current)
- return
-
- if(is_handofgod_god(owner.current))
- var/mob/camera/god/G = owner.current
- if(G.side == "red")
- if(ticker.mode.blue_deities.len)
- target = ticker.mode.blue_deities[1]
- if(G.side == "blue")
- if(ticker.mode.red_deities.len)
- target = ticker.mode.red_deities[1]
- if(!target)
- return 0
- update_explanation_text()
-
-/datum/objective/deicide/update_explanation_text()
- ..()
- if(target && target.current)
- explanation_text = "Phase [target.name], the false god, out of this plane of existence.."
- else
- explanation_text = "Free Objective"
-
-
-
-/datum/objective/follower_block
- explanation_text = "Do not allow any followers of the false god to escape on the station's shuttle alive."
- dangerrating = 25
- martyr_compatible = 1
-
-/datum/objective/follower_block/check_completion()
- var/side = "ABORT"
- if(is_handofgod_redcultist(owner.current))
- side = "red"
- else if(is_handofgod_bluecultist(owner.current))
- side = "blue"
- if(side == "ABORT")
- return 0
-
- var/area/A = SSshuttle.emergency.areaInstance
-
- for(var/mob/living/player in player_list)
- if(player.mind && player.stat != DEAD && get_area(player) == A)
- if(side == "red")
- if(is_handofgod_bluecultist(player))
- return 0
- else if(side == "blue")
- if(is_handofgod_redcultist(player))
- return 0
- return 1
-
-
-
-/datum/objective/escape_followers
- dangerrating = 5
-
-
-/datum/objective/escape_followers/proc/gen_amount_goal(lower,upper)
- target_amount = rand(lower,upper)
- explanation_text = "Your will must surpass this station. Having [target_amount] followers escape on the shuttle or pods will allow that."
- return target_amount
-
-
-/datum/objective/escape_followers/check_completion()
- var/escaped = 0
- if(is_handofgod_god(owner.current))
- var/mob/camera/god/G = owner.current
- if(G.side == "red")
- for(var/datum/mind/follower_mind in ticker.mode.red_deity_followers)
- if(follower_mind.current && follower_mind.current.stat != DEAD)
- if(follower_mind.current.onCentcom())
- escaped++
-
- if(G.side == "blue")
- for(var/datum/mind/follower_mind in ticker.mode.blue_deity_followers)
- if(follower_mind.current && follower_mind.current.stat != DEAD)
- if(follower_mind.current.onCentcom())
- escaped++
-
- return (escaped >= target_amount)
-
-
-/datum/objective/sacrifice_prophet
- explanation_text = "A false prophet is preaching their god's faith on the station. Sacrificing them will show the mortals who the true god is."
- dangerrating = 10
-
-
-/datum/objective/sacrifice_prophet/check_completion()
- var/mob/camera/god/G = owner.current
- if(istype(G))
- return G.prophets_sacrificed_in_name
- return 0
diff --git a/code/game/gamemodes/handofgod/powers.dm b/code/game/gamemodes/handofgod/powers.dm
deleted file mode 100644
index 30b3365cfcd..00000000000
--- a/code/game/gamemodes/handofgod/powers.dm
+++ /dev/null
@@ -1,363 +0,0 @@
-/mob/camera/god/proc/ability_cost(cost = 0,structures = 0, requires_conduit = 0, can_place_near_enemy_nexus = 0)
- if(faith < cost)
- src << "You lack the faith!"
- return 0
-
- if(structures)
- if(!isturf(loc) || istype(loc, /turf/open/space))
- src << "Your structure would just float away, you need stable ground!"
- return 0
-
- var/turf/T = get_turf(src)
- if(T)
- if(T.density)
- src << "There is something blocking your structure!"
- return 0
-
- for(var/atom/movable/AM in T)
- if(AM == src)
- continue
- if(AM.density)
- src << "There is something blocking your structure!"
- return 0
-
- if(requires_conduit)
- //Organised this way as there can be multiple conduits, so it's more likely to be a conduit check.
- var/valid = 0
-
- for(var/obj/structure/divine/conduit/C in conduits)
- if(get_dist(src, C) <= CONDUIT_RANGE)
- valid++
- break
-
- if(!valid)
- if(get_dist(src, god_nexus) <= CONDUIT_RANGE)
- valid++
-
- if(!valid)
- src << "You must be near your Nexus or a Conduit to do this!"
- return 0
-
- if(!can_place_near_enemy_nexus)
- var/datum/mind/enemy
- switch(side)
- if("red")
- if(ticker.mode.blue_deities.len)
- enemy = ticker.mode.blue_deities[1]
- if("blue")
- if(ticker.mode.red_deities.len)
- enemy = ticker.mode.red_deities[1]
-
- if(enemy && is_handofgod_god(enemy.current))
- var/mob/camera/god/enemy_god = enemy.current
- if(enemy_god.god_nexus && (get_dist(src,enemy_god.god_nexus) <= CONDUIT_RANGE*2))
- src << "You are too close to the other god's stronghold!"
- return 0
-
- return 1
-
-
-/mob/camera/god/verb/returntonexus()
- set category = "Deity"
- set name = "Goto Nexus"
- set desc = "Teleports you to your next instantly."
-
- if(god_nexus)
- Move(get_turf(god_nexus))
- else
- src << "You don't even have a Nexus, construct one."
-
-
-/mob/camera/god/verb/jumptofollower()
- set category = "Deity"
- set name = "Jump to Follower"
- set desc = "Teleports you to one of your followers."
- var/list/following = list()
- if(side == "red")
- following = ticker.mode.red_deity_followers|ticker.mode.red_deity_prophets
- else if(side == "blue")
- following = ticker.mode.blue_deity_followers|ticker.mode.blue_deity_prophets
- else
- src << "You are unaligned, and thus do not have followers"
- return
-
- var/datum/mind/choice = input("Choose a follower","Jump to Follower") as null|anything in following
- if(choice && choice.current)
- Move(get_turf(choice.current))
-
-
-/mob/camera/god/verb/newprophet()
- set category = "Deity"
- set name = "Appoint Prophet (100)"
- set desc = "Appoint one of your followers as your Prophet, who can hear your words"
-
- var/list/following = list()
-
- if(!ability_cost(100))
- return
- if(side == "red")
- var/datum/mind/old_proph = locate() in ticker.mode.red_deity_prophets
- if(old_proph && old_proph.current && old_proph.current.stat != DEAD)
- src << "You can only have one prophet alive at a time."
- return
- else
- following = ticker.mode.red_deity_followers
- else if(side == "blue")
- var/datum/mind/old_proph = locate() in ticker.mode.blue_deity_prophets
- if(old_proph && old_proph.current && old_proph.current.stat != DEAD)
- src << "You can only have one prophet alive at a time."
- return
- else
- following = ticker.mode.blue_deity_followers
-
- else
- src << "You are unalligned, and thus do not have prophets"
- return
-
- var/datum/mind/choice = input("Choose a follower to make into your prophet","Prophet Uplifting") as null|anything in following
- if(choice && choice.current && choice.current.stat != DEAD)
- src << "You choose [choice.current] as your prophet."
- choice.make_Handofgod_prophet(side)
- speak2god = new()
- speak2god.god = src
- speak2god.Grant(choice.current)
-
- //Prophet gear
- var/mob/living/carbon/human/H = choice.current
- var/popehat = null
- var/popestick = null
- var/success = ""
- switch(side)
- if("red")
- popehat = /obj/item/clothing/head/helmet/plate/crusader/prophet/red
- popestick = /obj/item/weapon/godstaff/red
- if("blue")
- popehat = /obj/item/clothing/head/helmet/plate/crusader/prophet/blue
- popestick = /obj/item/weapon/godstaff/blue
-
- if(popehat)
- var/obj/item/clothing/head/helmet/plate/crusader/prophet/P = new popehat()
-
- if(H.equip_to_slot_if_possible(P,slot_in_backpack,0,1,1))
- success = "It is in your backpack."
- else
- H.unEquip(H.head)
- H.equip_to_slot_or_del(P,slot_head)
- success = "It is on your head."
-
- if(success)
- H << "A powerful hat has been bestowed upon you, you will need to wear it to utilize your staff fully."
- H << "[success]"
-
- if(popestick)
- var/obj/item/weapon/godstaff/G = new popestick()
- G.god = src
- if(!H.equip_to_slot_if_possible(G,slot_in_backpack,0,1,1))
- if(!H.put_in_hands(G))
- G.loc = get_turf(H)
- success = "It is on the floor..."
- else
- success = "It is in your hands..."
- else
- success = "It is in your backpack..."
-
- if(success)
- H << "A powerful staff has been bestowed upon you, you can use this to convert the false god's structures!"
- H << "[success]"
- //end prophet gear
-
- add_faith(-100)
-
-
-/mob/camera/god/verb/talk(msg as text)
- set category = "Deity"
- set name = "Talk to Anyone (20)"
- set desc = "Allows you to send a message to anyone, regardless of their faith."
- if(!ability_cost(20))
- return
- var/mob/choice = input("Choose who you wish to talk to", "Talk to ANYONE") as null|anything in mob_list
- if(choice)
- var/original = msg
- msg = "You hear a voice coming from everywhere and nowhere... [msg]"
- choice << msg
- src << "You say the following to [choice], [original]"
- add_faith(-20)
-
-
-/mob/camera/god/verb/smite()
- set category = "Deity"
- set name = "Smite (40)"
- set desc = "Hits anything under you with a moderate amount of damage."
-
- if(!ability_cost(40,0,1))
- return
- if(!range(7,god_nexus))
- src << "You lack the strength to smite this far from your nexus."
- return
-
- var/has_smitten = 0 //Hast thou been smitten, infidel?
- for(var/mob/living/L in get_turf(src))
- L.adjustFireLoss(20)
- L.adjustBruteLoss(20)
- L << "You feel the wrath of [name]!"
- has_smitten = 1
- if(has_smitten)
- add_faith(-40)
-
-
-/mob/camera/god/verb/disaster()
- set category = "Deity"
- set name = "Invoke Disaster (300)" //difficult to reach without lots of followers
- set desc = "Tug at the fibres of reality itself and bend it to your whims!"
-
- if(!ability_cost(300,0,1))
- return
-
- var/event = pick(/datum/round_event/meteor_wave, /datum/round_event/communications_blackout, /datum/round_event/radiation_storm, /datum/round_event/carp_migration,
- /datum/round_event/spacevine, /datum/round_event/vent_clog, /datum/round_event/wormholes)
- if(event)
- new event()
- add_faith(-300)
-
-
-/mob/camera/god/verb/constructnexus()
- set category = "Deity"
- set name = "Construct Nexus"
- set desc = "Instantly creates your nexus, You can only do this once, make sure you're happy with it!"
-
- if(!ability_cost(0,1,0))
- return
-
- place_nexus()
-
-
-/* //Transolocators have no sprite
-/mob/camera/god/verb/movenexus()
- set category = "Deity"
- set name = "Relocate Nexus (50)"
- set desc = "Instantly relocates your nexus to an existing translocator belonging to your faith, this destroys the translocator in the process"
-
- if(ability_cost(50,0,0) && god_nexus)
- var/list/translocators = list()
- var/list/used_keys = list()
- for(var/obj/structure/divine/translocator/T in structures)
- translocators["[T.name] ([get_area(T)])"] = T
-
- if(!translocators.len)
- src << "You have no translocators!"
- return
-
- var/picked = input(src,"Choose a translocator","Relocate Nexus") as null|anything in translocators
- if(!picked || !translocators[picked])
- return
-
- var/obj/structure/divine/translocator/T = translocators[T]
- var/turf/Tturf = get_turf(T)
- god_nexus.loc = T
- translocators[picked] = null
- add_faith(-50)
- qdel(T)
-*/
-
-/mob/camera/god/verb/construct_structures()
- set category = "Deity"
- set name = "Construct Structure (75)"
- set desc = "Create the foundation of a divine object."
-
- if(!ability_cost(75,1,1))
- return
-
- structure_construction_ui(src)
-
-
-/mob/camera/god/verb/construct_traps()
- set category = "Deity"
- set name = "Construct Trap (20)"
- set desc = "Creates a ward or trap."
-
- if(!ability_cost(20,1,1))
- return
-
- trap_construction_ui(src)
-
-
-
-/mob/camera/god/verb/construct_items()
- set category = "Deity"
- set name = "Construct Items (20)"
- set desc = "Construct some items for your followers"
-
- if(!ability_cost(20,1,1))
- return
-
- var/list/item_types = list("claymore sword" = /obj/item/weapon/claymore/hog)
- if(side == "red")
- item_types["red banner"] = /obj/item/weapon/banner/red
- item_types["red bannerbackpack"] = /obj/item/weapon/storage/backpack/bannerpack/red
- item_types["red armour"] = /obj/item/weapon/storage/box/itemset/crusader/red
-
- else if(side == "blue")
- item_types["blue banner"] = /obj/item/weapon/banner/blue
- item_types["blue bannerbackpack"] = /obj/item/weapon/storage/backpack/bannerpack/blue
- item_types["blue armour"] = /obj/item/weapon/storage/box/itemset/crusader/blue
-
-
- var/item = input("Choose what you wish to create.", "Divine Items") as null|anything in item_types
- if(!item || !item_types[item] || !ability_cost(20,1,1))
- return
-
- src << "You produce \a [item]"
- add_faith(-20)
-
- var/itemtype = item_types[item]
- new itemtype (get_turf(src))
-
-
-
-/mob/camera/god/verb/veil_structures()
- set category = "Deity"
- set name = "Veil Structures (20)"
- set desc = "Hide your structures from sight and touch, but prevent yourself from using them."
-
- if(!ability_cost(20,1,1))
- return
-
- src << "You focus your powers and start dragging your influence into the spiritual plane."
- for(var/mob/M in orange(3,src))//Yes I know this is terrible, but visible message doesnt work for this
- M << "The air begins to shimmer..."
- if(do_after(src, 30, 0, src))
- for(var/obj/structure/divine/R in orange(3,src))
- if(istype(R, /obj/structure/divine/nexus)|| istype(R, /obj/structure/divine/trap)||(src.side != R.side))
- continue
- R.visible_message("[R] fades away.")
- R.invisibility = 55
- R.alpha = 100 //To help ghosts distinguish hidden structures
- R.density = 0
- R.deactivate()
- src << "You hide your influence from view"
- add_faith(-20)
-
-
-/mob/camera/god/verb/reveal_structures()
- set category = "Deity"
- set name = "Reveal Structures (20)"
- set desc = "Make your structures visible again and allow them to be used."
-
- if(!ability_cost(20,1,1))
- return
-
- src << "You focus your powers and start dragging your influence into the material plane."
- for(var/mob/M in orange(3,src))//Yes I know this is terrible, but visible message doesnt work for this
- M << "The air begins to shimmer..."
- if(do_after(src, 40, 0, src))
- for(var/obj/structure/divine/R in orange(3,src))
- if(istype(R, /obj/structure/divine/nexus)|| istype(R, /obj/structure/divine/trap)||(src.side != R.side))
- continue
- R.visible_message("[R] suddenly appears!")
- R.invisibility = 0
- R.alpha = initial(R.alpha)
- R.density = initial(R.density)
- R.activate()
- src << "You bring your influence into view"
- add_faith(-20)
-
diff --git a/code/game/gamemodes/handofgod/structures.dm b/code/game/gamemodes/handofgod/structures.dm
deleted file mode 100644
index 79d6615d06b..00000000000
--- a/code/game/gamemodes/handofgod/structures.dm
+++ /dev/null
@@ -1,661 +0,0 @@
-
-/proc/build_hog_construction_lists()
- if(global_handofgod_traptypes.len && global_handofgod_structuretypes.len)
- return
-
- var/list/types = subtypesof(/obj/structure/divine) - /obj/structure/divine/trap
- for(var/T in types)
- var/obj/structure/divine/D = T
- if(initial(D.constructable))
- if(initial(D.trap))
- global_handofgod_traptypes[initial(D.name)] = T
- else
- global_handofgod_structuretypes[initial(D.name)] = T
-
-/obj/structure/divine
- name = "divine construction site"
- icon = 'icons/obj/hand_of_god_structures.dmi'
- desc = "An unfinished divine building"
- anchored = 1
- density = 1
- var/constructable = TRUE
- var/trap = FALSE
- var/metal_cost = 0
- var/glass_cost = 0
- var/lesser_gem_cost = 0
- var/greater_gem_cost = 0
- var/mob/camera/god/deity
- var/side = "neutral" //"blue" or "red", also used for colouring structures when construction is started by a deity
- var/health = 100
- var/maxhealth = 100
- var/deactivated = 0 //Structures being hidden can't be used. Mainly to prevent invisible defense pylons.
- var/autocolours = TRUE //do we colour to our side?
-
-/obj/structure/divine/New()
- ..()
-
-/obj/structure/divine/proc/deactivate()
- deactivated = 1
-
-/obj/structure/divine/proc/activate()
- deactivated = 0
-
-
-/obj/structure/divine/proc/update_icons()
- if(autocolours)
- icon_state = "[initial(icon_state)]-[side]"
-
-
-/obj/structure/divine/Destroy()
- if(deity)
- deity.structures -= src
- return ..()
-
-
-
-/obj/structure/divine/attackby(obj/item/I, mob/user)
-
- //Structure conversion/capture
- if(istype(I, /obj/item/weapon/godstaff))
- if(!is_handofgod_cultist(user))
- user << "You're not quite sure what the hell you're even doing."
- return
- var/obj/item/weapon/godstaff/G = I
- if(G.god && deity != G.god)
- assign_deity(G.god, alert_old_deity = TRUE)
- visible_message("\The [src] has been captured by [user]!")
- else
- return ..()
-
-/obj/structure/divine/attacked_by(obj/item/I, mob/living/user)
- ..()
- take_damage(I.force, I.damtype, 1)
-
-/obj/structure/divine/proc/take_damage(damage, damage_type = BRUTE, sound_effect = 1)
- switch(damage_type)
- if(BRUTE)
- if(sound_effect)
- if(damage)
- playsound(loc, 'sound/weapons/smash.ogg', 50, 1)
- else
- playsound(loc, 'sound/weapons/tap.ogg', 50, 1)
- if(BURN)
- if(sound_effect)
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- else
- return
- health -= damage
- if(!health)
- visible_message("\The [src] was destroyed!")
- qdel(src)
-
-
-/obj/structure/divine/bullet_act(obj/item/projectile/P)
- . = ..()
- take_damage(P.damage, P.damage_type, 0)
-
-
-/obj/structure/divine/attack_alien(mob/living/carbon/alien/humanoid/user)
- user.changeNext_move(CLICK_CD_MELEE)
- user.do_attack_animation(src)
- add_hiddenprint(user)
- visible_message("\The [user] slashes at [src]!")
- playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
- take_damage(20, BRUTE, 0)
-
-/obj/machinery/attack_animal(mob/living/simple_animal/M)
- M.changeNext_move(CLICK_CD_MELEE)
- M.do_attack_animation(src)
- if(M.melee_damage_upper > 0 || M.obj_damage)
- M.visible_message("[M.name] smashes against \the [src.name].",\
- "You smash against the [src.name].")
- if(M.obj_damage)
- take_damage(M.obj_damage, M.melee_damage_type, 1)
- else
- take_damage(rand(M.melee_damage_lower,M.melee_damage_upper), M.melee_damage_type, 1)
-
-
-/obj/structure/divine/proc/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE)
- if(!new_deity)
- return 0
- if(deity)
- if(alert_old_deity)
- deity << "Your [name] was captured by [new_deity]'s cult!"
- deity.structures -= src
- deity = new_deity
- deity.structures |= src
- side = deity.side
- update_icons()
- return 1
-
-
-/obj/structure/divine/construction_holder
- alpha = 125
- constructable = FALSE
- var/obj/structure/divine/construction_result = /obj/structure/divine //a path, but typed to /obj/structure/divine for initial()
-
-
-
-/obj/structure/divine/construction_holder/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE)
- if(..())
- color = side
-
-
-/obj/structure/divine/construction_holder/attack_god(mob/camera/god/user)
- if(user.side == side && construction_result)
- user.add_faith(75)
- visible_message("[user] has cancelled \the [initial(construction_result.name)]")
- qdel(src)
-
-
-/obj/structure/divine/construction_holder/proc/setup_construction(construct_type)
- if(ispath(construct_type))
- construction_result = construct_type
- name = "[initial(construction_result.name)] construction site "
- icon_state = initial(construction_result.icon_state)
- metal_cost = initial(construction_result.metal_cost)
- glass_cost = initial(construction_result.glass_cost)
- lesser_gem_cost = initial(construction_result.lesser_gem_cost)
- greater_gem_cost = initial(construction_result.greater_gem_cost)
- desc = "An unfinished [initial(construction_result.name)]."
-
-
-/obj/structure/divine/construction_holder/attackby(obj/item/I, mob/user)
- if(!I || !user)
- return 0
-
- if(istype(I, /obj/item/stack/sheet/metal))
- var/obj/item/stack/sheet/metal/M = I
- if(metal_cost)
- var/spend = min(metal_cost, M.amount)
- user << "You add [spend] metal to \the [src]."
- metal_cost = max(0, metal_cost - spend)
- M.use(spend)
- check_completion()
- else
- user << "\The [src] does not require any more metal!"
- return
-
- if(istype(I, /obj/item/stack/sheet/glass))
- var/obj/item/stack/sheet/glass/G = I
- if(glass_cost)
- var/spend = min(glass_cost, G.amount)
- user << "You add [spend] glass to \the [src]."
- glass_cost = max(0, glass_cost - spend)
- G.use(spend)
- check_completion()
- else
- user << "\The [src] does not require any more glass!"
- return
-
- if(istype(I, /obj/item/stack/sheet/lessergem))
- var/obj/item/stack/sheet/lessergem/LG = I
- if(lesser_gem_cost)
- var/spend = min(lesser_gem_cost, LG.amount)
- user << "You add [spend] lesser gems to \the [src]."
- lesser_gem_cost = max(0, lesser_gem_cost - spend)
- LG.use(spend)
- check_completion()
- else
- user << "\The [src] does not require any more lesser gems!"
- return
-
- if(istype(I, /obj/item/stack/sheet/greatergem))
- var/obj/item/stack/sheet/greatergem/GG = I //GG!
- if(greater_gem_cost)
- var/spend = min(greater_gem_cost, GG.amount)
- user << "You add [spend] greater gems to \the [src]."
- greater_gem_cost = max(0, greater_gem_cost - spend)
- GG.use(spend)
- check_completion()
- else
- user << "\The [src] does not require any more greater gems!"
- return
-
- else
- return ..()
-
-
-/obj/structure/divine/construction_holder/proc/check_completion()
- if(!metal_cost && !glass_cost && !lesser_gem_cost && !greater_gem_cost)
- visible_message("\The [initial(construction_result.name)] is complete!")
- var/obj/structure/divine/D = new construction_result (get_turf(src))
- D.assign_deity(deity)
- qdel(src)
-
-
-/obj/structure/divine/construction_holder/examine(mob/user)
- ..()
-
- if(metal_cost || glass_cost || lesser_gem_cost || greater_gem_cost)
- user << "To finish construction it requires the following materials:"
- if(metal_cost)
- user << "[metal_cost] metal "
- if(glass_cost)
- user << "[glass_cost] glass
"
- if(lesser_gem_cost)
- user << "[lesser_gem_cost] lesser gems
"
- if(greater_gem_cost)
- user << "[greater_gem_cost] greater gems
"
-
-
-/obj/structure/divine/nexus
- name = "nexus"
- desc = "It anchors a deity to this world. It radiates an unusual aura. Cultists protect this at all costs. It looks well protected from explosive shock."
- icon_state = "nexus"
- health = 500
- maxhealth = 500
- constructable = FALSE
- var/faith_regen_rate = 1
- var/list/powerpylons = list()
-
-
-/obj/structure/divine/nexus/ex_act()
- return
-
-/obj/structure/divine/nexus/take_damage(damage, damage_type = BRUTE, sound_effect = 1)
- switch(damage_type)
- if(BRUTE)
- if(sound_effect)
- if(damage)
- playsound(loc, 'sound/weapons/smash.ogg', 50, 1)
- else
- playsound(loc, 'sound/weapons/tap.ogg', 50, 1)
- if(BURN)
- if(sound_effect)
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- else
- return
- health -= damage
- if(deity)
- deity.update_health_hud()
- if(!health)
- if(!qdeleted(deity) && deity.nexus_required)
- deity << "Your nexus was destroyed. You feel yourself fading..."
- qdel(deity)
- visible_message("\The [src] was destroyed!")
- qdel(src)
-
-
-/obj/structure/divine/nexus/New()
- START_PROCESSING(SSobj, src)
-
-
-/obj/structure/divine/nexus/process()
- if(deity)
- deity.update_followers()
- deity.add_faith(faith_regen_rate + (powerpylons.len / 5) + (deity.alive_followers / 3))
- deity.max_faith = initial(deity.max_faith) + (deity.alive_followers*10) //10 followers = 100 max faith, so disaster() at around 20 followers
- deity.check_death()
-
-
-/obj/structure/divine/nexus/Destroy()
- STOP_PROCESSING(SSobj, src)
- return ..()
-
-
-/obj/structure/divine/conduit
- name = "conduit"
- desc = "It allows a deity to extend their reach. Their powers are just as potent near a conduit as a nexus."
- icon_state = "conduit"
- health = 150
- maxhealth = 150
- metal_cost = 10
- glass_cost = 5
-
-
-/obj/structure/divine/conduit/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE)
- if(deity)
- deity.conduits -= src
- ..()
- if(deity)
- deity.conduits += src
-
-/obj/structure/divine/conduit/deactivate()
- ..()
- if(deity)
- deity.conduits -= src
-
-/obj/structure/divine/conduit/activate()
- ..()
- if(deity)
- deity.conduits += src
-
-/* //No good sprites, and not enough items to make it viable yet
-/obj/structure/divine/forge
- name = "forge"
- desc = "A forge fueled by divine might, it allows the creation of sacred and powerful artifacts. It requires common materials to craft objects."
- icon_state = "forge"
- health = 250
- maxhealth = 250
- density = 0
- maxhealth = 250
- metal_cost = 40
-*/
-
-/obj/structure/divine/convertaltar
- name = "conversion altar"
- desc = "An altar dedicated to a deity. Cultists can \"forcefully teach\" their non-aligned crewmembers to join their side and take up their deity."
- icon_state = "convertaltar"
- density = 0
- metal_cost = 10
- can_buckle = 1
-
-
-/obj/structure/divine/convertaltar/attack_hand(mob/living/user)
- ..()
- if(deactivated)
- return
- var/mob/living/carbon/human/H = locate() in get_turf(src)
- if(!is_handofgod_cultist(user))
- user << "You try to use it, but unfortunately you don't know any rituals."
- return
- if(!H)
- return
- if(!H.mind)
- user << "Only sentients may serve your deity."
- return
- if((side == "red" && is_handofgod_redcultist(user) && !is_handofgod_redcultist(H)) || (side == "blue" && is_handofgod_bluecultist(user) && !is_handofgod_bluecultist(H)))
- user << "You invoke the conversion ritual."
- ticker.mode.add_hog_follower(H.mind, side)
- else
- user << "You invoke the conversion ritual."
- user << "But the altar ignores your words..."
-
-
-/obj/structure/divine/sacrificealtar
- name = "sacrificial altar"
- desc = "An altar designed to perform blood sacrifice for a deity. The cultists performing the sacrifice will gain a powerful material to use in their forge. Sacrificing a prophet will yield even better results."
- icon_state = "sacrificealtar"
- density = 0
- metal_cost = 15
- can_buckle = 1
-
-
-/obj/structure/divine/sacrificealtar/attack_hand(mob/living/user)
- ..()
- if(deactivated)
- return
- var/mob/living/L = locate() in get_turf(src)
- if(!is_handofgod_cultist(user))
- user << "You try to use it, but unfortunately you don't know any rituals."
- return
- if(!L)
- return
- if((side == "red" && is_handofgod_redcultist(user)) || (side == "blue" && is_handofgod_bluecultist(user)))
- if((side == "red" && is_handofgod_redcultist(L)) || (side == "blue" && is_handofgod_bluecultist(L)))
- user << "You cannot sacrifice a fellow cultist."
- return
- user << "You attempt to sacrifice [L] by invoking the sacrificial ritual."
- sacrifice(L)
- else
- user << "You attempt to sacrifice [L] by invoking the sacrificial ritual."
- user << "But the altar ignores your words..."
-
-
-/obj/structure/divine/sacrificealtar/proc/sacrifice(mob/living/L)
- if(!L)
- L = locate() in get_turf(src)
- if(L)
- if(ismonkey(L))
- var/luck = rand(1,4)
- if(luck > 3)
- new /obj/item/stack/sheet/lessergem(get_turf(src))
-
- else if(ishuman(L))
- var/mob/living/carbon/human/H = L
-
- //Sacrifice altars can't teamkill
- if(side == "red" && is_handofgod_redcultist(H))
- return
- else if(side == "blue" && is_handofgod_bluecultist(H))
- return
-
- if(is_handofgod_prophet(H))
- new /obj/item/stack/sheet/greatergem(get_turf(src))
- if(deity)
- deity.prophets_sacrificed_in_name++
- else
- new /obj/item/stack/sheet/lessergem(get_turf(src))
-
- else if(isAI(L) || istype(L, /mob/living/carbon/alien/humanoid/royal/queen))
- new /obj/item/stack/sheet/greatergem(get_turf(src))
- else
- new /obj/item/stack/sheet/lessergem(get_turf(src))
- L.gib()
-
-
-/obj/structure/divine/healingfountain
- name = "healing fountain"
- desc = "A fountain containing the waters of life... or death, depending on where your allegiances lie."
- icon_state = "fountain"
- metal_cost = 10
- glass_cost = 5
- autocolours = FALSE
- var/time_between_uses = 1800
- var/last_process = 0
- var/cult_only = TRUE
-
-/obj/structure/divine/healingfountain/anyone
- desc = "A fountain containing the waters of life."
- cult_only = FALSE
-
-/obj/structure/divine/healingfountain/attack_hand(mob/living/user)
- if(deactivated)
- return
- if(last_process + time_between_uses > world.time)
- user << "The fountain appears to be empty."
- return
- last_process = world.time
- if(!is_handofgod_cultist(user) && cult_only)
- user << "The water burns!"
- user.reagents.add_reagent("hell_water",20)
- else
- user << "The water feels warm and soothing as you touch it. The fountain immediately dries up shortly afterwards."
- user.reagents.add_reagent("godblood",20)
- update_icons()
- addtimer(src, "update_icons", time_between_uses)
-
-
-/obj/structure/divine/healingfountain/update_icons()
- if(last_process + time_between_uses > world.time)
- icon_state = "fountain"
- else
- icon_state = "fountain-[side]"
-
-
-/obj/structure/divine/powerpylon
- name = "power pylon"
- desc = "A pylon which increases the deity's rate it can influence the world."
- icon_state = "powerpylon"
- density = 1
- health = 30
- maxhealth = 30
- metal_cost = 5
- glass_cost = 15
-
-
-/obj/structure/divine/powerpylon/New()
- ..()
- if(deity && deity.god_nexus)
- deity.god_nexus.powerpylons += src
-
-
-/obj/structure/divine/powerpylon/Destroy()
- if(deity && deity.god_nexus)
- deity.god_nexus.powerpylons -= src
- return ..()
-
-
-/obj/structure/divine/powerpylon/deactivate()
- ..()
- if(deity)
- deity.god_nexus.powerpylons -= src
-
-/obj/structure/divine/powerpylon/activate()
- ..()
- if(deity)
- deity.god_nexus.powerpylons += src
-
-/obj/structure/divine/defensepylon
- name = "defense pylon"
- desc = "A pylon which is blessed to withstand many blows, and fire strong bolts at nonbelievers. A god can toggle it."
- icon_state = "defensepylon"
- health = 150
- maxhealth = 150
- metal_cost = 25
- glass_cost = 30
- var/obj/machinery/porta_turret/defensepylon_internal_turret/pylon_gun
-
-
-/obj/structure/divine/defensepylon/New()
- ..()
- pylon_gun = new(src)
- pylon_gun.base = src
- pylon_gun.faction = list("[side] god")
-
-
-/obj/structure/divine/defensepylon/Destroy()
- qdel(pylon_gun) //just in case
- return ..()
-
-
-/obj/structure/divine/defensepylon/examine(mob/user)
- ..()
- user << "\The [src] looks [pylon_gun.on ? "on" : "off"]."
-
-
-/obj/structure/divine/defensepylon/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE)
- if(..() && pylon_gun)
- pylon_gun.faction = list("[side] god")
- pylon_gun.side = side
-
-/obj/structure/divine/defensepylon/attack_god(mob/camera/god/user)
- if(user.side == side)
- if(deactivated)
- user << "You need to reveal it first!"
- return
- pylon_gun.on = !pylon_gun.on
- icon_state = (pylon_gun.on) ? "defensepylon-[side]" : "defensepylon"
-
-/obj/structure/divine/defensepylon/deactivate()
- ..()
- pylon_gun.on = 0
- icon_state = (pylon_gun.on) ? "defensepylon-[side]" : "defensepylon"
-
-/obj/structure/divine/defensepylon/activate()
- ..()
- pylon_gun.on = 1
- icon_state = (pylon_gun.on) ? "defensepylon-[side]" : "defensepylon"
-
-//This sits inside the defensepylon, to avoid copypasta
-/obj/machinery/porta_turret/defensepylon_internal_turret
- name = "defense pylon"
- desc = "A plyon which is blessed to withstand many blows, and fire strong bolts at nonbelievers."
- icon = 'icons/obj/hand_of_god_structures.dmi'
- installation = null
- always_up = 1
- use_power = 0
- has_cover = 0
- health = 200
- projectile = /obj/item/projectile/beam/pylon_bolt
- eprojectile = /obj/item/projectile/beam/pylon_bolt
- shot_sound = 'sound/weapons/emitter2.ogg'
- eshot_sound = 'sound/weapons/emitter2.ogg'
- base_icon_state = "defensepylon"
- active_state = ""
- off_state = ""
- faction = null
- emp_vunerable = 0
- var/side = "neutral"
-
-/obj/machinery/porta_turret/defensepylon_internal_turret/setup()
- return
-
-/obj/machinery/porta_turret/defensepylon_internal_turret/shootAt(atom/movable/target)
- var/obj/item/projectile/A = ..()
- if(A)
- A.color = side
-
-/obj/machinery/porta_turret/defensepylon_internal_turret/assess_perp(mob/living/carbon/human/perp)
- if(perp.handcuffed) //dishonourable to kill somebody who might be converted.
- return 0
- var/badtarget = 0
- switch(side)
- if("blue")
- badtarget = is_handofgod_bluecultist(perp)
- if("red")
- badtarget = is_handofgod_redcultist(perp)
- else
- badtarget = 1
- if(badtarget)
- return 0
- return 10
-
-
-
-/obj/item/projectile/beam/pylon_bolt
- name = "divine bolt"
- icon_state = "greyscale_bolt"
- damage = 15
-
-
-/obj/structure/divine/shrine
- name = "shrine"
- desc = "A shrine dedicated to a deity."
- icon_state = "shrine"
- metal_cost = 15
- glass_cost = 15
-
-
-/obj/structure/divine/shrine/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE)
- if(..())
- name = "shrine to [new_deity.name]"
- desc = "A shrine dedicated to [new_deity.name]"
-
-
-
-
-//Functional, but need sprites
-/*
-/obj/structure/divine/translocator
- name = "translocator"
- desc = "A powerful structure, made with a greater gem. It allows a deity to move their nexus to where this stands"
- icon_state = "translocator"
- health = 100
- maxhealth = 100
- metal_cost = 20
- glass_cost = 20
- greater_gem_cost = 1
-
-
-/obj/structure/divine/lazarusaltar
- name = "lazarus altar"
- desc = "A very powerful altar capable of bringing life back to the recently deceased, made with a greater gem. It can revive anyone and will heal virtually all wounds, but they are but a shell of their former self."
- icon_state = "lazarusaltar"
- density = 0
- health = 100
- maxhealth = 100
- metal_cost = 20
- greater_gem_cost = 1
-
-
-/obj/structure/divine/lazarusaltar/attack_hand(mob/living/user)
- var/mob/living/L = locate() in get_turf(src)
- if(!is_handofgod_culstist(user))
- user << "You try to use it, but unfortunately you don't know any rituals."
- return
- if(!L)
- return
-
- if((side == "red" && is_handofgod_redcultist(user))) || (side == "blue" && is_handofgod_bluecultist(user)))
- user << "You attempt to revive [L] by invoking the rebirth ritual."
- L.revive()
- L.adjustCloneLoss(50)
- L.adjustStaminaLoss(100)
- else
- user << "You attempt to revive [L] by invoking the rebirth ritual."
- user << "But the altar ignores your words..."
-*/
-
-
diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
index 116d910e056..55a703913be 100644
--- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
+++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
@@ -50,11 +50,10 @@
if(disguise == null)
return
stealth_active = 1
- if(istype(src.loc, /mob/living/carbon/human))
- var/mob/living/carbon/human/M = src.loc
- addtimer(GLOBAL_PROC, "anim", 0, FALSE, M.loc, M, 'icons/mob/mob.dmi',
- null, "cloak", null, M.dir)
-
+ if(istype(loc, /mob/living/carbon/human))
+ var/mob/living/carbon/human/M = loc
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja/cloak,
+ list(get_turf(M), M.dir))
M.name_override = disguise.name
M.icon = disguise.icon
M.icon_state = disguise.icon_state
@@ -65,10 +64,10 @@
if(!stealth_active)
return
stealth_active = 0
- if(istype(src.loc, /mob/living/carbon/human))
- var/mob/living/carbon/human/M = src.loc
- addtimer(GLOBAL_PROC, "anim", 0, FALSE, M.loc, M, 'icons/mob/mob.dmi',
- null, "uncloak", null, M.dir)
+ if(istype(loc, /mob/living/carbon/human))
+ var/mob/living/carbon/human/M = loc
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja,
+ list(get_turf(M), M.dir))
M.name_override = null
M.cut_overlays()
M.regenerate_icons()
@@ -92,11 +91,11 @@
ActivateStealth()
/obj/item/clothing/suit/armor/abductor/vest/proc/Adrenaline()
- if(istype(src.loc, /mob/living/carbon/human))
+ if(istype(loc, /mob/living/carbon/human))
if(combat_cooldown != initial(combat_cooldown))
- src.loc << "Combat injection is still recharging."
+ loc << "Combat injection is still recharging."
return
- var/mob/living/carbon/human/M = src.loc
+ var/mob/living/carbon/human/M = loc
M.adjustStaminaLoss(-75)
M.SetParalysis(0)
M.SetStunned(0)
diff --git a/code/game/gamemodes/miniantags/revenant/revenant_blight.dm b/code/game/gamemodes/miniantags/revenant/revenant_blight.dm
index 19cb12d0205..9133fa69c22 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant_blight.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant_blight.dm
@@ -14,9 +14,11 @@
severity = BIOHAZARD
var/stagedamage = 0 //Highest stage reached.
var/finalstage = 0 //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects.
+ var/old_color = ""
/datum/disease/revblight/cure()
if(affected_mob)
+ affected_mob.color = old_color
affected_mob << "You feel better."
if(affected_mob.dna && affected_mob.dna.species)
affected_mob.dna.species.handle_mutant_bodyparts(affected_mob)
@@ -58,11 +60,8 @@
affected_mob.dna.species.handle_mutant_bodyparts(affected_mob,"#1d2953")
affected_mob.dna.species.handle_hair(affected_mob,"#1d2953")
affected_mob.visible_message("[affected_mob] looks terrifyingly gaunt...", "You suddenly feel like your skin is wrong...")
- var/old_color = affected_mob.color
+ old_color = affected_mob.color
affected_mob.color = "#1d2953"
- spawn(100)
- if(affected_mob)
- affected_mob = old_color
- cure()
+ addtimer(src, "cure", 100, FALSE)
else
- return
\ No newline at end of file
+ return
diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
index f63dfae041e..2ac221435fc 100644
--- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm
+++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
@@ -63,6 +63,7 @@
icon = 'icons/obj/surgery.dmi'
name = "pile of viscera"
desc = "A repulsive pile of guts and gore."
+ gender = NEUTER
random_icon_states = list("innards")
/mob/living/simple_animal/slaughter/phasein()
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 98d0f963433..e0d0fdb3d00 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -91,7 +91,7 @@ var/bomb_set
if (istype(I, /obj/item/weapon/disk/nuclear))
if(!user.drop_item())
return
- I.loc = src
+ I.forceMove(src)
auth = I
add_fingerprint(user)
return
@@ -496,6 +496,20 @@ This is here to make the tiles around the station mininuke change when it's arme
poi_list |= src
START_PROCESSING(SSobj, src)
+/obj/item/weapon/disk/nuclear/attackby(obj/item/I, mob/living/user, params)
+ if(istype(I, /obj/item/weapon/claymore/highlander))
+ var/obj/item/weapon/claymore/highlander/H = I
+ if(H.nuke_disk)
+ user << "Wait... what?"
+ qdel(H.nuke_disk)
+ H.nuke_disk = null
+ return
+ user.visible_message("[user] captures [src]!", "You've got the disk! Defend it with your life!")
+ loc = H
+ H.nuke_disk = src
+ return 1
+ return ..()
+
/obj/item/weapon/disk/nuclear/suicide_act(mob/user)
user.visible_message("[user] is \
going delta! It looks like they're comitting suicide.")
diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm
index e9c0e194255..0cb14a1f13d 100644
--- a/code/game/gamemodes/wizard/soulstone.dm
+++ b/code/game/gamemodes/wizard/soulstone.dm
@@ -251,7 +251,7 @@
break
if(!chosen_ghost) //Failing that, we grab a ghost
- var/list/consenting_candidates = pollCandidates("Would you like to play as a Shade?", "Cultist", null, ROLE_CULTIST, poll_time = 100)
+ var/list/consenting_candidates = pollCandidates("Would you like to play as a Shade?", "Cultist", null, ROLE_CULTIST, poll_time = 50)
if(consenting_candidates.len)
chosen_ghost = pick(consenting_candidates)
if(!T)
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index 866daf1fbe1..e66248b0a9a 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -19,7 +19,10 @@
..(location)
if(C && istype(C))
circuit = C
- else if(circuit)
+ //Some machines, oldcode arcades mostly, new themselves, so circuit
+ //can already be an instance of a type and trying to new that will
+ //cause a runtime
+ else if(ispath(circuit))
circuit = new circuit(null)
power_change()
update_icon()
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 5c4c0435d3f..50edc96d054 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -346,17 +346,12 @@
/obj/machinery/door/window/clockwork/New(loc, set_dir)
..()
- if(set_dir)
- var/obj/effect/E = PoolOrNew(/obj/effect/overlay/temp/ratvar/door/window, get_turf(src))
- setDir(set_dir)
- E.setDir(set_dir)
- made_glow = TRUE
- debris += new/obj/item/stack/sheet/brass(src)
+ debris += new/obj/item/stack/sheet/brass(src, 2)
change_construction_value(2)
/obj/machinery/door/window/clockwork/setDir(direct)
if(!made_glow)
- var/obj/effect/E = PoolOrNew(/obj/effect/overlay/temp/ratvar/window/single, get_turf(src))
+ var/obj/effect/E = PoolOrNew(/obj/effect/overlay/temp/ratvar/door/window, get_turf(src))
E.setDir(direct)
made_glow = TRUE
..()
diff --git a/code/game/machinery/limbgrower.dm b/code/game/machinery/limbgrower.dm
new file mode 100644
index 00000000000..14c8415adf8
--- /dev/null
+++ b/code/game/machinery/limbgrower.dm
@@ -0,0 +1,238 @@
+#define LIMBGROWER_MAIN_MENU 1
+#define LIMBGROWER_CATEGORY_MENU 2
+#define LIMBGROWER_CHEMICAL_MENU 3
+//use these for the menu system
+
+
+/obj/machinery/limbgrower
+ name = "limb grower"
+ desc = "It grows new limbs using Synthflesh."
+ icon = 'icons/obj/machines/limbgrower.dmi'
+ icon_state = "limbgrower_idleoff"
+ density = 1
+ flags = OPENCONTAINER
+
+ var/operating = 0
+ anchored = 1
+ use_power = 1
+ var/disabled = 0
+ idle_power_usage = 10
+ active_power_usage = 100
+ var/busy = 0
+ var/prod_coeff = 1
+
+ var/datum/design/being_built
+ var/datum/research/files
+ var/selected_category
+ var/screen = 1
+ var/emag = FALSE //Gives access to other cool stuff
+
+ var/list/categories = list(
+ "human",
+ "lizard",
+ "plasmaman",
+ "special"
+ )
+
+/obj/machinery/limbgrower/New()
+ ..()
+ create_reagents(0)
+ var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/limbgrower(null)
+ B.apply_default_parts(src)
+ files = new /datum/research/limbgrower(src)
+
+/obj/item/weapon/circuitboard/machine/limbgrower
+ name = "circuit board (Limb Grower)"
+ build_path = /obj/machinery/limbgrower
+ origin_tech = "programming=2;biotech=2"
+ req_components = list(
+ /obj/item/weapon/stock_parts/manipulator = 1,
+ /obj/item/weapon/reagent_containers/glass/beaker = 2,
+ /obj/item/weapon/stock_parts/console_screen = 1)
+
+/obj/machinery/limbgrower/interact(mob/user)
+ if(!is_operational())
+ return
+
+ var/dat = main_win(user)
+
+ switch(screen)
+ if(LIMBGROWER_MAIN_MENU)
+ dat = main_win(user)
+ if(LIMBGROWER_CATEGORY_MENU)
+ dat = category_win(user,selected_category)
+ if(LIMBGROWER_CHEMICAL_MENU)
+ dat = chemical_win(user)
+
+ var/datum/browser/popup = new(user, "Limb Grower", name, 400, 500)
+ popup.set_content(dat)
+ popup.open()
+
+/obj/machinery/limbgrower/deconstruction()
+ for(var/obj/item/weapon/reagent_containers/glass/G in component_parts)
+ reagents.trans_to(G, G.reagents.maximum_volume)
+
+/obj/machinery/limbgrower/attackby(obj/item/O, mob/user, params)
+ if (busy)
+ user << "The Limb Grower is busy. Please wait for completion of previous operation."
+ return
+
+ if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", O))
+ updateUsrDialog()
+ return
+
+ if(exchange_parts(user, O))
+ return
+
+ if(panel_open && default_deconstruction_crowbar(O))
+ return
+
+ if(user.a_intent == "harm") //so we can hit the machine
+ return ..()
+
+/obj/machinery/limbgrower/Topic(href, href_list)
+ if(..())
+ return
+ if (!busy)
+ if(href_list["menu"])
+ screen = text2num(href_list["menu"])
+
+ if(href_list["category"])
+ selected_category = href_list["category"]
+
+ if(href_list["disposeI"]) //Get rid of a reagent incase you add the wrong one by mistake
+ reagents.del_reagent(href_list["disposeI"])
+
+ if(href_list["make"])
+
+ /////////////////
+ //href protection
+ being_built = files.FindDesignByID(href_list["make"]) //check if it's a valid design
+ if(!being_built)
+ return
+
+
+ var/synth_cost = being_built.reagents["synthflesh"]*prod_coeff
+ var/power = max(2000, synth_cost/5)
+
+ if(reagents.has_reagent("synthflesh", being_built.reagents["synthflesh"]*prod_coeff))
+ busy = 1
+ use_power(power)
+ flick("limbgrower_fill",src)
+ icon_state = "limbgrower_idleon"
+ addtimer(src, "build_item",32*prod_coeff)
+
+ else
+ usr << "The limb grower is busy. Please wait for completion of previous operation."
+
+ updateUsrDialog()
+ return
+
+/obj/machinery/limbgrower/proc/build_item()
+ if(reagents.has_reagent("synthflesh", being_built.reagents["synthflesh"]*prod_coeff)) //sanity check, if this happens we are in big trouble
+ reagents.remove_reagent("synthflesh",being_built.reagents["synthflesh"]*prod_coeff)
+ var/buildpath = being_built.build_path
+ if(ispath(buildpath, /obj/item/bodypart)) //This feels like spatgheti code, but i need to initilise a limb somehow
+ build_limb(buildpath)
+ else
+ //Just build whatever it is
+ new buildpath(loc)
+ else
+ src.visible_message(" Something went very wrong and there isnt enough synthflesh anymore!")
+ busy = 0
+ flick("limbgrower_unfill",src)
+ icon_state = "limbgrower_idleoff"
+ updateUsrDialog()
+
+/obj/machinery/limbgrower/proc/build_limb(buildpath)
+ //i need to create a body part manually using a set icon (otherwise it doesnt appear)
+ var/obj/item/bodypart/limb
+ limb = new buildpath(loc)
+ if(selected_category=="human" || selected_category=="lizard") // Doing this because plasmamen have their limbs in a different icon file
+ limb.icon = 'icons/mob/human_parts_greyscale.dmi'
+ else
+ limb.icon = 'icons/mob/human_parts.dmi'
+ // Set this limb up using the specias name and body zone
+ limb.icon_state = "[selected_category]_[limb.body_zone]_s"
+ limb.name = "Synthetic [selected_category] [parse_zone(limb.body_zone)]"
+ limb.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]"
+
+/obj/machinery/limbgrower/RefreshParts()
+ reagents.maximum_volume = 0
+ for(var/obj/item/weapon/reagent_containers/glass/G in component_parts)
+ reagents.maximum_volume += G.volume
+ G.reagents.trans_to(src, G.reagents.total_volume)
+ var/T=1.2
+ for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
+ T -= M.rating*0.2
+ prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
+
+/obj/machinery/limbgrower/proc/main_win(mob/user)
+ var/dat = "
Limb Grower Menu:
"
+ dat += "Chemical Storage"
+ dat += materials_printout()
+ dat += ""
+
+ for(var/C in categories)
+ if(C=="special" && !emag) //Only want to show special when console is emagged
+ continue
+
+ dat += " [C] "
+ dat += ""
+ //one category per line
+
+ dat += " Browsing [selected_category]:
"
+ dat += materials_printout()
+
+ for(var/v in files.known_designs)
+ var/datum/design/D = files.known_designs[v]
+ if(!(selected_category in D.category))
+ continue
+ if(disabled || !can_build(D))
+ dat += "[D.name]"
+ else
+ dat += "[D.name]"
+ dat += "[get_design_cost(D)]
"
+
+ dat += "Browsing Chemical Storage:
"
+ dat += materials_printout()
+
+ for(var/datum/reagent/R in reagents.reagent_list)
+ dat += "[R.name]: [R.volume]"
+ dat += "Purge
"
+
+ dat += "
"
+ return dat
+
+/obj/machinery/limbgrower/proc/can_build(datum/design/D)
+ return (reagents.has_reagent("synthflesh", D.reagents["synthflesh"]*prod_coeff)) //Return whether the machine has enough synthflesh to produce the design
+
+/obj/machinery/limbgrower/proc/get_design_cost(datum/design/D)
+ var/dat
+ if(D.reagents["synthflesh"])
+ dat += "[D.reagents["synthflesh"] * prod_coeff] Synthetic flesh "
+ return dat
+
+/obj/machinery/limbgrower/emag_act(mob/user)
+ if(emag==TRUE)
+ return
+ for(var/datum/design/D in files.possible_designs)
+ if((D.build_type & LIMBGROWER) && ("special" in D.category))
+ files.AddDesign2Known(D)
+ user << "A warning flashes onto the screen, stating that safety overrides have been deactivated"
+ emag = TRUE
\ No newline at end of file
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 4203573df56..2b7232cfc6d 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -459,9 +459,9 @@ Class Procs:
. = 1
-/obj/machinery/tesla_act(var/power)
+/obj/machinery/tesla_act(power, explosive = FALSE)
..()
- if(prob(85))
+ if(prob(85) && explosive)
explosion(src.loc,1,2,4,flame_range = 2, adminlog = 0, smoke = 0)
else if(prob(50))
emp_act(2)
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index 8f24ecfc84d..5254b3b511f 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -132,8 +132,9 @@
if(istype(charging, /obj/item/device/modular_computer))
var/obj/item/device/modular_computer/C = charging
- if(C.battery_module)
- var/obj/item/weapon/computer_hardware/battery/B = C.battery_module
+ var/obj/item/weapon/computer_hardware/battery/battery_module = C.all_components[MC_CELL]
+ if(battery_module)
+ var/obj/item/weapon/computer_hardware/battery/B = battery_module
if(B.battery)
if(B.battery.charge < B.battery.maxcharge)
B.battery.give(B.battery.chargerate * recharge_coeff)
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index 0c66903dbfe..bdd9cb59616 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -337,13 +337,7 @@
/obj/item/weapon/bombcore/badmin/summon/detonate()
var/obj/machinery/syndicatebomb/B = src.loc
- for(var/i = 0; i < amt_summon; i++)
- var/atom/movable/X = new summon_path
- X.admin_spawned = TRUE
- X.loc = get_turf(src)
- if(prob(50))
- for(var/j = 1, j <= rand(1, 3), j++)
- step(X, pick(NORTH,SOUTH,EAST,WEST))
+ spawn_and_random_walk(summon_path, src, amt_summon, walk_chance=50, admin_spawn=TRUE)
qdel(B)
qdel(src)
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 95e8c2d397c..27278c10bb7 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -774,7 +774,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
/obj/item/weapon/storage/box/matches = 10,
/obj/item/weapon/lighter/greyscale = 4,
/obj/item/weapon/storage/fancy/rollingpapers = 5)
- contraband = list(/obj/item/weapon/lighter = 3)
+ contraband = list(/obj/item/weapon/lighter = 3, /obj/item/clothing/mask/vape = 5)
premium = list(/obj/item/weapon/storage/fancy/cigarettes/cigpack_robustgold = 3, \
/obj/item/weapon/storage/fancy/cigarettes/cigars = 1, /obj/item/weapon/storage/fancy/cigarettes/cigars/havana = 1, /obj/item/weapon/storage/fancy/cigarettes/cigars/cohiba = 1)
refill_canister = /obj/item/weapon/vending_refill/cigarette
@@ -909,7 +909,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
desc = "A kitchen and restaurant equipment vendor"
product_ads = "Mm, food stuffs!;Food and food accessories.;Get your plates!;You like forks?;I like forks.;Woo, utensils.;You don't really need these..."
icon_state = "dinnerware"
- products = list(/obj/item/weapon/storage/bag/tray = 8,/obj/item/weapon/kitchen/fork = 6,/obj/item/weapon/kitchen/knife = 6,/obj/item/weapon/kitchen/rollingpin = 2,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 8,/obj/item/clothing/suit/apron/chef = 2,/obj/item/weapon/reagent_containers/food/condiment/pack/ketchup = 5,/obj/item/weapon/reagent_containers/food/condiment/pack/hotsauce = 5,/obj/item/weapon/reagent_containers/food/condiment/saltshaker = 5,/obj/item/weapon/reagent_containers/food/condiment/peppermill = 5,/obj/item/weapon/reagent_containers/glass/bowl = 20,/obj/item/weapon/sharpener = 2)
+ products = list(/obj/item/weapon/storage/bag/tray = 8,/obj/item/weapon/kitchen/fork = 6,/obj/item/weapon/kitchen/knife = 6,/obj/item/weapon/kitchen/rollingpin = 2,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 8,/obj/item/clothing/suit/apron/chef = 2,/obj/item/weapon/reagent_containers/food/condiment/pack/ketchup = 5,/obj/item/weapon/reagent_containers/food/condiment/pack/hotsauce = 5,/obj/item/weapon/reagent_containers/food/condiment/saltshaker = 5,/obj/item/weapon/reagent_containers/food/condiment/peppermill = 5,/obj/item/weapon/reagent_containers/glass/bowl = 20)
contraband = list(/obj/item/weapon/kitchen/rollingpin = 2, /obj/item/weapon/kitchen/knife/butcher = 2)
/obj/machinery/vending/sovietsoda
@@ -1001,7 +1001,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
/obj/item/clothing/head/beanie/purple=1, /obj/item/clothing/head/beanie/yellow=1, /obj/item/clothing/head/beanie/orange=1, /obj/item/clothing/head/beanie/cyan=1, /obj/item/clothing/head/beanie/christmas=1,
/obj/item/clothing/head/beanie/striped=1, /obj/item/clothing/head/beanie/stripedred=1, /obj/item/clothing/head/beanie/stripedblue=1, /obj/item/clothing/head/beanie/stripedgreen=1,
/obj/item/clothing/suit/jacket/letterman_red=1)
- 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/weapon/storage/belt/fannypack/black=2,/obj/item/clothing/suit/jacket/letterman_syndie=1,/obj/item/clothing/under/jabroni=1)
+ 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/weapon/storage/belt/fannypack/black=2,/obj/item/clothing/suit/jacket/letterman_syndie=1,/obj/item/clothing/under/jabroni=1, /obj/item/clothing/suit/vapeshirt=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/suit/jacket/leather/overcoat=1,/obj/item/clothing/under/pants/mustangjeans=1,/obj/item/clothing/tie/dope_necklace=3,/obj/item/clothing/suit/jacket/letterman_nanotrasen=1)
refill_canister = /obj/item/weapon/vending_refill/clothing
diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm
index 7043e0bf508..438c868d041 100644
--- a/code/game/mecha/mecha_defense.dm
+++ b/code/game/mecha/mecha_defense.dm
@@ -9,7 +9,7 @@
return 1 //always return non-0
-/obj/mecha/proc/take_damage(amount, type="brute", booster_deflection_modifier = 1, booster_damage_modifier = 1)
+/obj/mecha/proc/take_damage(amount, type="brute", booster_deflection_modifier = 1, booster_damage_modifier = 1, send_message = 1)
if(prob(deflect_chance * booster_deflection_modifier))
visible_message("[src]'s armour deflects the attack!")
log_append_to_last("Armor saved.")
@@ -19,18 +19,19 @@
damage = damage * booster_damage_modifier
health -= damage
update_health()
- occupant_message("Taking damage!")
+ if(send_message)
+ occupant_message("Taking damage!")
log_append_to_last("Took [damage] points of damage. Damage type: \"[type]\".",1)
return 1
-/obj/mecha/proc/take_directional_damage(amount, type="brute", adir = 0, booster_deflection_modifier = 1, booster_damage_modifier = 1)
+/obj/mecha/proc/take_directional_damage(amount, type="brute", adir = 0, booster_deflection_modifier = 1, booster_damage_modifier = 1, send_message = 1)
var/facing_modifier = get_armour_facing(dir2angle(adir) - dir2angle(src))
booster_damage_modifier /= facing_modifier
booster_deflection_modifier *= facing_modifier
- return take_damage(amount, type, booster_deflection_modifier, booster_damage_modifier)
+ return take_damage(amount, type, booster_deflection_modifier, booster_damage_modifier, send_message)
/obj/mecha/proc/absorbDamage(damage,damage_type)
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index 4924c0470de..0b6b6cae361 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -2,7 +2,9 @@
desc = "Autonomous Power Loader Unit. This newer model is refitted with powerful armour against the dangers of the EVA mining process."
name = "\improper APLU \"Ripley\""
icon_state = "ripley"
- step_in = 5
+ step_in = 4 //Move speed, lower is faster.
+ var/hi_pres_step_in = 4 //step_in while in high pressure.
+ var/lo_pres_step_in = 2 //step_in while in low/zero pressure.
max_temperature = 20000
health = 200
lights_power = 7
@@ -72,7 +74,7 @@
desc = "OH SHIT IT'S THE DEATHSQUAD WE'RE ALL GONNA DIE"
name = "\improper DEATH-RIPLEY"
icon_state = "deathripley"
- step_in = 3
+ hi_pres_step_in = 3
opacity=0
lights_power = 7
wreckage = /obj/structure/mecha_wreckage/ripley/deathripley
@@ -150,11 +152,11 @@
var/pressure = environment.return_pressure()
if(pressure < 40)
- step_in = 3
+ step_in = lo_pres_step_in
for(var/obj/item/mecha_parts/mecha_equipment/drill/drill in equipment)
drill.equip_cooldown = initial(drill.equip_cooldown)/2
else
- step_in = 5
+ step_in = hi_pres_step_in
for(var/obj/item/mecha_parts/mecha_equipment/drill/drill in equipment)
drill.equip_cooldown = initial(drill.equip_cooldown)
diff --git a/code/game/objects/effects/decals/Cleanable/aliens.dm b/code/game/objects/effects/decals/Cleanable/aliens.dm
index a0e5d4a3dc3..b7824b43a97 100644
--- a/code/game/objects/effects/decals/Cleanable/aliens.dm
+++ b/code/game/objects/effects/decals/Cleanable/aliens.dm
@@ -3,9 +3,6 @@
/obj/effect/decal/cleanable/xenoblood
name = "xeno blood"
desc = "It's green and acidic. It looks like... blood?"
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "xfloor1"
random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
@@ -43,9 +40,9 @@
/obj/effect/decal/cleanable/xenoblood/xgibs
name = "xeno gibs"
desc = "Gnarly..."
- gender = PLURAL
icon = 'icons/effects/blood.dmi'
icon_state = "xgib1"
+ layer = LOW_OBJ_LAYER
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6")
/obj/effect/decal/cleanable/xenoblood/xgibs/ex_act()
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index 916bd7d2cf3..688ddf506e1 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -1,9 +1,6 @@
/obj/effect/decal/cleanable/blood
name = "blood"
desc = "It's red and gooey. Perhaps it's the chef's cooking?"
- gender = PLURAL
- density = 0
- layer = ABOVE_NORMAL_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "floor1"
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
@@ -29,16 +26,12 @@
/obj/effect/decal/cleanable/blood/tracks
icon_state = "tracks"
desc = "They look like tracks left by wheels."
- gender = PLURAL
random_icon_states = null
/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose
name = "blood"
icon_state = "ltrails_1"
desc = "Your instincts say you shouldn't be following these."
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
random_icon_states = null
var/list/existing_dirs = list()
blood_DNA = list()
@@ -51,11 +44,9 @@
/obj/effect/decal/cleanable/blood/gibs
name = "gibs"
desc = "They look bloody and gruesome."
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "gibbl5"
+ layer = LOW_OBJ_LAYER
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
/obj/effect/decal/cleanable/blood/gibs/New()
@@ -108,7 +99,6 @@
/obj/effect/decal/cleanable/blood/drip
name = "drips of blood"
desc = "It's red."
- gender = PLURAL
icon_state = "1"
random_icon_states = list("drip1","drip2","drip3","drip4","drip5")
bloodiness = 0
@@ -125,7 +115,6 @@
icon = 'icons/effects/footprints.dmi'
icon_state = "nothingwhatsoever"
desc = "where might they lead?"
- gender = PLURAL
random_icon_states = null
var/entered_dirs = 0
var/exited_dirs = 0
diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm
index ebf8ab3f8c5..5e460de0b80 100644
--- a/code/game/objects/effects/decals/Cleanable/misc.dm
+++ b/code/game/objects/effects/decals/Cleanable/misc.dm
@@ -1,16 +1,12 @@
/obj/effect/decal/cleanable/generic
name = "clutter"
desc = "Someone should clean that up."
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/obj/objects.dmi'
icon_state = "shards"
/obj/effect/decal/cleanable/ash
name = "ashes"
desc = "Ashes to ashes, dust to dust, and into space."
- gender = PLURAL
icon = 'icons/obj/objects.dmi'
icon_state = "ash"
@@ -24,25 +20,16 @@
name = "dirt"
desc = "Someone should clean that up."
icon_state = "dirt"
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
mouse_opacity = 0
/obj/effect/decal/cleanable/flour
name = "flour"
desc = "It's still good. Four second rule!"
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon_state = "flour"
/obj/effect/decal/cleanable/greenglow
name = "glowing goo"
desc = "Jeez. I hope that's not for lunch."
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
luminosity = 1
icon_state = "greenglow"
@@ -52,36 +39,34 @@
/obj/effect/decal/cleanable/cobweb
name = "cobweb"
desc = "Somebody should remove that."
- density = 0
- layer = OBJ_LAYER
+ gender = NEUTER
+ layer = WALL_OBJ_LAYER
icon_state = "cobweb1"
- burntime = 1
/obj/effect/decal/cleanable/cobweb/fire_act()
qdel(src)
+/obj/effect/decal/cleanable/cobweb2
+ name = "cobweb"
+ desc = "Somebody should remove that."
+ gender = NEUTER
+ layer = WALL_OBJ_LAYER
+ icon_state = "cobweb2"
+
+/obj/effect/decal/cleanable/cobweb2/fire_act()
+ qdel(src)
+
/obj/effect/decal/cleanable/molten_item
name = "gooey grey mass"
desc = "It looks like a melted... something."
- density = 0
- layer = OBJ_LAYER
+ gender = NEUTER
icon = 'icons/obj/chemical.dmi'
icon_state = "molten"
-/obj/effect/decal/cleanable/cobweb2
- name = "cobweb"
- desc = "Somebody should remove that."
- density = 0
- layer = OBJ_LAYER
- icon_state = "cobweb2"
-
//Vomit (sorry)
/obj/effect/decal/cleanable/vomit
name = "vomit"
desc = "Gosh, how unpleasant."
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "vomit_1"
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
@@ -112,38 +97,34 @@
/obj/effect/decal/cleanable/tomato_smudge
name = "tomato smudge"
desc = "It's red."
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
+ gender = NEUTER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3")
/obj/effect/decal/cleanable/plant_smudge
name = "plant smudge"
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
+ gender = NEUTER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_plant")
/obj/effect/decal/cleanable/egg_smudge
name = "smashed egg"
desc = "Seems like this one won't hatch."
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
+ gender = NEUTER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_egg1", "smashed_egg2", "smashed_egg3")
/obj/effect/decal/cleanable/pie_smudge //honk
name = "smashed pie"
desc = "It's pie cream from a cream pie."
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
+ gender = NEUTER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_pie")
/obj/effect/decal/cleanable/chem_pile
name = "chemical pile"
desc = "A pile of chemicals. You can't quite tell what's inside it."
- gender = PLURAL
+ gender = NEUTER
icon = 'icons/obj/objects.dmi'
icon_state = "ash"
@@ -152,8 +133,6 @@
desc = "The shredded remains of what appears to be clothing."
icon_state = "shreds"
gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
/obj/effect/decal/cleanable/shreds/New()
pixel_x = rand(-5, 5)
@@ -165,3 +144,4 @@
desc = "A sizable pile of table salt. Someone must be upset."
icon = 'icons/effects/tomatodecal.dmi'
icon_state = "salt_pile"
+ gender = NEUTER
diff --git a/code/game/objects/effects/decals/Cleanable/robots.dm b/code/game/objects/effects/decals/Cleanable/robots.dm
index 7c0666a0c6e..30cd95d3a9e 100644
--- a/code/game/objects/effects/decals/Cleanable/robots.dm
+++ b/code/game/objects/effects/decals/Cleanable/robots.dm
@@ -3,11 +3,9 @@
/obj/effect/decal/cleanable/robot_debris
name = "robot debris"
desc = "It's a useless heap of junk... or is it?"
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/mob/robots.dmi'
icon_state = "gib1"
+ layer = LOW_OBJ_LAYER
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7")
blood_state = BLOOD_STATE_OIL
bloodiness = MAX_SHOE_BLOODINESS
@@ -45,9 +43,6 @@
/obj/effect/decal/cleanable/oil
name = "motor oil"
desc = "It's black and greasy. Looks like Beepsky made another mess."
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/mob/robots.dmi'
icon_state = "floor1"
var/viruses = list()
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index 9a24696cc87..b4a78c247b2 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -1,4 +1,6 @@
/obj/effect/decal/cleanable
+ gender = PLURAL
+ layer = ABOVE_NORMAL_TURF_LAYER
var/list/random_icon_states = list()
var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA
var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints
diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm
index c629ff1e768..4a0175076a1 100644
--- a/code/game/objects/effects/decals/crayon.dm
+++ b/code/game/objects/effects/decals/crayon.dm
@@ -3,15 +3,9 @@
desc = "Graffiti. Damn kids."
icon = 'icons/effects/crayondecal.dmi'
icon_state = "rune1"
- layer = ABOVE_NORMAL_TURF_LAYER
+ gender = NEUTER
var/do_icon_rotate = TRUE
-/obj/effect/decal/cleanable/crayon/examine()
- set src in view(2)
- ..()
- return
-
-
/obj/effect/decal/cleanable/crayon/New(location, main = "#FFFFFF", var/type = "rune1", var/e_name = "rune", var/rotation = 0, var/alt_icon = null)
..()
loc = location
diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm
index 20ac8176ef4..42eecf20b49 100644
--- a/code/game/objects/effects/effect_system/effects_smoke.dm
+++ b/code/game/objects/effects/effect_system/effects_smoke.dm
@@ -287,10 +287,10 @@
var/more = ""
if(M)
more = "(?) (FLW) "
- message_admins("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", 0, 1)
+ message_admins("Smoke: ([whereLink])[contained]. Key: [carry.my_atom.fingerprintslast][more].", 0, 1)
log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].")
else
- message_admins("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", 0, 1)
+ message_admins("Smoke: ([whereLink])[contained]. No associated key.", 0, 1)
log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.")
diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm
index 87d07232160..e63dcbb7840 100644
--- a/code/game/objects/effects/overlays.dm
+++ b/code/game/objects/effects/overlays.dm
@@ -55,12 +55,13 @@
duration = 5
randomdir = FALSE
layer = BELOW_MOB_LAYER
+ var/splatter_type = "splatter"
/obj/effect/overlay/temp/dir_setting/bloodsplatter/New(loc, set_dir)
if(set_dir in diagonals)
- icon_state = "splatter[pick(1, 2, 6)]"
+ icon_state = "[splatter_type][pick(1, 2, 6)]"
else
- icon_state = "splatter[pick(3, 4, 5)]"
+ icon_state = "[splatter_type][pick(3, 4, 5)]"
..()
var/target_pixel_x = 0
var/target_pixel_y = 0
@@ -90,44 +91,35 @@
layer = ABOVE_MOB_LAYER
animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration)
+/obj/effect/overlay/temp/dir_setting/bloodsplatter/xenosplatter
+ splatter_type = "xsplatter"
-/obj/effect/overlay/temp/heal //color is white by default, set to whatever is needed
- name = "healing glow"
- icon_state = "heal"
- duration = 15
+/obj/effect/overlay/temp/dir_setting/firing_effect
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "firing_effect"
+ duration = 2
-/obj/effect/overlay/temp/heal/New(loc, colour)
+/obj/effect/overlay/temp/dir_setting/firing_effect/setDir(newdir)
+ switch(newdir)
+ if(NORTH)
+ layer = BELOW_MOB_LAYER
+ pixel_x = rand(-3,3)
+ pixel_y = rand(4,6)
+ if(SOUTH)
+ pixel_x = rand(-3,3)
+ pixel_y = rand(-1,1)
+ else
+ pixel_x = rand(-1,1)
+ pixel_y = rand(-1,1)
..()
- pixel_x = rand(-12, 12)
- pixel_y = rand(-9, 0)
- if(colour)
- color = colour
-/obj/effect/overlay/temp/kinetic_blast
- name = "kinetic explosion"
- icon = 'icons/obj/projectiles.dmi'
- icon_state = "kinetic_blast"
- layer = ABOVE_ALL_MOB_LAYER
- duration = 4
+/obj/effect/overlay/temp/dir_setting/firing_effect/energy
+ icon_state = "firing_effect_energy"
+ duration = 3
-/obj/effect/overlay/temp/explosion
- name = "explosion"
- icon = 'icons/effects/96x96.dmi'
- icon_state = "explosion"
- pixel_x = -32
- pixel_y = -32
- duration = 8
-
-/obj/effect/overlay/temp/explosion/fast
- icon_state = "explosionfast"
- duration = 4
-
-/obj/effect/overlay/temp/blob
- name = "blob"
- icon_state = "blob_attack"
- alpha = 140
- randomdir = 0
- duration = 6
+/obj/effect/overlay/temp/dir_setting/firing_effect/magic
+ icon_state = "shieldsparkles"
+ duration = 3
/obj/effect/overlay/temp/dir_setting/ninja
name = "ninja shadow"
@@ -344,7 +336,7 @@
/obj/effect/overlay/temp/emp/pulse
name = "emp pulse"
- icon_state = "emp pulse"
+ icon_state = "emppulse"
duration = 8
randomdir = 0
@@ -393,6 +385,80 @@
/obj/effect/overlay/temp/sparkle/tailsweep
icon_state = "tailsweep"
+
+/obj/effect/overlay/temp/heal //color is white by default, set to whatever is needed
+ name = "healing glow"
+ icon_state = "heal"
+ duration = 15
+
+/obj/effect/overlay/temp/heal/New(loc, colour)
+ ..()
+ pixel_x = rand(-12, 12)
+ pixel_y = rand(-9, 0)
+ if(colour)
+ color = colour
+
+/obj/effect/overlay/temp/kinetic_blast
+ name = "kinetic explosion"
+ icon = 'icons/obj/projectiles.dmi'
+ icon_state = "kinetic_blast"
+ layer = ABOVE_ALL_MOB_LAYER
+ duration = 4
+
+/obj/effect/overlay/temp/explosion
+ name = "explosion"
+ icon = 'icons/effects/96x96.dmi'
+ icon_state = "explosion"
+ pixel_x = -32
+ pixel_y = -32
+ duration = 8
+
+/obj/effect/overlay/temp/explosion/fast
+ icon_state = "explosionfast"
+ duration = 4
+
+/obj/effect/overlay/temp/blob
+ name = "blob"
+ icon_state = "blob_attack"
+ alpha = 140
+ randomdir = 0
+ duration = 6
+
+/obj/effect/overlay/temp/impact_effect
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "impact_bullet"
+ duration = 5
+
+/obj/effect/overlay/temp/impact_effect/New(loc, atom/target, obj/item/projectile/P)
+ if(target == P.original) //the projectile hit the target originally clicked
+ pixel_x = P.p_x + target.pixel_x - 16 + rand(-4,4)
+ pixel_y = P.p_y + target.pixel_y - 16 + rand(-4,4)
+ else
+ pixel_x = target.pixel_x + rand(-4,4)
+ pixel_y = target.pixel_y + rand(-4,4)
+ ..()
+
+/obj/effect/overlay/temp/impact_effect/red_laser
+ icon_state = "impact_laser"
+ duration = 4
+
+/obj/effect/overlay/temp/impact_effect/blue_laser
+ icon_state = "impact_laser_blue"
+ duration = 4
+
+/obj/effect/overlay/temp/impact_effect/green_laser
+ icon_state = "impact_laser_green"
+ duration = 4
+
+/obj/effect/overlay/temp/impact_effect/purple_laser
+ icon_state = "impact_laser_purple"
+ duration = 4
+
+/obj/effect/overlay/temp/impact_effect/ion
+ icon_state = "shieldsparkles"
+ duration = 6
+
+
/obj/effect/overlay/palmtree_r
name = "Palm tree"
icon = 'icons/misc/beach2.dmi'
diff --git a/code/game/objects/effects/step_triggers.dm b/code/game/objects/effects/step_triggers.dm
index abebb75a63a..1754dfa6e46 100644
--- a/code/game/objects/effects/step_triggers.dm
+++ b/code/game/objects/effects/step_triggers.dm
@@ -3,7 +3,7 @@
/obj/effect/step_trigger
var/affect_ghosts = 0
var/stopper = 1 // stops throwers
- var/mobs_only = 0
+ var/mobs_only = FALSE
invisibility = INVISIBILITY_ABSTRACT // nope cant see this shit
anchored = 1
@@ -25,6 +25,7 @@
/obj/effect/step_trigger/message
var/message //the message to give to the mob
var/once = 1
+ mobs_only = TRUE
/obj/effect/step_trigger/message/Trigger(mob/M)
if(M.client)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 9d7659791ce..1e0b83f6ffd 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -344,6 +344,8 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
var/datum/action/A = X
A.Remove(user)
if(DROPDEL & flags)
+ //Prevents infinite loops where Destroy() calls an objects dropped() function
+ flags &= ~DROPDEL
qdel(src)
// called just as an item is picked up (loc is not yet changed)
@@ -589,4 +591,4 @@ obj/item/proc/item_action_slot_check(slot, mob/user)
//when an item modify our speech spans when in our active hand. Override this to modify speech spans.
/obj/item/proc/get_held_item_speechspans(mob/living/carbon/user)
- return
\ No newline at end of file
+ return
diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm
index 509f41dabea..9f3b53a8ac0 100644
--- a/code/game/objects/items/blueprints.dm
+++ b/code/game/objects/items/blueprints.dm
@@ -54,6 +54,7 @@
fluffnotice = "Property of Nanotrasen. For heads of staff only. Store in high-secure storage."
var/list/image/showing = list()
var/client/viewing
+ var/legend = FALSE //Viewing the wire legend
/obj/item/areaeditor/blueprints/Destroy()
@@ -63,15 +64,25 @@
/obj/item/areaeditor/blueprints/attack_self(mob/user)
. = ..()
- var/area/A = get_area()
- if(get_area_type() == AREA_STATION)
- . += "
You examine the wire legend.
"
+ for(var/wireset in wire_color_directory)
+ message += "
[wire_name_directory[wireset]]"
+ message += "
[wire_name_directory[device]]:" + for(var/Col in wire_color_directory[device]) + var/wire_name = wire_color_directory[device][Col] + if(!findtext(wire_name, WIRE_DUD_PREFIX)) //don't show duds + message += "
[Col]: [wire_name]
" + message += "" + return message + return "" + /proc/create_area(mob/living/creator) var/res = detect_room(get_turf(creator)) if(!istype(res,/list)) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index b7ce1e4a737..91745ffed8e 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -50,6 +50,8 @@ var/global/list/obj/item/device/pda/PDAs = list() var/image/photo = null //Scanned photo + var/list/contained_item = list(/obj/item/weapon/pen, /obj/item/toy/crayon, /obj/item/weapon/lipstick, /obj/item/device/flashlight/pen, /obj/item/clothing/mask/cigarette) + var/obj/item/inserted_item //Used for pen, crayon, and lipstick insertion or removal. Same as above. /obj/item/device/pda/pickup(mob/user) ..() @@ -74,7 +76,7 @@ var/global/list/obj/item/device/pda/PDAs = list() PDAs += src if(default_cartridge) cartridge = new default_cartridge(src) - new /obj/item/weapon/pen(src) + inserted_item = new /obj/item/weapon/pen(src) /obj/item/device/pda/proc/update_label() name = "PDA-[owner] ([ownjob])" //Name generalisation @@ -314,10 +316,8 @@ var/global/list/obj/item/device/pda/PDAs = list() update_label() if("Eject")//Ejects the cart, only done from hub. if (!isnull(cartridge)) - var/turf/T = loc - if(ismob(T)) - T = T.loc - cartridge.loc = T + U.put_in_hands(cartridge) + U << "You remove [cartridge] from [src]." scanmode = 0 if (cartridge.radio) cartridge.radio.hostpda = null @@ -704,18 +704,16 @@ var/global/list/obj/item/device/pda/PDAs = list() return if (usr.canUseTopic(src)) - var/obj/item/weapon/pen/O = locate() in src - if(O) - if (istype(loc, /mob)) + if(inserted_item) + if(ismob(loc)) var/mob/M = loc - if(M.get_active_held_item() == null) - M.put_in_hands(O) - usr << "You remove \the [O] from \the [src]." - return - O.loc = get_turf(src) + M.put_in_hands(inserted_item) + else + inserted_item.forceMove(loc) + usr << "You remove \the [inserted_item] from \the [src]." + inserted_item = null else usr << "This PDA does not have a pen in it!" - /obj/item/device/pda/proc/id_check(mob/user, choice as num)//To check for IDs; 1 for in-pda use, 2 for out of pda use. if(choice == 1) if (id) @@ -775,15 +773,15 @@ var/global/list/obj/item/device/pda/PDAs = list() pai = C user << "You slot \the [C] into [src]." updateUsrDialog() - else if(istype(C, /obj/item/weapon/pen)) - var/obj/item/weapon/pen/O = locate() in src - if(O) - user << "There is already a pen in \the [src]!" + else if(is_type_in_list(C, contained_item)) //Checks if there is a pen + if(inserted_item) + user << "There is already \a [inserted_item] in \the [src]!" else if(!user.unEquip(C)) return - C.loc = src + C.forceMove(src) user << "You slide \the [C] into \the [src]." + inserted_item = C else if(istype(C, /obj/item/weapon/photo)) var/obj/item/weapon/photo/P = C photo = P.img diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index 6e89ab267a0..07bfc457c92 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -23,6 +23,7 @@ disrupt() /obj/item/device/chameleon/equipped() + ..() disrupt() /obj/item/device/chameleon/attack_self() diff --git a/code/game/gamemodes/handofgod/items.dm b/code/game/objects/items/religion.dm similarity index 55% rename from code/game/gamemodes/handofgod/items.dm rename to code/game/objects/items/religion.dm index f512c5c11cb..4f6fa7ad3f0 100644 --- a/code/game/gamemodes/handofgod/items.dm +++ b/code/game/objects/items/religion.dm @@ -7,29 +7,19 @@ var/moralecooldown = 0 var/moralewait = 600 - /obj/item/weapon/banner/attack_self(mob/living/carbon/human/user) if(moralecooldown + moralewait > world.time) return - var/side = "" - if(is_handofgod_redcultist(user)) - side = "red" - else if (is_handofgod_bluecultist(user)) - side = "blue" - - if(!side) - return user << "You increase the morale of your fellows!" moralecooldown = world.time for(var/mob/living/carbon/human/H in range(4,get_turf(src))) - if((side == "red") && is_handofgod_redcultist(H) || (side == "blue") && is_handofgod_bluecultist(H)) - H << "Your morale is increased by [user]'s banner!" - H.adjustBruteLoss(-15) - H.adjustFireLoss(-15) - H.AdjustStunned(-2) - H.AdjustWeakened(-2) - H.AdjustParalysis(-2) + H << "Your morale is increased by [user]'s banner!" + H.adjustBruteLoss(-15) + H.adjustFireLoss(-15) + H.AdjustStunned(-2) + H.AdjustWeakened(-2) + H.AdjustParalysis(-2) /obj/item/weapon/banner/red @@ -38,52 +28,32 @@ item_state = "banner-red" desc = "A banner with the logo of the red deity." -/obj/item/weapon/banner/red/examine(mob/user) - ..() - if(is_handofgod_redcultist(user)) - user << "A banner representing our might against the heretics. We may use it to increase the morale of our fellow members!" - else if(is_handofgod_bluecultist(user)) - user << "A heretical banner that should be destroyed posthaste." - - /obj/item/weapon/banner/blue name = "blue banner" icon_state = "banner-blue" item_state = "banner-blue" desc = "A banner with the logo of the blue deity" -/obj/item/weapon/banner/blue/examine(mob/user) - ..() - - if(is_handofgod_redcultist(user)) - user << "A heretical banner that should be destroyed posthaste." - else if(is_handofgod_bluecultist(user)) - user << "A banner representing our might against the heretics. We may use it to increase the morale of our fellow members!" - - /obj/item/weapon/storage/backpack/bannerpack name = "nanotrasen banner backpack" desc = "It's a backpack with lots of extra room. A banner with Nanotrasen's logo is attached, that can't be removed." max_combined_w_class = 27 //6 more then normal, for the tradeoff of declaring yourself an antag at all times. icon_state = "bannerpack" - /obj/item/weapon/storage/backpack/bannerpack/red name = "red banner backpack" desc = "It's a backpack with lots of extra room. A red banner is attached, that can't be removed." icon_state = "bannerpack-red" - /obj/item/weapon/storage/backpack/bannerpack/blue name = "blue banner backpack" desc = "It's a backpack with lots of extra room. A blue banner is attached, that can't be removed." icon_state = "bannerpack-blue" - - //this is all part of one item set /obj/item/clothing/suit/armor/plate/crusader name = "Crusader's Armour" + desc = "Armour that's comprised of metal and cloth." icon_state = "crusader" w_class = 4 //bulky slowdown = 2.0 //gotta pretend we're balanced. @@ -96,16 +66,9 @@ /obj/item/clothing/suit/armor/plate/crusader/blue icon_state = "crusader-blue" -/obj/item/clothing/suit/armor/plate/crusader/examine(mob/user) - ..() - if(!is_handofgod_cultist(user)) - user << "Armour that's comprised of metal and cloth." - else - user << "Armour that was used to protect from backstabs, gunshots, explosives, and lasers. The original wearers of this type of armour were trying to avoid being murdered. Since they're not around anymore, you're not sure if they were successful or not." - - /obj/item/clothing/head/helmet/plate/crusader name = "Crusader's Hood" + desc = "A brownish hood." icon_state = "crusader" w_class = 3 //normal flags_inv = HIDEHAIR|HIDEEARS|HIDEFACE @@ -117,140 +80,67 @@ /obj/item/clothing/head/helmet/plate/crusader/red icon_state = "crusader-red" - -/obj/item/clothing/head/helmet/plate/crusader/examine(mob/user) - ..() - if(!is_handofgod_cultist(user)) - user << "A brownish hood." - else - user << "A hood that's very protective, despite being made of cloth. Due to the tendency of the wearer to be targeted for assassinations, being protected from being shot in the face was very important.." - - - //Prophet helmet /obj/item/clothing/head/helmet/plate/crusader/prophet name = "Prophet's Hat" + desc = "A religious-looking hat." alternate_worn_icon = 'icons/mob/large-worn-icons/64x64/head.dmi' flags = 0 armor = list(melee = 60, bullet = 60, laser = 60, energy = 50, bomb = 70, bio = 50, rad = 50) //religion protects you from disease and radiation, honk. worn_x_dimension = 64 worn_y_dimension = 64 - var/side = "neither" - -/obj/item/clothing/head/helmet/plate/crusader/prophet/equipped(mob/living/carbon/user, slot) - var/faithful = 0 - if(slot == slot_head) - switch(side) - if("blue") - faithful = is_handofgod_bluecultist(user) - if("red") - faithful = is_handofgod_redcultist(user) - else - faithful = 1 - if(!faithful) - user << "Your mind is assaulted by a vast power, furious at your desecration!" - user.emote("scream") - user.adjustFireLoss(10) - user.unEquip(src) - user.head = null - user.update_inv_head() - src.screen_loc = null - user.Weaken(1) /obj/item/clothing/head/helmet/plate/crusader/prophet/red icon_state = "prophet-red" - side = "red" - /obj/item/clothing/head/helmet/plate/crusader/prophet/blue icon_state = "prophet-blue" - side = "blue" - - -/obj/item/clothing/head/helmet/plate/crusader/prophet/examine(mob/user) - ..() - if(!is_handofgod_cultist(user)) - user << "A brownish, religious-looking hat." - else - user << "A hat bestowed upon a prophet of gods and demigods." - user << "This hat belongs to the [side] god." - - //Structure conversion staff /obj/item/weapon/godstaff name = "godstaff" + desc = "It's a stick..?" icon_state = "godstaff-red" - var/mob/camera/god/god = null + var/conversion_color = "#ffffff" var/staffcooldown = 0 var/staffwait = 30 -/obj/item/weapon/godstaff/examine(mob/user) - ..() - if(!is_handofgod_cultist(user)) - user << "It's a stick..?" - else - user << "A powerful staff capable of changing the allegiance of god/demigod structures." - - -/obj/item/weapon/godstaff/attack_self(mob/living/carbon/user) - if((god && !god.is_handofgod_myprophet(user)) || !god) - user << "YOU ARE NOT THE CHOSEN ONE!" - return - if(!(istype(user.head, /obj/item/clothing/head/helmet/plate/crusader/prophet))) - user << "Your connection to your diety isn't strong enough! You must wear your big hat!" - return +/obj/item/weapon/godstaff/afterattack(atom/target, mob/user, proximity_flag, click_parameters) if(staffcooldown + staffwait > world.time) return - user.visible_message("[user] chants deeply and waves their staff") + user.visible_message("[user] chants deeply and waves their staff!") if(do_after(user, 20,1,src)) - for(var/obj/structure/divine/R in orange(3,user)) - user.say("Grant us true sight my god!") - if(istype(R, /obj/structure/divine/nexus)|| istype(R, /obj/structure/divine/trap)) - continue - R.visible_message("[R] suddenly appears!") - R.invisibility = 0 - R.alpha = initial(R.alpha) - R.density = initial(R.density) - R.activate() + target.color = conversion_color //wololo staffcooldown = world.time /obj/item/weapon/godstaff/red icon_state = "godstaff-red" + conversion_color = "#ff0000" /obj/item/weapon/godstaff/blue icon_state = "godstaff-blue" - - + conversion_color = "#0000ff" /obj/item/clothing/gloves/plate name = "Plate Gauntlets" icon_state = "crusader" + desc = "They're like gloves, but made of metal." siemens_coefficient = 0 cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT - /obj/item/clothing/gloves/plate/red icon_state = "crusader-red" /obj/item/clothing/gloves/plate/blue icon_state = "crusader-blue" - -/obj/item/clothing/gloves/plate/examine(mob/user) - ..() - if(!is_handofgod_cultist(user)) - usr << "They're like gloves, but made of metal." - else - usr << "Protective gloves that are also blessed to protect from heat and shock." - - /obj/item/clothing/shoes/plate name = "Plate Boots" + desc = "Metal boots, they look heavy." icon_state = "crusader" w_class = 3 //normal armor = list(melee = 50, bullet = 50, laser = 50, energy = 40, bomb = 60, bio = 0, rad = 0) //does this even do anything on boots? @@ -268,14 +158,6 @@ icon_state = "crusader-blue" -/obj/item/clothing/shoes/plate/examine(mob/user) - ..() - if(!is_handofgod_cultist(user)) - usr << "Metal boots, they look heavy." - else - usr << "Heavy boots that are blessed for sure footing. You'll be safe from being taken down by the heresy that is the banana peel." - - /obj/item/weapon/storage/box/itemset/crusader name = "Crusader's Armour Set" //i can't into ck2 references desc = "This armour is said to be based on the armor of kings on another world thousands of years ago, who tended to assassinate, conspire, and plot against everyone who tried to do the same to them. Some things never change." @@ -301,6 +183,7 @@ new /obj/item/clothing/shoes/plate/red(src) -/obj/item/weapon/claymore/hog +/obj/item/weapon/claymore/weak + desc = "This one is rusted." force = 30 armour_penetration = 15 \ No newline at end of file diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 5e8b75b987a..5f1e514cde7 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -10,15 +10,16 @@ icon_state = "elecarm" var/charge_cost = 30 -/obj/item/borg/stun/attack(mob/living/M, mob/living/silicon/robot/user) +/obj/item/borg/stun/attack(mob/living/M, mob/living/user) if(ishuman(M)) var/mob/living/carbon/human/H = M if(H.check_shields(0, "[M]'s [name]", src, MELEE_ATTACK)) playsound(M, 'sound/weapons/Genhit.ogg', 50, 1) return 0 - - if(!user.cell.use(charge_cost)) - return + if(isrobot(user)) + var/mob/living/silicon/robot/R = user + if(!R.cell.use(charge_cost)) + return user.do_attack_animation(M) M.Weaken(5) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 2e765ab4e05..74be2659ad9 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -137,6 +137,7 @@ if (R.max_res_amount > 1) var/obj/item/stack/new_item = O new_item.amount = R.res_amount*multiplier + new_item.update_icon() if(new_item.amount <= 0)//if the stack is empty, i.e it has been merged with an existing stack and has been garbage collected return @@ -232,7 +233,7 @@ ..() return -/obj/item/stack/AltClick(mob/user) +/obj/item/stack/AltClick(mob/living/user) if(user.incapacitated()) user << "You can't do that right now!" return diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index 461d4cc2a33..c2615f28d7a 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -573,3 +573,177 @@ CIGARETTE PACKETS ARE IN FANCY.DM user << "You need to dry this first!" else ..() + +/////////////// +//VAPE NATION// +/////////////// +/obj/item/clothing/mask/vape + name = "E-Cigarette" + desc = "A classy and highly sophisticated electronic cigarette, for classy and dignified gentlemen. A warning label reads \"Warning: do not fill with flamable materials\""//<<< i'd vape to that. + icon = 'icons/obj/clothing/masks.dmi' + icon_state = null + item_state = null + var/chem_volume = 100 + var/vapetime = 0 //this so it won't puff out clouds every tick + var/screw = 0 // kinky + var/super = 0 //for the fattest vapes dude. + var/emagged = 0 //LET THE GRIEF BEGIN + +/obj/item/clothing/mask/vape/suicide_act(mob/user) + user.visible_message("[user] is puffin hard on dat vape, they trying to join the vape life on a whole notha plane!")//it doesn't give you cancer, it is cancer + return (TOXLOSS|OXYLOSS) + + +/obj/item/clothing/mask/vape/New(loc, var/param_color = null) + ..() + create_reagents(chem_volume) + reagents.set_reacting(FALSE) // so it doesn't react until you light it + reagents.add_reagent("nicotine", 50) + if(!icon_state) + if(!param_color) + param_color = pick("red","blue","black","white","green","purple","yellow","orange") + icon_state = "[param_color]_vape" + item_state = "[param_color]_vape" + +/obj/item/clothing/mask/vape/attackby(obj/item/O, mob/user, params) + if(istype(O, /obj/item/weapon/reagent_containers/glass)) + if(reagents.total_volume < chem_volume) + if(O.reagents.total_volume > 0) + O.reagents.trans_to(src,25) + user << "You add the contents of [O] to the [src]" + else + user << "The [O] is empty!" + else + user << "[src] can't hold anymore reagents!" + + if(istype(O, /obj/item/weapon/screwdriver)) + if(!screw) + screw = 1 + user << "You open the cap on the [src]" + if(super) + add_overlay(image(icon, "vapeopen_med")) + else + add_overlay(image(icon, "vapeopen_low")) + else + screw = 0 + user << "You close the cap on the [src]" + cut_overlays() + + if(istype(O, /obj/item/device/multitool)) + if(screw && !emagged)//also kinky + if(!super) + cut_overlays() + super = 1 + user << "You increase the voltage in the [src]" + add_overlay(image(icon, "vapeopen_med")) + else + cut_overlays() + super = 0 + user << "You decrease the voltage in the [src]" + add_overlay(image(icon, "vapeopen_low")) + + if(screw && emagged) + user << "The [name] can't be modified!" + + +/obj/item/clothing/mask/vape/emag_act(mob/user)// I WON'T REGRET WRITTING THIS, SURLY. + if(screw) + if(!emagged) + cut_overlays() + emagged = 1 + super = 0 + user << "You maximize the voltage in the [src]" + add_overlay(image(icon, "vapeopen_high")) + var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread //for effect + sp.set_up(5, 1, src) + sp.start() + else + user << "The [name] is already emagged!" + else + user << "You need to open the cap to do that" + +/obj/item/clothing/mask/vape/attack_self(mob/user) + if(reagents.total_volume > 0) + user << "you empty [src] of all reagents." + reagents.clear_reagents() + return + +/obj/item/clothing/mask/vape/equipped(mob/user, slot) + if(slot == slot_wear_mask) + if(!screw) + user << "You start puffing on that dank vape" + reagents.set_reacting(TRUE) + START_PROCESSING(SSobj, src) + else //it will not start if the vape is opened. + user << "You need to close the cap first!" + +/obj/item/clothing/mask/vape/dropped(mob/user) + var/mob/living/carbon/C = user + if(C.get_item_by_slot(slot_wear_mask) == src) + reagents.set_reacting(FALSE) + STOP_PROCESSING(SSobj, src) + +/obj/item/clothing/mask/vape/proc/hand_reagents()//had to rename to avoid duplicate error + if(reagents.total_volume) + if(iscarbon(loc)) + var/mob/living/carbon/C = loc + if (src == C.wear_mask) // if it's in the human/monkey mouth, transfer reagents to the mob + var/fraction = min(REAGENTS_METABOLISM/reagents.total_volume, 1) //this will react instantly, making them a little more dangerous than cigarettes + reagents.reaction(C, INGEST, fraction) + reagents.trans_to(C, REAGENTS_METABOLISM) + if(reagents.get_reagent_amount("welding_fuel")) + //HOT STUFF + C.fire_stacks = 2 + C.IgniteMob() + + if(reagents.get_reagent_amount("plasma")) // the plasma explodes when exposed to fire + var/datum/effect_system/reagents_explosion/e = new() + e.set_up(round(reagents.get_reagent_amount("plasma") / 2.5, 1), get_turf(src), 0, 0) + e.start() + if(ismob(loc)) + var/mob/M = loc + M.unEquip(src, 1) + qdel(src) + return + reagents.remove_any(REAGENTS_METABOLISM) + +/obj/item/clothing/mask/vape/process() + var/mob/living/M = loc + + if(isliving(loc)) + M.IgniteMob() + + vapetime++ + + if(!reagents.total_volume) + if(ismob(loc)) + M << "The [name] is empty!" + STOP_PROCESSING(SSobj, src) + //it's reusable so it won't unequip when empty + return + //open flame removed because vapes are a closed system, they wont light anything on fire + + if(super && vapetime > 3)//Time to start puffing those fat vapes, yo. + var/datum/effect_system/smoke_spread/chem/s = new + s.set_up(reagents, 1, loc) + s.start() + vapetime = 0 + + if(emagged && vapetime > 3) + var/datum/effect_system/smoke_spread/chem/s = new + s.set_up(reagents, 4, loc) + s.start() + vapetime = 0 + if(prob(5))//small chance for the vape to break and deal damage if it's emagged + playsound(get_turf(src), 'sound/effects/pop_expl.ogg', 50, 0) + M.apply_damage(20, BURN, "head") + M.unEquip(src, 1) + M.Weaken(15, 1, 0) + qdel(src) + var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread + sp.set_up(5, 1, src) + sp.start() + M << "The [name] suddenly explodes in your mouth!" + + if(reagents && reagents.total_volume) + hand_reagents() diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index 60f8799ae76..c5e24fc13a4 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -52,10 +52,10 @@ add_fingerprint(user) var/turf/bombturf = get_turf(src) var/area/A = get_area(bombturf) - var/message = "[ADMIN_LOOKUPFLW(user)]) has primed a [name] for detonation at [ADMIN_COORDJMP(src)]" + var/message = "[ADMIN_LOOKUPFLW(user)]) has primed a [name] for detonation at [ADMIN_COORDJMP(bombturf)]" bombers += message message_admins(message) - log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] [COORD(src)].") + log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] [COORD(bombturf)].") if(iscarbon(user)) var/mob/living/carbon/C = user C.throw_mode_on() diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm index 76536e7b21d..0af7877d3d7 100644 --- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm +++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm @@ -17,15 +17,8 @@ for(var/mob/living/carbon/C in viewers(T, null)) C.flash_act() - for(var/i=1, i<=deliveryamt, i++) - var/atom/movable/x = new spawner_type - x.admin_spawned = admin_spawned - x.loc = T - if(prob(50)) - for(var/j = 1, j <= rand(1, 3), j++) - step(x, pick(NORTH,SOUTH,EAST,WEST)) - - // Spawn some hostile syndicate critters + // Spawn some hostile syndicate critters and spread them out + spawn_and_random_walk(spawner_type, T, deliveryamt, walk_chance=50, admin_spawn=admin_spawned) qdel(src) diff --git a/code/game/objects/items/weapons/implants/implant_loyality.dm b/code/game/objects/items/weapons/implants/implant_loyality.dm index c669b279ccc..fe9a59d0df5 100644 --- a/code/game/objects/items/weapons/implants/implant_loyality.dm +++ b/code/game/objects/items/weapons/implants/implant_loyality.dm @@ -32,7 +32,7 @@ return -1 if(target.mind in ticker.mode.revolutionaries) ticker.mode.remove_revolutionary(target.mind) - if((target.mind in ticker.mode.cult) || (target.mind in ticker.mode.blue_deity_prophets|ticker.mode.red_deity_prophets|ticker.mode.red_deity_followers|ticker.mode.blue_deity_followers)) + if(target.mind in ticker.mode.cult) target << "You feel something interfering with your mental conditioning, but you resist it!" else target << "You feel a sense of peace and security. You are now protected from brainwashing." @@ -46,7 +46,6 @@ return 1 return 0 - /obj/item/weapon/implanter/mindshield name = "implanter (mindshield)" diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm index efac43f30ea..ee4a454f671 100644 --- a/code/game/objects/items/weapons/kitchen.dm +++ b/code/game/objects/items/weapons/kitchen.dm @@ -121,6 +121,7 @@ desc = "A sharpened bone. The bare mimimum in survival." force = 15 throwforce = 15 + materials = list() /obj/item/weapon/kitchen/knife/combat/cyborg name = "cyborg knife" diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index 9f93c93eca3..b9d3a17e023 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -238,7 +238,6 @@ /obj/item/weapon/melee/energy/blade/dropped() ..() - qdel(src) /obj/item/weapon/melee/energy/blade/attack_self(mob/user) return diff --git a/code/game/objects/items/weapons/melee/misc.dm b/code/game/objects/items/weapons/melee/misc.dm index b81a9cf75aa..596ed7b35b6 100644 --- a/code/game/objects/items/weapons/melee/misc.dm +++ b/code/game/objects/items/weapons/melee/misc.dm @@ -21,6 +21,17 @@ user.visible_message("[user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide.") return (OXYLOSS) +/obj/item/weapon/melee/synthetic_arm_blade + name = "synthetic arm blade" + desc = "A grotesque blade that on closer inspection seems made of synthentic flesh, it still feels like it would hurt very badly as a weapon." + icon = 'icons/obj/weapons.dmi' + icon_state = "arm_blade" + item_state = "arm_blade" + origin_tech = "combat=5,biotech=5" + w_class = 5.0 + force = 15 + throwforce = 10 + sharpness = IS_SHARP /obj/item/weapon/melee/sabre name = "officer's sabre" @@ -36,7 +47,7 @@ armour_penetration = 75 sharpness = IS_SHARP origin_tech = "combat=5" - attack_verb = list("lunged at", "stabbed") + attack_verb = list("slashed", "cut") hitsound = 'sound/weapons/rapierhit.ogg' materials = list(MAT_METAL = 1000) diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm index 2f4c84ba913..feeab19e611 100644 --- a/code/game/objects/items/weapons/mop.dm +++ b/code/game/objects/items/weapons/mop.dm @@ -1,5 +1,3 @@ -#define is_cleanable(A) (istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/rune)) - /obj/item/weapon/mop desc = "The world of janitalia wouldn't be complete without a mop." name = "mop" @@ -42,16 +40,14 @@ obj/item/weapon/mop/proc/clean(turf/A) user << "Your mop is dry!" return - var/turf/turf = A - if(is_cleanable(A)) - turf = A.loc + var/turf/T = get_turf(A) - if(istype(turf)) - user.visible_message("[user] begins to clean \the [turf] with [src].", "You begin to clean \the [turf] with [src]...") + if(T) + user.visible_message("[user] begins to clean \the [T] with [src].", "You begin to clean \the [T] with [src]...") - if(do_after(user, src.mopspeed, target = turf)) + if(do_after(user, src.mopspeed, target = T)) user << "You finish mopping." - clean(turf) + clean(T) /obj/effect/attackby(obj/item/I, mob/user, params) diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 46dbaa39b36..0b248912b93 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -431,6 +431,23 @@ /obj/item/weapon/melee/sabre ) +/obj/item/weapon/storage/belt/sabre/examine(mob/user) + ..() + if(contents.len) + user << "Alt-click it to quickly draw the blade." + +/obj/item/weapon/storage/belt/sabre/AltClick(mob/user) + if(!ishuman(user) || !user.canUseTopic(src)) + return + if(contents.len) + var/obj/item/I = contents[1] + user.visible_message("[user] takes [I] out of [src].", "You take [I] out of [src].",\ + ) + user.put_in_hands(I) + update_icon() + else + user << "[src] is empty." + /obj/item/weapon/storage/belt/sabre/update_icon() icon_state = "sheath" item_state = "sheath" @@ -442,6 +459,7 @@ L.regenerate_icons() ..() + /obj/item/weapon/storage/belt/sabre/New() ..() new /obj/item/weapon/melee/sabre(src) diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 9f27404afae..38ade34e247 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -2,7 +2,7 @@ /obj/item/weapon/storage/box/syndicate/New() ..() - switch (pickweight(list("bloodyspai" = 3, "stealth" = 2, "bond" = 2, "screwed" = 2, "sabotage" = 3, "guns" = 2, "murder" = 2, "implant" = 1, "hacker" = 3, "lordsingulo" = 1, "darklord" = 1, "sniper" = 1, "metaops" = 1))) + switch (pickweight(list("bloodyspai" = 3, "stealth" = 2, "bond" = 2, "screwed" = 2, "sabotage" = 3, "guns" = 2, "murder" = 2, "implant" = 1, "hacker" = 3, "lordsingulo" = 1, "darklord" = 1, "sniper" = 1, "metaops" = 1, "ninja" = 1))) if("bloodyspai") // 27 tc now this is more right new /obj/item/clothing/under/chameleon(src) // 2 tc since it's not the full set new /obj/item/clothing/mask/chameleon(src) // Goes with above @@ -131,6 +131,19 @@ new /obj/item/weapon/grenade/plastic/c4 (src) // 1 tc new /obj/item/weapon/card/emag(src) // 6 tc return + + if("ninja") // 33 tc worth + new /obj/item/weapon/katana(src) // Unique , hard to tell how much tc this is worth. 8 tc? + new /obj/item/weapon/implanter/adrenalin(src) // 8 tc + new /obj/item/weapon/throwing_star(src) // ~5 tc for all 6 + new /obj/item/weapon/throwing_star(src) + new /obj/item/weapon/throwing_star(src) + new /obj/item/weapon/throwing_star(src) + new /obj/item/weapon/throwing_star(src) + new /obj/item/weapon/throwing_star(src) + new /obj/item/weapon/storage/belt/military/assault(src) // 3 tc + new /obj/item/weapon/card/id/syndicate(src) // 2 tc + new /obj/item/device/chameleon(src) // 7 tc /obj/item/weapon/storage/box/syndie_kit name = "box" diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index a48395a2cab..8b3816cc3dd 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -518,6 +518,7 @@ obj/item/weapon/weldingtool/proc/switched_off(mob/user) can_off_process = 1 light_intensity = 1 toolspeed = 2 + var/nextrefueltick = 0 /obj/item/weapon/weldingtool/experimental/brass name = "brass welding tool" @@ -526,20 +527,11 @@ obj/item/weapon/weldingtool/proc/switched_off(mob/user) item_state = "brasswelder" -//Proc to make the experimental welder generate fuel, optimized as fuck -Sieve -//i don't think this is actually used, yaaaaay -Pete -/obj/item/weapon/weldingtool/experimental/proc/fuel_gen() - if(!welding && !last_gen) - last_gen = 1 - reagents.add_reagent("welding_fuel",1) - spawn(10) - last_gen = 0 - /obj/item/weapon/weldingtool/experimental/process() ..() - if(reagents.total_volume < max_fuel) - fuel_gen() - + if(get_fuel() < max_fuel && nextrefueltick < world.time) + nextrefueltick = world.time + 10 + reagents.add_reagent("welding_fuel", 1) /* diff --git a/code/game/objects/items/weapons/vending_items.dm b/code/game/objects/items/weapons/vending_items.dm index 82fa5b64f5d..29b76b0a746 100644 --- a/code/game/objects/items/weapons/vending_items.dm +++ b/code/game/objects/items/weapons/vending_items.dm @@ -57,8 +57,8 @@ /obj/item/weapon/vending_refill/cigarette machine_name = "ShadyCigs Deluxe" icon_state = "refill_smoke" - charges = list(12, 1, 2)// of 36 standard, 3 contraband, 6 premium - init_charges = list(12, 1, 2) + charges = list(12, 3, 2)// of 36 standard, 9 contraband, 6 premium + init_charges = list(12, 3, 2) /obj/item/weapon/vending_refill/autodrobe machine_name = "AutoDrobe" @@ -69,5 +69,5 @@ /obj/item/weapon/vending_refill/clothing machine_name = "ClothesMate" icon_state = "refill_clothes" - charges = list(31, 3, 4)// of 101 standard, 7 contraband, 10 premium(?) - init_charges = list(31, 2, 4) + charges = list(31, 4, 4)// of 101 standard, 12 contraband, 10 premium(?) + init_charges = list(31, 4, 4) diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 0702a80d30c..07d09d07451 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -82,10 +82,14 @@ var/highlander_claymores = 0 /obj/item/weapon/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim." + flags = CONDUCT | NODROP + slot_flags = null block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY - attack_verb = list("brutalized", "eviscerated", "disemboweled", "hacked", "carved", "cleaved", "gored") //ONLY THE MOST VISCERAL ATTACK VERBS + attack_verb = list("brutalized", "eviscerated", "disemboweled", "hacked", "carved", "cleaved") //ONLY THE MOST VISCERAL ATTACK VERBS var/notches = 0 //HOW MANY PEOPLE HAVE BEEN SLAIN WITH THIS BLADE var/announced = FALSE //IF WE ARE THE ONLY ONE LEFT STANDING + var/bloodthirst_level = 0 //HOW THIRSTY WE ARE FOR BLOOD + var/obj/item/weapon/disk/nuclear/nuke_disk //OUR STORED NUKE DISK /obj/item/weapon/claymore/highlander/New() ..() @@ -95,19 +99,27 @@ var/highlander_claymores = 0 /obj/item/weapon/claymore/highlander/Destroy() STOP_PROCESSING(SSobj, src) highlander_claymores-- + if(nuke_disk) + nuke_disk.forceMove(get_turf(src)) + nuke_disk.visible_message("The nuke disk is vulnerable!") + nuke_disk = null return ..() /obj/item/weapon/claymore/highlander/process() if(isliving(loc)) var/mob/living/L = loc if(L.stat != DEAD) + if(!announced) + handle_bloodthirst(L) if(announced || admin_spawned || highlander_claymores > 1) return announced = TRUE L.fully_heal() - world << "[L.real_name] IS THE ONLY ONE LEFT STANDING!" + world << "[uppertext(L.real_name)] IS THE ONLY ONE LEFT STANDING!" world << sound('sound/misc/highlander_only_one.ogg') L << "YOU ARE THE ONLY ONE LEFT STANDING!" + for(var/obj/item/weapon/bloodcrawl/B in L) + qdel(B) /obj/item/weapon/claymore/highlander/pickup(mob/living/user) user << "The power of Scotland protects you! You are shielded from all stuns and knockdowns." @@ -120,12 +132,18 @@ var/highlander_claymores = 0 /obj/item/weapon/claymore/highlander/examine(mob/user) ..() user << "It has [!notches ? "nothing" : "[notches] notches"] scratched into the blade." + if(nuke_disk) + user << "It's holding the nuke disk!" /obj/item/weapon/claymore/highlander/attack(mob/living/target, mob/living/user) var/old_target_stat = target.stat . = ..() + bloodthirst_level = max(bloodthirst_level - (target.mind && target.mind.special_role == "highlander" ? 15 : 5), 0) if(target && target.stat == DEAD && old_target_stat != DEAD && target.mind && target.mind.special_role == "highlander") user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES + if(bloodthirst_level >= 30) + user << "[src] shakes greedily as it devours [target]'s soul. Its bloodthirst is quenched for the moment..." + bloodthirst_level = 0 add_notch(user) target.visible_message("[target] crumbles to dust beneath [user]'s blows!", "As you fall, your body crumbles to dust!") target.dust() @@ -138,6 +156,7 @@ var/highlander_claymores = 0 closest_victim = H if(!closest_victim) user << "[src] thrums for a moment and falls dark. Perhaps there's nobody nearby." + return user << "[src] thrums and points to the [dir2text(get_dir(user, closest_victim))]." /obj/item/weapon/claymore/highlander/IsReflect() @@ -196,6 +215,22 @@ var/highlander_claymores = 0 name = new_name playsound(user, 'sound/items/Screwdriver2.ogg', 50, 1) +/obj/item/weapon/claymore/highlander/proc/handle_bloodthirst(mob/living/S) //THE BLADE THIRSTS FOR BLOOD AND WILL PUNISH THE WEAK OR PACIFISTIC + bloodthirst_level += (1 + min(notches, 10)) + if(bloodthirst_level == 30) + S << "[src] shudders in your hand. It hungers for battle..." + if(bloodthirst_level == 60) + S << "[src] trembles violently. Kill someone already!" + if(bloodthirst_level == 90) + S << "[src] starts shaking viciously! Shed blood or it'll give you away!" + if(bloodthirst_level >= 120) + var/turf/T = get_turf(S) + for(var/mob/M in player_list - S) + if(M.z == T.z) + M << "THERE IS A COWARD WHO DOES NOT FIGHT TO THE [uppertext(dir2text(get_dir(M, T)))]. THEIR NAME IS [uppertext(S.real_name)] - SLAUGHTER THEM." + S << "you fucked up" + bloodthirst_level = 100 + /obj/item/weapon/katana name = "katana" desc = "Woefully underpowered in D20" diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 22e1473d8c4..89a48c7c22c 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -216,10 +216,10 @@ if(burn) Item.fire_act() //Set them on fire, too -/obj/proc/tesla_act(var/power) +/obj/proc/tesla_act(power, explosive = FALSE) being_shocked = 1 var/power_bounced = power / 2 - tesla_zap(src, 3, power_bounced) + tesla_zap(src, 3, power_bounced, explosive) addtimer(src, "reset_shocked", 10) /obj/proc/reset_shocked() diff --git a/code/game/objects/structures/crates_lockers/closets/fitness.dm b/code/game/objects/structures/crates_lockers/closets/fitness.dm index d3e7f0156ea..7c01cb0b18f 100644 --- a/code/game/objects/structures/crates_lockers/closets/fitness.dm +++ b/code/game/objects/structures/crates_lockers/closets/fitness.dm @@ -11,6 +11,8 @@ new /obj/item/clothing/under/shorts/red(src) new /obj/item/clothing/under/shorts/blue(src) new /obj/item/clothing/under/shorts/green(src) + if(prob(3)) + new /obj/item/clothing/under/jabroni(src) /obj/structure/closet/boxinggloves diff --git a/code/game/objects/structures/divine.dm b/code/game/objects/structures/divine.dm new file mode 100644 index 00000000000..51415356960 --- /dev/null +++ b/code/game/objects/structures/divine.dm @@ -0,0 +1,46 @@ +/obj/structure/sacrificealtar + name = "sacrificial altar" + desc = "An altar designed to perform blood sacrifice for a deity." + icon = 'icons/obj/hand_of_god_structures.dmi' + icon_state = "sacrificealtar" + anchored = 1 + density = 0 + can_buckle = 1 + +/obj/structure/sacrificealtar/attack_hand(mob/living/user) + ..() + if(!has_buckled_mobs()) + return + var/mob/living/L = locate() in buckled_mobs + if(!L) + return + user << "You attempt to sacrifice [L] by invoking the sacrificial ritual." + L.gib() + message_admins("[key_name_admin(user)] has sacrificed [key_name_admin(L)] on the sacrifical altar.") + +/obj/structure/healingfountain + name = "healing fountain" + desc = "A fountain containing the waters of life." + icon = 'icons/obj/hand_of_god_structures.dmi' + icon_state = "fountain" + anchored = 1 + density = 1 + var/time_between_uses = 1800 + var/last_process = 0 + +/obj/structure/healingfountain/attack_hand(mob/living/user) + if(last_process + time_between_uses > world.time) + user << "The fountain appears to be empty." + return + last_process = world.time + user << "The water feels warm and soothing as you touch it. The fountain immediately dries up shortly afterwards." + user.reagents.add_reagent("godblood",20) + update_icons() + addtimer(src, "update_icons", time_between_uses) + + +/obj/structure/healingfountain/proc/update_icons() + if(last_process + time_between_uses > world.time) + icon_state = "fountain" + else + icon_state = "fountain-red" \ No newline at end of file diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index 08a823f44be..a94dd50fe7a 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -25,6 +25,7 @@ playsound(get_turf(src), 'sound/effects/meteorimpact.ogg', 100 , 0, 0) icon = 'icons/obj/flora/pinetrees.dmi' icon_state = "tree_stump" + density = 0 pixel_x = -16 name += " stump" cut = TRUE diff --git a/code/game/objects/structures/fluff.dm b/code/game/objects/structures/fluff.dm index c2fa1e72cf6..13ae66801be 100644 --- a/code/game/objects/structures/fluff.dm +++ b/code/game/objects/structures/fluff.dm @@ -120,3 +120,43 @@ name = "dense stack of papers" desc = "A stack of various papers, childish scribbles scattered across each page." icon_state = "paperstack" + + +/obj/structure/fluff/divine + name = "Miracle" + icon = 'icons/obj/hand_of_god_structures.dmi' + anchored = 1 + density = 1 + +/obj/structure/fluff/divine/nexus + name = "nexus" + desc = "It anchors a deity to this world. It radiates an unusual aura. It looks well protected from explosive shock." + icon_state = "nexus-neutral" + +/obj/structure/fluff/divine/conduit + name = "conduit" + desc = "It allows a deity to extend their reach. Their powers are just as potent near a conduit as a nexus." + icon_state = "conduit-neutral" + +/obj/structure/fluff/divine/convertaltar + name = "conversion altar" + desc = "An altar dedicated to a deity." + icon_state = "convertaltar-neutral" + density = 0 + can_buckle = 1 + +/obj/structure/fluff/divine/powerpylon + name = "power pylon" + desc = "A pylon which increases the deity's rate it can influence the world." + icon_state = "powerpylon" + can_buckle = 1 + +/obj/structure/fluff/divine/defensepylon + name = "defense pylon" + desc = "A pylon which is blessed to withstand many blows, and fire strong bolts at nonbelievers. A god can toggle it." + icon_state = "defensepylon" + +/obj/structure/fluff/divine/shrine + name = "shrine" + desc = "A shrine dedicated to a deity." + icon_state = "shrine" \ No newline at end of file diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index c6284f25056..91a840b1e3c 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -264,17 +264,8 @@ var/turf/T = get_turf(src) var/obj/structure/cable/C = T.get_cable_node() if(C) - var/mob/living/closest_mob - for(var/A in oview(src, 3)) - if(istype(A, /mob/living)) - var/dist = get_dist(src, A) - if(dist <= 3) - closest_mob = A - if(closest_mob) - var/shock_damage = C.powernet.avail * 0.0002//setting shock damage for later. equals 1/5000 the power in the grid - src.Beam(closest_mob, icon_state="lightning[rand(1,12)]", time=5) - closest_mob.electrocute_act(shock_damage, src, 1)//ZAP, damage should be about 40 with 200000W - playsound(src.loc, 'sound/magic/LightningShock.ogg', 100, 1, extrarange = 5) + playsound(src.loc, 'sound/magic/LightningShock.ogg', 100, 1, extrarange = 5) + tesla_zap(src, 3, C.powernet.avail * 0.01) //Zap for 1/100 of the amount of power. At a million watts in the grid, it will be as powerful as a tesla revolver shot. take_damage(tforce) /obj/structure/grille/storage_contents_dump_act(obj/item/weapon/storage/src_object, mob/user) diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index 042ce6b307d..56e81172352 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -20,6 +20,22 @@ var/obj/F = new /obj/structure/kitchenspike(src.loc,) transfer_fingerprints_to(F) qdel(src) + else if(istype(I, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = I + if(!WT.remove_fuel(0, user)) + return + user << "You begin cutting \the [src] apart..." + playsound(src.loc, "sound/items/Welder.ogg", 40, 1) + if(do_after(user, 40/WT.toolspeed, 1, target = src)) + if(!WT.isOn()) + return + playsound(src.loc, "sound/items/Welder.ogg", 50, 1) + visible_message("[user] slices apart \the [src].", + "You cut \the [src] apart with \the [WT].", + "You hear welding.") + new /obj/item/stack/sheet/metal(src.loc, 4) + qdel(src) + return else return ..() diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 1d452fdc76c..9a9e11d2091 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -391,6 +391,7 @@ icon = 'icons/obj/smooth_structures/brass_table.dmi' icon_state = "brass_table" frame = /obj/structure/table_frame/brass + framestack = /obj/item/stack/sheet/brass buildstack = /obj/item/stack/sheet/brass framestackamount = 1 buildstackamount = 1 diff --git a/code/game/gamemodes/handofgod/traps.dm b/code/game/objects/structures/traps.dm similarity index 76% rename from code/game/gamemodes/handofgod/traps.dm rename to code/game/objects/structures/traps.dm index b39475f0ce1..b6c9e0ba7bb 100644 --- a/code/game/gamemodes/handofgod/traps.dm +++ b/code/game/objects/structures/traps.dm @@ -1,19 +1,14 @@ - -/obj/structure/divine/trap +/obj/structure/trap name = "IT'S A TARP" desc = "stepping on me is a guaranteed bad day" + icon = 'icons/obj/hand_of_god_structures.dmi' icon_state = "trap" density = 0 alpha = 30 //initially quite hidden when not "recharging" - health = 20 - maxhealth = 20 - trap = TRUE - autocolours = FALSE var/last_trigger = 0 var/time_between_triggers = 600 //takes a minute to recharge - -/obj/structure/divine/trap/Crossed(atom/movable/AM) +/obj/structure/trap/Crossed(atom/movable/AM) if(last_trigger + time_between_triggers > world.time) return alpha = initial(alpha) @@ -24,8 +19,7 @@ trap_effect(L) animate(src, alpha = initial(alpha), time = time_between_triggers) - -/obj/structure/divine/trap/examine(mob/user) +/obj/structure/trap/examine(mob/user) ..() if(!isliving(user)) //bad ghosts, stop trying to powergame from beyond the grave return @@ -34,17 +28,15 @@ animate(src, alpha = initial(alpha), time = time_between_triggers) -/obj/structure/divine/trap/proc/trap_effect(mob/living/L) +/obj/structure/trap/proc/trap_effect(mob/living/L) return - -/obj/structure/divine/trap/stun +/obj/structure/trap/stun name = "shock trap" desc = "A trap that will shock you, it will burn your flesh and render you immobile, You'd better avoid it." icon_state = "trap-shock" - -/obj/structure/divine/trap/stun/trap_effect(mob/living/L) +/obj/structure/trap/stun/trap_effect(mob/living/L) L << "You are paralyzed from the intense shock!" L.Weaken(5) var/turf/Lturf = get_turf(L) @@ -52,13 +44,13 @@ new /obj/effect/particle_effect/sparks(Lturf) -/obj/structure/divine/trap/fire +/obj/structure/trap/fire name = "flame trap" desc = "A trap that will set you ablaze. You'd better avoid it." icon_state = "trap-fire" -/obj/structure/divine/trap/fire/trap_effect(mob/living/L) +/obj/structure/trap/fire/trap_effect(mob/living/L) L << "Spontaneous combustion!" L.Weaken(1) var/turf/Lturf = get_turf(L) @@ -66,26 +58,26 @@ new /obj/effect/particle_effect/sparks(Lturf) -/obj/structure/divine/trap/chill +/obj/structure/trap/chill name = "frost trap" desc = "A trap that will chill you to the bone. You'd better avoid it." icon_state = "trap-frost" -/obj/structure/divine/trap/chill/trap_effect(mob/living/L) +/obj/structure/trap/chill/trap_effect(mob/living/L) L << "You're frozen solid!" L.Weaken(1) L.bodytemperature -= 300 new /obj/effect/particle_effect/sparks(get_turf(L)) -/obj/structure/divine/trap/damage +/obj/structure/trap/damage name = "earth trap" desc = "A trap that will summon a small earthquake, just for you. You'd better avoid it." icon_state = "trap-earth" -/obj/structure/divine/trap/damage/trap_effect(mob/living/L) +/obj/structure/trap/damage/trap_effect(mob/living/L) L << "The ground quakes beneath your feet!" L.Weaken(5) L.adjustBruteLoss(35) @@ -94,16 +86,14 @@ new /obj/structure/flora/rock(Lturf) -/obj/structure/divine/trap/ward +/obj/structure/trap/ward name = "divine ward" desc = "A divine barrier, It looks like you could destroy it with enough effort, or wait for it to dissipate..." icon_state = "ward" - health = 150 - maxhealth = 150 density = 1 time_between_triggers = 1200 //Exists for 2 minutes -/obj/structure/divine/trap/ward/New() +/obj/structure/trap/ward/New() ..() QDEL_IN(src, time_between_triggers) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index efcc4ec6499..9b076bcd5c2 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -516,19 +516,20 @@ /obj/structure/window/reinforced/clockwork/New(loc, direct) ..() + for(var/obj/item/I in debris) + debris -= I + qdel(I) if(!fulltile) if(direct) var/obj/effect/E = PoolOrNew(/obj/effect/overlay/temp/ratvar/window/single, get_turf(src)) setDir(direct) E.setDir(direct) made_glow = TRUE + debris += new/obj/item/stack/sheet/brass(src, 1) else PoolOrNew(/obj/effect/overlay/temp/ratvar/window, get_turf(src)) made_glow = TRUE - for(var/obj/item/I in debris) - debris -= I - qdel(I) - debris += new/obj/item/stack/sheet/brass(src) + debris += new/obj/item/stack/sheet/brass(src, 2) change_construction_value(fulltile ? 3 : 2) /obj/structure/window/reinforced/clockwork/setDir(direct) diff --git a/code/game/turfs/simulated/dirtystation.dm b/code/game/turfs/simulated/dirtystation.dm index 2d65237947c..f3428beef4a 100644 --- a/code/game/turfs/simulated/dirtystation.dm +++ b/code/game/turfs/simulated/dirtystation.dm @@ -3,6 +3,8 @@ //Conspicuously not-recent versions of suspicious cleanables +//This file was made not awful by Xhuis on September 13, 2016 + /obj/effect/decal/cleanable/blood/old name = "dried blood" desc = "Looks like it's been here a while. Eew." @@ -10,7 +12,7 @@ /obj/effect/decal/cleanable/blood/old/New() ..() - icon_state += "-old" + icon_state += "-old" //This IS necessary because the parent /blood type uses icon randomization. blood_DNA["Non-human DNA"] = "A+" /obj/effect/decal/cleanable/blood/gibs/old @@ -20,8 +22,8 @@ /obj/effect/decal/cleanable/blood/gibs/old/New() ..() - icon_state += "-old" setDir(pick(1,2,4,8)) + icon_state += "-old" blood_DNA["Non-human DNA"] = "A+" /obj/effect/decal/cleanable/vomit/old @@ -36,26 +38,25 @@ name = "dusty robot debris" desc = "Looks like nobody has touched this in a while." - //Making the station dirty, one tile at a time. Called by master controller's setup_objects /turf/open/floor/proc/MakeDirty() if(prob(66)) //fastest possible exit 2/3 of the time return - // These look weird if you make them dirty - if(istype(src, /turf/open/floor/carpet) || istype(src, /turf/open/floor/grass) || istype(src, /turf/open/floor/plating/beach) || istype(src, /turf/open/floor/holofloor)|| istype(src, /turf/open/floor/plating/ironsand)) + if(!(flags & CAN_BE_DIRTY)) return if(locate(/obj/structure/grille) in contents) return - var/area/A = loc + var/area/A = get_area(src) - //zero dirt - if(!istype(A) || istype(A, /area/centcom) || istype(A, /area/holodeck) || istype(A, /area/library) || istype(A, /area/janitor) || istype(A, /area/chapel) || istype(A, /area/mine/explored) || istype(A, /area/mine/unexplored) || istype(A, /area/solar) || istype(A, /area/atmos) || istype(A, /area/medical/virology)) + if(A && !(A.flags & CAN_BE_DIRTY)) return + //The code below here isn't exactly optimal, but because of the individual decals that each area uses it's still applicable. + //high dirt - 1/3 if(istype(A, /area/toxins/test_area) || istype(A, /area/mine/production) || istype(A, /area/mine/living_quarters) || istype(A, /area/mine/north_outpost) || istype(A, /area/mine/west_outpost) || istype(A, /area/wreck) || istype(A, /area/derelict) || istype(A, /area/djstation)) new /obj/effect/decal/cleanable/dirt(src) //vanilla, but it works @@ -117,15 +118,16 @@ new /obj/effect/decal/cleanable/blood/gibs/old(src) else new /obj/effect/decal/cleanable/blood/old(src) - else - if(prob(30)) - if(istype(A, /area/medical/morgue)) - new /obj/item/weapon/ectoplasm(src) - else - new /obj/effect/decal/cleanable/vomit/old(src) + else if(prob(30)) + if(istype(A, /area/medical/morgue)) + new /obj/item/weapon/ectoplasm(src) + else + new /obj/effect/decal/cleanable/vomit/old(src) return if(istype(A, /area/toxins)) if(prob(20)) new /obj/effect/decal/cleanable/greenglow(src) //this cleans itself up but it might startle you when you see it. return + + return TRUE diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index edefd3b9f66..f4e9934dd27 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -29,9 +29,11 @@ /turf/open/floor/grass name = "grass patch" + desc = "You can't tell if this is real grass or just cheap plastic imitation." icon_state = "grass" floor_tile = /obj/item/stack/tile/grass broken_states = list("sand") + flags = NONE var/ore_type = /obj/item/weapon/ore/glass /turf/open/floor/grass/New() @@ -43,7 +45,8 @@ if(istype(C, /obj/item/weapon/shovel) && params) new ore_type(src) new ore_type(src) //Make some sand if you shovel grass - user << "You shovel [src]." + user.visible_message("[user] digs up [src].", "You uproot [src].") + playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1) make_plating() if(..()) return @@ -83,13 +86,15 @@ /turf/open/floor/carpet - name = "Carpet" + name = "carpet" + desc = "Soft velvet carpeting. Feels good between your toes." icon = 'icons/turf/floors/carpet.dmi' icon_state = "carpet" floor_tile = /obj/item/stack/tile/carpet broken_states = list("damaged") smooth = SMOOTH_TRUE canSmoothWith = null + flags = NONE /turf/open/floor/carpet/New() ..() diff --git a/code/game/turfs/simulated/floor/light_floor.dm b/code/game/turfs/simulated/floor/light_floor.dm index e4895097777..da67666b25d 100644 --- a/code/game/turfs/simulated/floor/light_floor.dm +++ b/code/game/turfs/simulated/floor/light_floor.dm @@ -1,5 +1,6 @@ /turf/open/floor/light - name = "Light floor" + name = "light floor" + desc = "A wired glass tile embedded into the floor." luminosity = 5 icon_state = "light_on" floor_tile = /obj/item/stack/tile/light diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm index 86f5d417620..a1d8ea6dfdf 100644 --- a/code/game/turfs/simulated/floor/misc_floor.dm +++ b/code/game/turfs/simulated/floor/misc_floor.dm @@ -1,5 +1,5 @@ /turf/open/floor/goonplaque - name = "Commemorative Plaque" + name = "commemorative plaque" icon_state = "plaque" desc = "\"This is a plaque in honour of our comrades on the G4407 Stations. Hopefully TG4407 model can live up to your fame and fortune.\" Scratched in beneath that is a crude image of a meteor and a spaceman. The spaceman is laughing. The meteor is exploding." floor_tile = /obj/item/stack/tile/plasteel @@ -27,35 +27,42 @@ floor_tile = /obj/item/stack/tile/plasteel /turf/open/floor/plating/beach - name = "Beach" + name = "beach" icon = 'icons/misc/beach.dmi' + flags = NONE /turf/open/floor/plating/beach/ex_act(severity, target) contents_explosion(severity, target) /turf/open/floor/plating/beach/sand - name = "Sand" + name = "sand" + desc = "Surf's up." icon_state = "sand" baseturf = /turf/open/floor/plating/beach/sand /turf/open/floor/plating/beach/coastline_t - name = "Coastline" + name = "coastline" + desc = "Tide's high tonight. Charge your batons." icon_state = "sandwater_t" baseturf = /turf/open/floor/plating/beach/coastline_t /turf/open/floor/plating/beach/coastline_b - name = "Coastline" + name = "coastline" icon_state = "sandwater_b" baseturf = /turf/open/floor/plating/beach/coastline_b /turf/open/floor/plating/beach/water - name = "Water" + name = "water" + desc = "You get the feeling that nobody's bothered to actually make this water functional..." icon_state = "water" baseturf = /turf/open/floor/plating/beach/water +/turf/open/floor/plating/ironsand + name = "iron sand" + desc = "Like sand, but more metal." + /turf/open/floor/plating/ironsand/New() ..() - name = "Iron Sand" icon_state = "ironsand[rand(1,15)]" /turf/open/floor/plating/ironsand/burn_tile() diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index e06fd5bf633..8e4841da760 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -235,6 +235,9 @@ slowdown = 2 luminosity = 1 +/turf/open/floor/plating/lava/ex_act() + return + /turf/open/floor/plating/lava/airless initial_gas_mix = "TEMP=2.7" diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 4a73e76ba90..2c4c0577749 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -13,7 +13,7 @@ var/PathNode/PNode = null //associated PathNode in the A* algorithm - flags = 0 + flags = CAN_BE_DIRTY var/list/proximity_checkers = list() diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index 07da6355d06..199e00dfd23 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -478,66 +478,6 @@ dat += "| Red Deity | ||
| Red Deity: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | " - dat += "PM | " - dat += "FLW |
| Blue Deity | ||
| Blue Deity: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | " - dat += "PM | " - dat += "FLW |
| Red Deity Prophets | ||
| Red Deity Prophet: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | " - dat += "PM | " - dat += "FLW |
| Blue Deity Prophets | ||
| Blue Deity Prophet: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | " - dat += "PM | " - dat += "FLW |
| Red Deity Followers | ||
| Red Deity Followers: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | " - dat += "PM | " - dat += "FLW |
| Blue Deity Followers | ||
| Blue Deity Followers: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | " - dat += "PM | " - dat += "FLW |
| Traitors | " + dat += " | "
- dat += "Alien/Mutant Color" + dat += "Mutant Color" dat += " Change" @@ -299,7 +301,14 @@ var/list/preferences_datums = list() dat += "[features["body_markings"]] " dat += " | "
+ if("legs" in pref_species.mutant_bodyparts)
+ dat += ""
+ dat += "Legs" + + dat += "[features["legs"]]" + + dat += " | "
if(config.mutant_humans)
if("tail_human" in pref_species.mutant_bodyparts)
@@ -986,6 +995,12 @@ var/list/preferences_datums = list()
if(new_body_markings)
features["body_markings"] = new_body_markings
+ if("legs")
+ var/new_legs
+ new_legs = input(user, "Choose your character's legs:", "Character Preference") as null|anything in legs_list
+ if(new_legs)
+ features["legs"] = new_legs
+
if("s_tone")
var/new_s_tone = input(user, "Choose your character's skin-tone:", "Character Preference") as null|anything in skin_tones
if(new_s_tone)
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 5042ae817ba..ee624a6c99f 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -2,7 +2,7 @@
#define SAVEFILE_VERSION_MIN 10
//This is the current version, anything below this will attempt to update (if it's not obsolete)
-#define SAVEFILE_VERSION_MAX 16
+#define SAVEFILE_VERSION_MAX 17
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
This proc checks if the current directory of the savefile S needs updating
@@ -97,7 +97,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
ignoring = list()
if(current_version < 15)
toggles |= SOUND_ANNOUNCEMENTS
-
+
//should this proc get fairly long (say 3 versions long),
//just increase SAVEFILE_VERSION_MIN so it's not as far behind
@@ -123,7 +123,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
joblessrole = BERANDOMJOB
else
joblessrole = BEASSISTANT
-
+ if(current_version < 17)
+ features["legs"] = "Normal Legs"
+
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
@@ -171,6 +173,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["ignoring"] >> ignoring
S["ghost_hud"] >> ghost_hud
S["inquisitive_ghost"] >> inquisitive_ghost
+ S["uses_glasses_colour"]>> uses_glasses_colour
//try to fix any outdated data if necessary
if(needs_update >= 0)
@@ -222,6 +225,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["ignoring"] << ignoring
S["ghost_hud"] << ghost_hud
S["inquisitive_ghost"] << inquisitive_ghost
+ S["uses_glasses_colour"]<< uses_glasses_colour
return 1
@@ -283,6 +287,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_lizard_frills"] >> features["frills"]
S["feature_lizard_spines"] >> features["spines"]
S["feature_lizard_body_markings"] >> features["body_markings"]
+ S["feature_lizard_legs"] >> features["legs"]
if(!config.mutant_humans)
features["tail_human"] = "none"
features["ears"] = "none"
@@ -348,6 +353,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
features["frills"] = sanitize_inlist(features["frills"], frills_list)
features["spines"] = sanitize_inlist(features["spines"], spines_list)
features["body_markings"] = sanitize_inlist(features["body_markings"], body_markings_list)
+ features["feature_lizard_legs"] = sanitize_inlist(features["legs"], legs_list, "Normal Legs")
joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole))
job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high))
@@ -399,6 +405,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_lizard_frills"] << features["frills"]
S["feature_lizard_spines"] << features["spines"]
S["feature_lizard_body_markings"] << features["body_markings"]
+ S["feature_lizard_legs"] << features["legs"]
S["clown_name"] << custom_names["clown"]
S["mime_name"] << custom_names["mime"]
S["ai_name"] << custom_names["ai"]
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 3a848e8d52a..d347342d22c 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -368,9 +368,10 @@ BLIND // can't see anything
var/random_sensor = 1
var/sensor_mode = 0 /* 1 = Report living/dead, 2 = Report detailed damages, 3 = Report location */
var/can_adjust = 1
- var/adjusted = 0
+ var/adjusted = NORMAL_STYLE
var/alt_covers_chest = 0 // for adjusted/rolled-down jumpsuits, 0 = exposes chest and arms, 1 = exposes arms only
var/obj/item/clothing/tie/hastie = null
+ var/mutantrace_variation = NO_MUTANTRACE_VARIATION //Are there special sprites for specific situations? Don't use this unless you need to.
/obj/item/clothing/under/worn_overlays(var/isinhands = FALSE)
. = list()
@@ -393,9 +394,24 @@ BLIND // can't see anything
if(random_sensor)
//make the sensor mode favor higher levels, except coords.
sensor_mode = pick(0, 1, 1, 2, 2, 2, 3, 3)
- adjusted = 0
+ adjusted = NORMAL_STYLE
..()
+/obj/item/clothing/under/equipped(mob/user, slot)
+ ..()
+ if(adjusted)
+ adjusted = NORMAL_STYLE
+ fitted = initial(fitted)
+ if(!alt_covers_chest)
+ body_parts_covered |= CHEST
+
+ if(mutantrace_variation && ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(DIGITIGRADE in H.dna.species.specflags)
+ adjusted = DIGITIGRADE_STYLE
+ H.update_inv_w_uniform()
+
+
/obj/item/clothing/under/attackby(obj/item/I, mob/user, params)
if(!attachTie(I, user))
..()
@@ -532,25 +548,29 @@ BLIND // can't see anything
usr << "You adjust the suit to wear it more casually."
else
usr << "You adjust the suit back to normal."
- usr.update_inv_w_uniform()
+ if(ishuman(usr))
+ var/mob/living/carbon/human/H = usr
+ H.update_inv_w_uniform()
+ H.update_body()
/obj/item/clothing/under/proc/toggle_jumpsuit_adjust()
+ if(adjusted == DIGITIGRADE_STYLE)
+ return
adjusted = !adjusted
if(adjusted)
if(fitted != FEMALE_UNIFORM_TOP)
fitted = NO_FEMALE_UNIFORM
- if (alt_covers_chest) // for the special snowflake suits that don't expose the chest when adjusted
- body_parts_covered = CHEST|GROIN|LEGS
- else
- body_parts_covered = GROIN|LEGS
+ if(!alt_covers_chest) // for the special snowflake suits that expose the chest when adjusted
+ body_parts_covered &= ~CHEST
else
fitted = initial(fitted)
- body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ if(!alt_covers_chest)
+ body_parts_covered |= CHEST
return adjusted
/obj/item/clothing/under/examine(mob/user)
..()
- if(src.adjusted)
+ if(src.adjusted == ALT_STYLE)
user << "Alt-click on [src] to wear it normally."
else
user << "Alt-click on [src] to wear it casually."
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index 19bf143a1cd..8ca4bf66cc4 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -1,6 +1,7 @@
/obj/item/clothing/glasses
name = "glasses"
materials = list(MAT_GLASS = 250)
+ var/glass_colour_type = null //colors your vision when worn
//called when thermal glasses are emped.
/obj/item/clothing/glasses/proc/thermal_overload()
@@ -23,6 +24,7 @@
darkness_view = 2
vision_flags = SEE_TURFS
invis_view = SEE_INVISIBLE_MINIMUM
+ glass_colour_type = /datum/client_colour/glass_colour/lightgreen
/obj/item/clothing/glasses/meson/night
name = "Night Vision Optical Meson Scanner"
@@ -31,6 +33,7 @@
item_state = "nvgmeson"
origin_tech = "magnets=4;engineering=5;plasmatech=4"
darkness_view = 8
+ glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/meson/gar
name = "gar mesons"
@@ -52,6 +55,7 @@
origin_tech = "magnets=2;engineering=1"
scan_reagents = 1 //You can see reagents while wearing science goggles
actions_types = list(/datum/action/item_action/toggle_research_scanner)
+ glass_colour_type = /datum/client_colour/glass_colour/purple
/obj/item/clothing/glasses/science/item_action_slot_check(slot)
if(slot == slot_glasses)
@@ -65,6 +69,7 @@
origin_tech = "materials=4;magnets=4;plasmatech=4;engineering=4"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM
+ glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/eyepatch
name = "eyepatch"
@@ -85,6 +90,7 @@
item_state = "glasses"
origin_tech = "magnets=3;engineering=3"
vision_flags = SEE_OBJS
+ glass_colour_type = /datum/client_colour/glass_colour/lightblue
/obj/item/clothing/glasses/material/mining
name = "Optical Material Scanner"
@@ -105,6 +111,7 @@
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
+ glass_colour_type = /datum/client_colour/glass_colour/lightgreen
/obj/item/clothing/glasses/regular
name = "Prescription Glasses"
@@ -133,7 +140,7 @@
darkness_view = 1
flash_protect = 1
tint = 1
-
+ glass_colour_type = /datum/client_colour/glass_colour/gray
dog_fashion = /datum/dog_fashion/head
/obj/item/clothing/glasses/sunglasses/reagent
@@ -173,6 +180,7 @@
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
+ glass_colour_type = /datum/client_colour/glass_colour/orange
/obj/item/clothing/glasses/sunglasses/gar/supergar
desc = "We evolve past the person we were a minute before. Little by little we advance with each turn. That's how a drill works!"
@@ -181,6 +189,7 @@
item_state = "gar"
force = 12
throwforce = 12
+ glass_colour_type = /datum/client_colour/glass_colour/red
/obj/item/clothing/glasses/welding
name = "welding goggles"
@@ -193,6 +202,7 @@
tint = 2
flags_cover = GLASSESCOVERSEYES
visor_flags_inv = HIDEEYES
+ glass_colour_type = /datum/client_colour/glass_colour/gray
/obj/item/clothing/glasses/welding/attack_self()
@@ -230,6 +240,7 @@
vision_flags = SEE_MOBS
invis_view = 2
flash_protect = 0
+ glass_colour_type = /datum/client_colour/glass_colour/red
/obj/item/clothing/glasses/thermal/emp_act(severity)
thermal_overload()
@@ -273,12 +284,14 @@
desc = "A sweet pair of orange shades."
icon_state = "orangeglasses"
item_state = "orangeglasses"
+ glass_colour_type = /datum/client_colour/glass_colour/lightorange
/obj/item/clothing/glasses/red
name = "red glasses"
desc = "A sweet pair of red shades."
icon_state = "redglasses"
item_state = "redglasses"
+ glass_colour_type = /datum/client_colour/glass_colour/red
/obj/item/clothing/glasses/godeye
name = "eye of god"
@@ -356,3 +369,35 @@
icon_state = "gar"
item_state = "gar"
+
+/obj/item/clothing/glasses/AltClick(mob/user)
+ if(glass_colour_type && ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(H.client)
+ if(H.client.prefs)
+ if(src == H.glasses)
+ H.client.prefs.uses_glasses_colour = !H.client.prefs.uses_glasses_colour
+ if(H.client.prefs.uses_glasses_colour)
+ H << "You will now see glasses colors."
+ else
+ H << "You will no longer see glasses colors."
+ H.update_glasses_color(src, 1)
+ else
+ return ..()
+
+/obj/item/clothing/glasses/proc/change_glass_color(mob/living/carbon/human/H, datum/client_colour/glass_colour/new_color_type)
+ var/old_colour_type = glass_colour_type
+ if(!new_color_type || ispath(new_color_type)) //the new glass colour type must be null or a path.
+ glass_colour_type = new_color_type
+ if(H && H.glasses == src)
+ if(old_colour_type)
+ H.remove_client_colour(old_colour_type)
+ if(glass_colour_type)
+ H.update_glasses_color(src, 1)
+
+
+/mob/living/carbon/human/proc/update_glasses_color(obj/item/clothing/glasses/G, glasses_equipped)
+ if(client && client.prefs.uses_glasses_colour && glasses_equipped)
+ add_client_colour(G.glass_colour_type)
+ else
+ remove_client_colour(G.glass_colour_type)
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index ba07bdd1aba..847208a09f4 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -6,6 +6,7 @@
var/hud_type = null
/obj/item/clothing/glasses/hud/equipped(mob/living/carbon/human/user, slot)
+ ..()
if(hud_type && slot == slot_glasses)
var/datum/atom_hud/H = huds[hud_type]
H.add_hud_to(user)
@@ -33,6 +34,7 @@
icon_state = "healthhud"
origin_tech = "magnets=3;biotech=2"
hud_type = DATA_HUD_MEDICAL_ADVANCED
+ glass_colour_type = /datum/client_colour/glass_colour/lightblue
/obj/item/clothing/glasses/hud/health/night
name = "Night Vision Health Scanner HUD"
@@ -42,6 +44,7 @@
origin_tech = "magnets=4;biotech=4;plasmatech=4;engineering=5"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM
+ glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/hud/diagnostic
name = "Diagnostic HUD"
@@ -49,6 +52,7 @@
icon_state = "diagnostichud"
origin_tech = "magnets=2;engineering=2"
hud_type = DATA_HUD_DIAGNOSTIC
+ glass_colour_type = /datum/client_colour/glass_colour/lightorange
/obj/item/clothing/glasses/hud/diagnostic/night
name = "Night Vision Diagnostic HUD"
@@ -58,6 +62,7 @@
origin_tech = "magnets=4;powerstorage=4;plasmatech=4;engineering=5"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM
+ glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/hud/security
name = "Security HUD"
@@ -65,6 +70,7 @@
icon_state = "securityhud"
origin_tech = "magnets=3;combat=2"
hud_type = DATA_HUD_SECURITY_ADVANCED
+ glass_colour_type = /datum/client_colour/glass_colour/red
/obj/item/clothing/glasses/hud/security/chameleon
name = "Chamleon Security HUD"
@@ -88,6 +94,7 @@
darkness_view = 1
flash_protect = 1
tint = 1
+ glass_colour_type = /datum/client_colour/glass_colour/darkred
/obj/item/clothing/glasses/hud/security/night
name = "Night Vision Security HUD"
@@ -96,6 +103,7 @@
origin_tech = "magnets=4;combat=4;plasmatech=4;engineering=5"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM
+ glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/hud/security/sunglasses/gars
name = "HUD gar glasses"
@@ -151,16 +159,20 @@
hud_type = DATA_HUD_SECURITY_ADVANCED
vision_flags = SEE_MOBS
invis_view = 2
+ glass_colour_type = /datum/client_colour/glass_colour/red
/obj/item/clothing/glasses/hud/toggle/thermal/attack_self(mob/user)
..()
switch (hud_type)
if (DATA_HUD_MEDICAL_ADVANCED)
icon_state = "meson"
+ change_glass_color(user, /datum/client_colour/glass_colour/green)
if (DATA_HUD_SECURITY_ADVANCED)
icon_state = "thermal"
+ change_glass_color(user, /datum/client_colour/glass_colour/red)
else
icon_state = "purple"
+ change_glass_color(user, /datum/client_colour/glass_colour/purple)
user.update_inv_glasses()
/obj/item/clothing/glasses/hud/toggle/thermal/emp_act(severity)
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 2c60fbb8900..11e77d18c1f 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -85,6 +85,10 @@
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/weapon/tank/jetpack/suit))
if(jetpack)
@@ -494,6 +498,7 @@
desc = "A special hardsuit helmet designed for only the most fashionable of military figureheads."
armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
actions_types = list()
+ flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR //we want to see the mask
/obj/item/clothing/head/helmet/space/hardsuit/captain/attack_self()
return //Sprites required for flashlight
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 5c65c32af97..98c4e5e2d7d 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -321,6 +321,12 @@
icon_state = "nerdshirt"
item_state = "nerdshirt"
+/obj/item/clothing/suit/vapeshirt //wearing this is asking to get beat.
+ name = "Vape Naysh shirt"
+ desc = "A cheap white T-shirt with a big tacky \"VN\" on the front, Why would you wear this unironicly?"
+ icon_state = "vapeshirt"
+ item_state = "vapeshirt"
+
/obj/item/clothing/suit/jacket
name = "bomber jacket"
desc = "Aviators not included."
diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm
index 4d71d282588..980c9603357 100644
--- a/code/modules/clothing/suits/wiz_robe.dm
+++ b/code/modules/clothing/suits/wiz_robe.dm
@@ -150,7 +150,7 @@
burn_state = FLAMMABLE
/obj/item/clothing/suit/wizrobe/paper
- name = "papier-mâché robe"
+ name = "papier-mâché robe"
desc = "A robe held together by various bits of clear-tape and paste."
icon_state = "wizard-paper"
item_state = "wizrobe"
@@ -199,6 +199,7 @@
max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard
armor = list(melee = 30, bullet = 20, laser = 20, energy = 20, bomb = 20, bio = 20, rad = 20)
+ unacidable = 1
slowdown = 0
/obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard
@@ -209,6 +210,7 @@
min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
armor = list(melee = 30, bullet = 20, laser = 20, energy = 20, bomb = 20, bio = 20, rad = 20)
+ unacidable = 1
actions_types = null //No inbuilt light
/obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard/attack_self(mob/user)
diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm
index 6b6bad92bec..2f23d7a4eff 100644
--- a/code/modules/clothing/under/jobs/civilian.dm
+++ b/code/modules/clothing/under/jobs/civilian.dm
@@ -31,6 +31,8 @@
icon_state = "cargotech"
item_state = "lb_suit"
item_color = "cargo"
+ body_parts_covered = CHEST|GROIN|ARMS
+ mutantrace_variation = MUTANTRACE_VARIATION
/obj/item/clothing/under/rank/chaplain
diff --git a/code/modules/clothing/under/shorts.dm b/code/modules/clothing/under/shorts.dm
index 23e98a040c6..0da22fc678e 100644
--- a/code/modules/clothing/under/shorts.dm
+++ b/code/modules/clothing/under/shorts.dm
@@ -4,6 +4,7 @@
gender = PLURAL
body_parts_covered = GROIN
fitted = NO_FEMALE_UNIFORM
+ mutantrace_variation = MUTANTRACE_VARIATION
can_adjust = 0
/obj/item/clothing/under/shorts/red
diff --git a/code/modules/events/holiday/halloween.dm b/code/modules/events/holiday/halloween.dm
index 107c8f10920..b3f97136cb9 100644
--- a/code/modules/events/holiday/halloween.dm
+++ b/code/modules/events/holiday/halloween.dm
@@ -18,6 +18,9 @@
for(var/mob/living/simple_animal/pet/dog/corgi/Ian/Ian in mob_list)
Ian.place_on_head(new /obj/item/weapon/bedsheet(Ian))
+ for(var/mob/living/simple_animal/parrot/Poly/Poly in mob_list)
+ new /mob/living/simple_animal/parrot/Poly/ghost(Poly.loc)
+ qdel(Poly)
/datum/round_event/spooky/announce()
priority_announce(pick("RATTLE ME BONES!","THE RIDE NEVER ENDS!", "A SKELETON POPS OUT!", "SPOOKY SCARY SKELETONS!", "CREWMEMBERS BEWARE, YOU'RE IN FOR A SCARE!") , "THE CALL IS COMING FROM INSIDE THE HOUSE")
@@ -68,7 +71,7 @@
/obj/item/weapon/storage/spooky
name = "trick-o-treat bag"
- desc = "A Pumpkin shaped bag that holds all sorts of goodies!"
+ desc = "A pumpkin-shaped bag that holds all sorts of goodies!"
icon = 'icons/obj/halloween_items.dmi'
icon_state = "treatbag"
@@ -79,5 +82,7 @@
/obj/item/weapon/reagent_containers/food/snacks/sugarcookie/spookycoffin,
/obj/item/weapon/reagent_containers/food/snacks/candy_corn,
/obj/item/weapon/reagent_containers/food/snacks/candy,
- /obj/item/weapon/reagent_containers/food/snacks/chocolatebar)
+ /obj/item/weapon/reagent_containers/food/snacks/candiedapple,
+ /obj/item/weapon/reagent_containers/food/snacks/chocolatebar,
+ /obj/item/organ/brain ) // OH GOD THIS ISN'T CANDY!
new type(src)
diff --git a/code/modules/events/shuttle_loan.dm b/code/modules/events/shuttle_loan.dm
index 4649f851152..328e8af3268 100644
--- a/code/modules/events/shuttle_loan.dm
+++ b/code/modules/events/shuttle_loan.dm
@@ -3,6 +3,7 @@
#define SPIDER_GIFT 3
#define DEPARTMENT_RESUPPLY 4
#define ANTIDOTE_NEEDED 5
+#define PIZZA_DELIVERY 6
/datum/round_event_control/shuttle_loan
@@ -20,7 +21,7 @@
var/thanks_msg = "The cargo shuttle should return in five minutes. Have some supply points for your trouble."
/datum/round_event/shuttle_loan/start()
- dispatch_type = pick(HIJACK_SYNDIE, RUSKY_PARTY, SPIDER_GIFT, DEPARTMENT_RESUPPLY, ANTIDOTE_NEEDED)
+ dispatch_type = pick(HIJACK_SYNDIE, RUSKY_PARTY, SPIDER_GIFT, DEPARTMENT_RESUPPLY, ANTIDOTE_NEEDED, PIZZA_DELIVERY)
/datum/round_event/shuttle_loan/announce()
SSshuttle.shuttle_loan = src
@@ -37,6 +38,8 @@
bonus_points = 0
if(ANTIDOTE_NEEDED)
priority_announce("Cargo: Your station has been chosen for an epidemiological research project. Send us your cargo shuttle to receive your research samples.", "Centcom Research Initiatives")
+ if (PIZZA_DELIVERY)
+ priority_announce("Cargo: It looks like a neighbouring station accidentally delivered their pizza to you instead", "Centcom Spacepizza Division")
/datum/round_event/shuttle_loan/proc/loan_shuttle()
priority_announce(thanks_msg, "Cargo shuttle commandeered by Centcom.")
@@ -60,6 +63,8 @@
SSshuttle.centcom_message += "Department resupply incoming."
if(ANTIDOTE_NEEDED)
SSshuttle.centcom_message += "Virus samples incoming."
+ if(PIZZA_DELIVERY)
+ SSshuttle.centcom_message += "Pizza delivery for [world.name]"
/datum/round_event/shuttle_loan/tick()
if(dispatched)
@@ -165,6 +170,16 @@
for(var/i in 1 to 5)
var/decal = pick(/obj/effect/decal/cleanable/flour, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/oil)
new decal(pick_n_take(empty_shuttle_turfs))
+ if(PIZZA_DELIVERY)
+ shuttle_spawns.Add(/obj/item/pizzabox/margherita)
+ shuttle_spawns.Add(/obj/item/pizzabox/margherita)
+ shuttle_spawns.Add(/obj/item/pizzabox/meat)
+ shuttle_spawns.Add(/obj/item/pizzabox/meat)
+ shuttle_spawns.Add(/obj/item/pizzabox/vegetable)
+ if(prob(10))
+ shuttle_spawns.Add(/obj/item/pizzabox/bomb)
+ else
+ shuttle_spawns.Add(/obj/item/pizzabox/margherita)
var/false_positive = 0
while(shuttle_spawns.len && empty_shuttle_turfs.len)
@@ -181,3 +196,4 @@
#undef SPIDER_GIFT
#undef DEPARTMENT_RESUPPLY
#undef ANTIDOTE_NEEDED
+#undef PIZZA_DELIVERY
diff --git a/code/modules/food_and_drinks/food/snacks/meat.dm b/code/modules/food_and_drinks/food/snacks/meat.dm
index d006bfb6ee7..ae777bcbcd1 100644
--- a/code/modules/food_and_drinks/food/snacks/meat.dm
+++ b/code/modules/food_and_drinks/food/snacks/meat.dm
@@ -190,6 +190,22 @@
icon_state = "meatwheat_clump"
bitesize = 4
+/obj/item/weapon/reagent_containers/food/snacks/meat/rawbacon
+ name = "raw piece of bacon"
+ desc = "A raw piece of bacon."
+ icon_state = "bacon"
+ cooked_type = /obj/item/weapon/reagent_containers/food/snacks/meat/bacon
+ bitesize = 2
+ list_reagents = list("nutriment" = 1)
+ filling_color = "#B22222"
+
+/obj/item/weapon/reagent_containers/food/snacks/meat/bacon
+ name = "piece of bacon"
+ desc = "A delicious piece of bacon."
+ icon_state = "baconcooked"
+ list_reagents = list("nutriment" = 2)
+ bonus_reagents = list("nutriment" = 1, "vitamin" = 1)
+
////////////////////////////////////// MEAT STEAKS ///////////////////////////////////////////////////////////
@@ -272,7 +288,6 @@
name = "raw spider cutlet"
cooked_type = /obj/item/weapon/reagent_containers/food/snacks/meat/cutlet/spider
-
//Cooked cutlets
/obj/item/weapon/reagent_containers/food/snacks/meat/cutlet
@@ -298,5 +313,4 @@
name = "xeno cutlet"
/obj/item/weapon/reagent_containers/food/snacks/meat/cutlet/spider
- name = "spider cutlet"
-
+ name = "spider cutlet"
\ No newline at end of file
diff --git a/code/modules/food_and_drinks/food/snacks_burgers.dm b/code/modules/food_and_drinks/food/snacks_burgers.dm
index 4cab54e9891..77e04689317 100644
--- a/code/modules/food_and_drinks/food/snacks_burgers.dm
+++ b/code/modules/food_and_drinks/food/snacks_burgers.dm
@@ -203,3 +203,9 @@
desc = "It's still warm. The steam coming off of it looks like baseball."
icon_state = "baseball"
bonus_reagents = list("nutriment" = 1, "vitamin" = 1)
+
+/obj/item/weapon/reagent_containers/food/snacks/burger/baconburger
+ name = "bacon burger"
+ desc = "The perfect combination of all things American."
+ icon_state = "baconburger"
+ bonus_reagents = list("nutriment" = 8, "vitamin" = 1)
diff --git a/code/modules/food_and_drinks/food/snacks_other.dm b/code/modules/food_and_drinks/food/snacks_other.dm
index babef429153..a257234425d 100644
--- a/code/modules/food_and_drinks/food/snacks_other.dm
+++ b/code/modules/food_and_drinks/food/snacks_other.dm
@@ -315,4 +315,14 @@
desc = "The former skull of a damned human, filled with goliath meat. It has a decorative lava pool made of ketchup and hotsauce."
icon_state = "stuffed_legion"
bonus_reagents = list("vitamin" = 3, "capsaicin" = 1, "tricordrazine" = 5)
- list_reagents = list("nutriment" = 5, "vitamin" = 5, "capsaicin" = 2, "tricordrazine" = 10,)
\ No newline at end of file
+ list_reagents = list("nutriment" = 5, "vitamin" = 5, "capsaicin" = 2, "tricordrazine" = 10,)
+
+
+/obj/item/weapon/reagent_containers/food/snacks/powercrepe
+ name = "Powercrepe"
+ desc = "With great power, comes great crepes. It looks like a pancake filled with jelly but packs quite a punch."
+ icon_state = "powercrepe"
+ bonus_reagents = list("nutriment" = 5, "vitamin" = 3, "iron" = 10)
+ list_reagents = list("nutriment" = 10, "vitamin" = 5, "cherryjelly" = 5)
+ force = 15
+ w_class = 4
\ No newline at end of file
diff --git a/code/modules/food_and_drinks/kitchen_machinery/processor.dm b/code/modules/food_and_drinks/kitchen_machinery/processor.dm
index ebbe4b1e4d2..41b3b987986 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/processor.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/processor.dm
@@ -3,7 +3,7 @@
name = "food processor"
desc = "An industrial grinder used to process meat and other foods. Keep hands clear of intake area while operating."
icon = 'icons/obj/kitchen.dmi'
- icon_state = "processor"
+ icon_state = "processor1"
layer = BELOW_OBJ_LAYER
density = 1
anchored = 1
@@ -90,6 +90,10 @@
input = /obj/item/weapon/reagent_containers/food/snacks/meat/slab
output = /obj/item/weapon/reagent_containers/food/snacks/faggot
+/datum/food_processor_process/bacon
+ input = /obj/item/weapon/reagent_containers/food/snacks/meat/rawcutlet
+ output = /obj/item/weapon/reagent_containers/food/snacks/meat/rawbacon
+
/datum/food_processor_process/sweetpotato
input = /obj/item/weapon/reagent_containers/food/snacks/grown/potato/sweet
output = /obj/item/weapon/reagent_containers/food/snacks/yakiimo
@@ -185,7 +189,7 @@
if(src.processing)
user << "The processor is in the process of processing!"
return 1
- if(default_deconstruction_screwdriver(user, "processor1", "processor", O))
+ if(default_deconstruction_screwdriver(user, "processor", "processor1", O))
return
if(exchange_parts(user, O))
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
index 94b40722664..573574f4e9c 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
@@ -262,3 +262,14 @@
)
result = /obj/item/weapon/reagent_containers/food/snacks/burger/baseball
category = CAT_BURGER
+
+/datum/crafting_recipe/food/baconburger
+ name = "Bacon Burger"
+ reqs = list(
+ /obj/item/weapon/reagent_containers/food/snacks/meat/bacon = 3,
+ /obj/item/weapon/reagent_containers/food/snacks/cheesewedge = 1,
+ /obj/item/weapon/reagent_containers/food/snacks/bun = 1
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/burger/baconburger
+ category = CAT_BURGER
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm
index 8229391e50e..439db2986b0 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm
@@ -111,7 +111,7 @@
/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 3,
/datum/reagent/blood = 30,
/datum/reagent/consumable/sprinkles = 5,
- /datum/reagent/toxin/teslium = 1 //To shock the whole thing into life
+ /datum/reagent/teslium = 1 //To shock the whole thing into life
)
result = /mob/living/simple_animal/pet/cat/cak
category = CAT_CAKE //Cat! Haha, get it? CAT? GET IT???
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm
index 2127fa29d33..de9861bb80d 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm
@@ -259,7 +259,7 @@
category = CAT_MISCFOOD
-/datum/crafting_recipe/stuffedlegion
+/datum/crafting_recipe/food/stuffedlegion
name = "Stuffed legion"
time = 40
reqs = list(
@@ -271,7 +271,8 @@
result = /obj/item/weapon/reagent_containers/food/snacks/stuffedlegion
category = CAT_MISCFOOD
-/datum/crafting_recipe/lizardwine
+
+/datum/crafting_recipe/food/lizardwine
name = "Lizard wine"
time = 40
reqs = list(
@@ -280,3 +281,17 @@
)
result = /obj/item/weapon/reagent_containers/food/drinks/bottle/lizardwine
category = CAT_MISCFOOD
+
+
+/datum/crafting_recipe/food/powercrepe
+ name = "Powercrepe"
+ time = 40
+ reqs = list(
+ /obj/item/weapon/reagent_containers/food/snacks/flatdough = 1,
+ /datum/reagent/consumable/milk = 1,
+ /datum/reagent/consumable/cherryjelly = 5,
+ /obj/item/weapon/stock_parts/cell/super =1,
+ /obj/item/weapon/melee/sabre = 1
+ )
+ result = /obj/item/weapon/reagent_containers/food/snacks/powercrepe
+ category = CAT_MISCFOOD
diff --git a/code/modules/holodeck/areas.dm b/code/modules/holodeck/areas.dm
index cd6a74581be..3e7f4d2c825 100644
--- a/code/modules/holodeck/areas.dm
+++ b/code/modules/holodeck/areas.dm
@@ -3,6 +3,7 @@
icon_state = "Holodeck"
luminosity = 1
lighting_use_dynamic = 0
+ flags = 0
var/obj/machinery/computer/holodeck/linked
var/restricted = 0 // if true, program goes on emag list
diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm
index ed2021bc5f4..1a81a053890 100644
--- a/code/modules/holodeck/turfs.dm
+++ b/code/modules/holodeck/turfs.dm
@@ -3,16 +3,17 @@
thermal_conductivity = 0
broken_states = list("engine")
burnt_states = list("engine")
+ flags = NONE
-/turf/open/floor/holofloor/attackby(obj/item/weapon/W as obj, mob/user as mob)
+/turf/open/floor/holofloor/attackby(obj/item/I, mob/living/user)
return // HOLOFLOOR DOES NOT GIVE A FUCK
/turf/open/floor/holofloor/plating
- name = "Holodeck Projector Floor"
+ name = "holodeck projector floor"
icon_state = "engine"
/turf/open/floor/holofloor/plating/burnmix
- name = "Burn-mix Floor"
+ name = "burn-mix floor"
initial_gas_mix = "o2=2500;plasma=5000;TEMP=370"
/turf/open/floor/holofloor/grass
@@ -38,7 +39,7 @@
icon_state = "water"
/turf/open/floor/holofloor/asteroid
- name = "Asteroid"
+ name = "asteroid"
icon_state = "asteroid0"
/turf/open/floor/holofloor/asteroid/New()
@@ -55,7 +56,7 @@
..()
/turf/open/floor/holofloor/hyperspace
- name = "Hyperspace"
+ name = "hyperspace"
icon = 'icons/turf/space.dmi'
icon_state = "speedspace_ew_1"
@@ -68,7 +69,7 @@
icon_state = "speedspace_ns_[(x + 5*y + (y%2+1)*7)%15+1]"
/turf/open/floor/holofloor/carpet
- name = "Carpet"
+ name = "carpet"
desc = "Electrically inviting."
icon = 'icons/turf/floors/carpet.dmi'
icon_state = "carpet"
diff --git a/code/modules/jobs/job_types/cargo_service.dm b/code/modules/jobs/job_types/cargo_service.dm
index 460d9da5299..a5590867607 100644
--- a/code/modules/jobs/job_types/cargo_service.dm
+++ b/code/modules/jobs/job_types/cargo_service.dm
@@ -152,6 +152,7 @@ Cook
uniform = /obj/item/clothing/under/rank/chef
suit = /obj/item/clothing/suit/toggle/chef
head = /obj/item/clothing/head/chefhat
+ backpack_contents = list(/obj/item/weapon/sharpener = 1)
/datum/outfit/job/cook/pre_equip(mob/living/carbon/human/H)
..()
diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm
index 40c2a19addb..9109ddefc76 100644
--- a/code/modules/mining/abandoned_crates.dm
+++ b/code/modules/mining/abandoned_crates.dm
@@ -11,12 +11,12 @@
/obj/structure/closet/crate/secure/loot/New()
..()
- var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "z")
+ var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
code = ""
for(var/i = 0, i < codelen, i++)
var/dig = pick(digits)
code += dig
- digits -= dig //Player can enter codes with matching digits, but there are never matching digits in the answer
+ digits -= dig //there are never matching digits in the answer
var/loot = rand(1,100) //100 different crates with varying chances of spawning
switch(loot)
@@ -153,18 +153,26 @@
/obj/structure/closet/crate/secure/loot/attack_hand(mob/user)
if(locked)
user << "The crate is locked with a Deca-code lock."
- var/input = input(usr, "Enter [codelen] digits.", "Deca-Code Lock", "") as text
+ var/input = input(usr, "Enter [codelen] digits. All digits must be unique.", "Deca-Code Lock", "") as text
if(user.canUseTopic(src, 1))
+ var/list/sanitised = list()
+ var/sanitycheck = 1
+ for(var/i=1,i<=length(input),i++) //put the guess into a list
+ sanitised += text2num(copytext(input,i,i+1))
+ for(var/i=1,i<=(length(input)-1),i++) //compare each digit in the guess to all those following it
+ for(var/j=(i+1),j<=length(input),j++)
+ if(sanitised[i] == sanitised[j])
+ sanitycheck = null //if a digit is repeated, reject the input
if (input == code)
user << "The crate unlocks!"
locked = 0
cut_overlays()
add_overlay("securecrateg")
- else if (input == null || length(input) != codelen)
+ else if (input == null || sanitycheck == null || length(input) != codelen)
user << "You leave the crate alone."
else
user << "A red light flashes."
- lastattempt = replacetext(input, 0, "z")
+ lastattempt = input
attempts--
if(attempts == 0)
boom(user)
@@ -192,19 +200,21 @@
user << "* Anti-Tamper Bomb will activate after [src.attempts] failed access attempts."
if(lastattempt != null)
var/list/guess = list()
+ var/list/answer = list()
var/bulls = 0
var/cows = 0
- for(var/i = 1, i < codelen + 1, i++)
- var/a = copytext(lastattempt, i, i+1) //Stuff the code into the list
- guess += a
- guess[a] = i
- for(var/i in guess) //Go through list and count matches
- var/a = findtext(code, i)
- if(a == guess[i])
- ++bulls
- else if(a)
+ for(var/i=1,i<=length(lastattempt),i++)
+ guess += text2num(copytext(lastattempt,i,i+1))
+ for(var/i=1,i<=length(lastattempt),i++)
+ answer += text2num(copytext(code,i,i+1))
+ for(var/i = 1, i < codelen + 1, i++) // Go through list and count matches
+ if( answer.Find(guess[i],1,codelen+1))
++cows
- user << "Last code attempt had [bulls] correct digits at correct positions and [cows] correct digits at incorrect positions."
+ if( answer[i] == guess[i])
+ ++bulls
+ --cows
+
+ user << "Last code attempt, [lastattempt], had [bulls] correct digits at correct positions and [cows] correct digits at incorrect positions."
return
return ..()
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index c17e682949e..2545d47892c 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -48,7 +48,7 @@
if(16)
new /obj/item/weapon/guardiancreator(src)
if(17)
- new /obj/item/borg/upgrade/modkit/aoe/mobs(src)
+ new /obj/item/borg/upgrade/modkit/aoe/turfs/andmobs(src)
if(18)
new /obj/item/device/warp_cube/red(src)
if(19)
@@ -95,7 +95,7 @@
"
if(wisp.orbiting)
- var/atom/A = wisp.orbiting
+ var/atom/A = wisp.orbiting.orbiting
if(istype(A, /mob/living))
var/mob/living/M = A
M.sight &= ~SEE_MOBS
@@ -534,8 +534,15 @@
var/turf/T = get_turf(src)
var/list/contents = T.GetAllContents()
var/mob/dead/observer/current_spirits = list()
- for(var/mob/dead/observer/G in dead_mob_list)
- if(G.orbiting in contents)
+ var/list/orbiters = list()
+ for(var/thing in contents)
+ var/atom/A = thing
+ if (A.orbiters)
+ orbiters += A.orbiters
+
+ for(var/thing in orbiters)
+ if (isobserver(thing))
+ var/mob/dead/observer/G = thing
ghost_counter++
G.invisibility = 0
current_spirits |= G
@@ -579,7 +586,7 @@
switch(random)
if(1)
user << "Your appearence morphs to that of a very small humanoid ash dragon! You get to look like a freak without the cool abilities."
- H.dna.features = list("mcolor" = "A02720", "tail_lizard" = "Dark Tiger", "tail_human" = "None", "snout" = "Sharp", "horns" = "Curled", "ears" = "None", "wings" = "None", "frills" = "None", "spines" = "Long", "body_markings" = "Dark Tiger Body")
+ H.dna.features = list("mcolor" = "A02720", "tail_lizard" = "Dark Tiger", "tail_human" = "None", "snout" = "Sharp", "horns" = "Curled", "ears" = "None", "wings" = "None", "frills" = "None", "spines" = "Long", "body_markings" = "Dark Tiger Body", "legs" = "Digitigrade Legs")
H.eye_color = "fee5a3"
H.set_species(/datum/species/lizard)
if(2)
@@ -704,15 +711,13 @@
/obj/structure/closet/crate/necropolis/bubblegum/New()
..()
- var/loot = rand(1,4)
+ var/loot = rand(1,3)
switch(loot)
if(1)
- new /obj/item/weapon/antag_spawner/slaughter_demon(src)
- if(2)
new /obj/item/mayhem(src)
- if(3)
+ if(2)
new /obj/item/blood_contract(src)
- if(4)
+ if(3)
new /obj/item/weapon/gun/magic/staff/spellblade(src)
/obj/item/blood_contract
diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm
index fdb907cac4b..6c9143d943e 100644
--- a/code/modules/mining/machine_vending.dm
+++ b/code/modules/mining/machine_vending.dm
@@ -38,13 +38,14 @@
new /datum/data/mining_equipment("Mining Hardsuit", /obj/item/clothing/suit/space/hardsuit/mining, 2000),
new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/weapon/pickaxe/diamond, 2000),
new /datum/data/mining_equipment("Super Resonator", /obj/item/weapon/resonator/upgraded, 2500),
- new /datum/data/mining_equipment("KA White Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer, 200),
- new /datum/data/mining_equipment("KA Adjustable Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer/adjustable, 300),
- new /datum/data/mining_equipment("KA Super Chassis", /obj/item/borg/upgrade/modkit/chassis_mod, 400),
- new /datum/data/mining_equipment("KA Hyper Chassis", /obj/item/borg/upgrade/modkit/chassis_mod/orange, 500),
+ new /datum/data/mining_equipment("KA White Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer, 100),
+ new /datum/data/mining_equipment("KA Adjustable Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer/adjustable, 150),
+ new /datum/data/mining_equipment("KA Super Chassis", /obj/item/borg/upgrade/modkit/chassis_mod, 250),
+ new /datum/data/mining_equipment("KA Hyper Chassis", /obj/item/borg/upgrade/modkit/chassis_mod/orange, 300),
new /datum/data/mining_equipment("KA Range Increase", /obj/item/borg/upgrade/modkit/range, 1000),
new /datum/data/mining_equipment("KA Damage Increase", /obj/item/borg/upgrade/modkit/damage, 1000),
new /datum/data/mining_equipment("KA Cooldown Decrease",/obj/item/borg/upgrade/modkit/cooldown, 1000),
+ new /datum/data/mining_equipment("KA AoE Damage", /obj/item/borg/upgrade/modkit/aoe/mobs, 2000),
new /datum/data/mining_equipment("Point Transfer Card", /obj/item/weapon/card/mining_point_card, 500),
new /datum/data/mining_equipment("Mining Drone", /mob/living/simple_animal/hostile/mining_drone, 800),
new /datum/data/mining_equipment("Drone Melee Upgrade", /obj/item/device/mine_bot_ugprade, 400),
diff --git a/code/modules/mining/mine_areas.dm b/code/modules/mining/mine_areas.dm
index 10dbc16c516..9d133fe1b74 100644
--- a/code/modules/mining/mine_areas.dm
+++ b/code/modules/mining/mine_areas.dm
@@ -16,6 +16,7 @@
power_light = 0
outdoors = 1
ambientsounds = list('sound/ambience/ambimine.ogg')
+ flags = NONE
/area/mine/unexplored
name = "Mine"
@@ -29,12 +30,13 @@
power_light = 0
outdoors = 1
ambientsounds = list('sound/ambience/ambimine.ogg')
+ flags = NONE
/area/mine/lobby
- name = "Mining station"
+ name = "Mining Station"
/area/mine/storage
- name = "Mining station Storage"
+ name = "Mining Station Storage"
/area/mine/production
name = "Mining Station Starboard Wing"
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index 2438bd0b626..db741e5f04c 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -662,6 +662,10 @@
return 1
/turf/open/chasm/proc/drop(atom/movable/AM)
+ //Make sure the item is still there after our sleep
+ if(!AM || qdeleted(AM))
+ return
+
var/turf/T = locate(drop_x, drop_y, drop_z)
if(T)
AM.visible_message("[AM] falls into [src]!", "GAH! Ah... where are you?")
@@ -697,6 +701,9 @@
initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
/turf/open/chasm/straight_down/lava_land_surface/drop(atom/movable/AM)
+ //Make sure the item is still there after our sleep
+ if(!AM || qdeleted(AM))
+ return
AM.visible_message("[AM] falls into [src]!", "You stumble and stare into an abyss before you. It stares back, and you fall \
into the enveloping dark.")
if(isliving(AM))
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 8642e27ca31..3f36349ff7f 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -383,7 +383,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/orbitsize = (I.Width()+I.Height())*0.5
orbitsize -= (orbitsize/world.icon_size)*(world.icon_size*0.25)
- if(orbiting != target)
+ if(orbiting && orbiting.orbiting != target)
src << "Now orbiting [target]."
var/rot_seg
@@ -403,13 +403,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
orbit(target,orbitsize, FALSE, 20, rot_seg)
/mob/dead/observer/orbit()
- setDir(2 )//reset dir so the right directional sprites show up
+ setDir(2)//reset dir so the right directional sprites show up
+ ..()
+
+/mob/dead/observer/stop_orbit()
..()
//restart our floating animation after orbit is done.
- sleep 2 //orbit sets up a 2ds animation when it finishes, so we wait for that to end
- if (!orbiting) //make sure another orbit hasn't started
- pixel_y = 0
- animate(src, pixel_y = 2, time = 10, loop = -1)
+ pixel_y = 0
+ animate(src, pixel_y = 2, time = 10, loop = -1)
/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak
set category = "Ghost"
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index ecaf9f1c75f..377d8ac3b15 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -266,6 +266,7 @@
if(client)
client.screen -= I
I.layer = initial(I.layer)
+ I.appearance_flags &= ~NO_CLIENT_COLOR
I.forceMove(loc)
I.dropped(src)
return TRUE
diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm
index 0f4de4b6890..0ff617d7532 100644
--- a/code/modules/mob/living/carbon/alien/larva/life.dm
+++ b/code/modules/mob/living/carbon/alien/larva/life.dm
@@ -6,7 +6,7 @@
if (notransform)
return
- if(..())
+ if(..()) //not dead
// GROW!
if(amount_grown < max_grown)
amount_grown++
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 0198c4a1cf8..94ee29b74b0 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -672,7 +672,8 @@
if(B)
B.damaged_brain = 0
for(var/datum/disease/D in viruses)
- D.cure(0)
+ if (D.severity != NONTHREAT)
+ D.cure(0)
if(admin_revive)
regenerate_limbs()
handcuffed = initial(handcuffed)
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 4de7733bd26..96afa3055f4 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -9,6 +9,14 @@
if(head && (head.flags & HEADBANGPROTECT))
return 1
+//Overridden so we can handle when it hits a limb that doesn't exist
+mob/living/carbon/bullet_act(obj/item/projectile/P, def_zone)
+ var/obj/item/bodypart/affecting = get_bodypart(def_zone)
+ if(!affecting) //that zone is dismembered
+ . = bullet_act(P, "chest")//act on chest instead
+ else
+ . = ..()//Proceed with standard handling
+
/mob/living/carbon/check_projectile_dismemberment(obj/item/projectile/P, def_zone)
var/obj/item/bodypart/affecting = get_bodypart(def_zone)
if(affecting && affecting.dismemberable && affecting.get_damage() >= (affecting.max_damage - P.dismemberment))
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 535f7f39ffb..a3a7413932b 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -3,11 +3,12 @@
var/organnum = 0
if(def_zone)
+ //Can pass in a bodypart or zone, so lets shortcut that handling
if(islimb(def_zone))
return checkarmor(def_zone, type)
- var/obj/item/bodypart/affecting = get_bodypart(ran_zone(def_zone))
+ //Note the check_zone call, this changes UI target values to bodypart zones
+ var/obj/item/bodypart/affecting = get_bodypart(check_zone(def_zone))
return checkarmor(affecting, type)
- //If a specific bodypart is targetted, check how that bodypart is protected and return the value.
//If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values
for(var/X in bodyparts)
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 3283e04d22e..7a0cb8e246a 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -69,6 +69,8 @@
if(slot_glasses)
glasses = I
var/obj/item/clothing/glasses/G = I
+ if(G.glass_colour_type)
+ update_glasses_color(G, 1)
if(G.tint)
update_tint()
if(G.vision_correction)
@@ -144,6 +146,8 @@
else if(I == glasses)
glasses = null
var/obj/item/clothing/glasses/G = I
+ if(G.glass_colour_type)
+ update_glasses_color(G, 0)
if(G.tint)
update_tint()
if(G.vision_correction)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 0c3b27ba8d1..5d7003106aa 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -29,20 +29,26 @@
if (notransform)
return
- if(..())
+ if(..()) //not dead
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_life(src)
+ if(stat != DEAD)
//heart attack stuff
handle_heart()
+ if(stat != DEAD)
//Stuff jammed in your limbs hurts
handle_embedded_objects()
+
//Update our name based on whether our face is obscured/disfigured
name = get_visible_name()
dna.species.spec_life(src) // for mutantraces
+ if(stat != DEAD)
+ return 1
+
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
if((wear_suit && (wear_suit.flags & STOPSPRESSUREDMAGE)) && (head && (head.flags & STOPSPRESSUREDMAGE)))
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 852a19fd1ab..f250fa7cb85 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -164,11 +164,16 @@
if(exotic_bloodtype && C.dna.blood_type != exotic_bloodtype)
C.dna.blood_type = exotic_bloodtype
-
+ if(("legs" in C.dna.species.mutant_bodyparts) && C.dna.features["legs"] == "Digitigrade Legs")
+ specflags += DIGITIGRADE
+ if(DIGITIGRADE in specflags)
+ C.Digitigrade_Leg_Swap(FALSE)
/datum/species/proc/on_species_loss(mob/living/carbon/C)
if(C.dna.species.exotic_bloodtype)
C.dna.blood_type = random_blood_type()
+ if(DIGITIGRADE in specflags)
+ C.Digitigrade_Leg_Swap(TRUE)
/datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour)
H.remove_overlay(HAIR_LAYER)
@@ -258,8 +263,6 @@
var/list/standing = list()
- handle_mutant_bodyparts(H)
-
var/obj/item/bodypart/head/HD = H.get_bodypart("head")
if(!(H.disabilities & HUSK))
@@ -289,7 +292,7 @@
else
standing += image("icon"=U2.icon, "icon_state"="[U2.icon_state]_s", "layer"=-BODY_LAYER)
- if(H.socks && H.get_num_legs() >= 2)
+ if(H.socks && H.get_num_legs() >= 2 && !(DIGITIGRADE in specflags))
var/datum/sprite_accessory/socks/U3 = socks_list[H.socks]
if(U3)
standing += image("icon"=U3.icon, "icon_state"="[U3.icon_state]_s", "layer"=-BODY_LAYER)
@@ -298,7 +301,7 @@
H.overlays_standing[BODY_LAYER] = standing
H.apply_overlay(BODY_LAYER)
-
+ handle_mutant_bodyparts(H)
/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
var/list/bodyparts_to_add = mutant_bodyparts.Copy()
@@ -371,6 +374,29 @@
else if ("wings" in mutant_bodyparts)
bodyparts_to_add -= "wings_open"
+ //Digitigrade legs are stuck in the phantom zone between true limbs and mutant bodyparts. Mainly it just needs more agressive updating than most limbs.
+ var/update_needed = FALSE
+ var/not_digitigrade = TRUE
+ for(var/X in H.bodyparts)
+ var/obj/item/bodypart/O = X
+ if(!O.use_digitigrade)
+ continue
+ not_digitigrade = FALSE
+ if(!(DIGITIGRADE in specflags)) //Someone cut off a digitigrade leg and tacked it on
+ specflags += DIGITIGRADE
+ var/should_be_squished = FALSE
+ if(H.wear_suit && ((H.wear_suit.flags_inv & HIDEJUMPSUIT) || (H.wear_suit.body_parts_covered & LEGS)) || (H.w_uniform && (H.w_uniform.body_parts_covered & LEGS)))
+ should_be_squished = TRUE
+ if(O.use_digitigrade == FULL_DIGITIGRADE && should_be_squished)
+ O.use_digitigrade = SQUISHED_DIGITIGRADE
+ update_needed = TRUE
+ else if(O.use_digitigrade == SQUISHED_DIGITIGRADE && !should_be_squished)
+ O.use_digitigrade = FULL_DIGITIGRADE
+ update_needed = TRUE
+ if(update_needed)
+ H.update_body_parts()
+ if(not_digitigrade && (DIGITIGRADE in specflags)) //Curse is lifted
+ specflags -= DIGITIGRADE
if(!bodyparts_to_add)
return
@@ -411,6 +437,8 @@
S = wings_list[H.dna.features["wings"]]
if("wingsopen")
S = wings_open_list[H.dna.features["wings"]]
+ if("legs")
+ S = legs_list[H.dna.features["legs"]]
if(!S || S.icon_state == "none")
continue
@@ -552,6 +580,10 @@
return 0
if(num_legs < 2)
return 0
+ if(DIGITIGRADE in specflags)
+ if(!disable_warning)
+ H << "The footwear around here isn't compatible with your feet!"
+ return 0
return 1
if(slot_belt)
if(H.belt)
@@ -678,7 +710,7 @@
return
/datum/species/proc/after_equip_job(datum/job/J, mob/living/carbon/human/H)
- return
+ H.update_mutant_bodyparts()
/datum/species/proc/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == exotic_blood)
@@ -1065,13 +1097,15 @@
user.add_mob_blood(H)
switch(hit_area)
- if("head") //Harder to score a stun but if you do it lasts a bit longer
+ if("head")
if(H.stat == CONSCIOUS && armor_block < 50)
if(prob(I.force))
- H.visible_message("[H] has been knocked unconscious!", \
- "[H] has been knocked unconscious!")
- H.apply_effect(20, PARALYZE, armor_block)
- if(prob(I.force + ((100 - H.health)/2)) && H != user && I.damtype == BRUTE)
+ H.visible_message("[H] has been knocked senseless!", \
+ "[H] has been knocked senseless!")
+ H.confused = max(H.confused, 20)
+ H.adjust_blurriness(10)
+
+ if(prob(I.force + ((100 - H.health)/2)) && H != user)
ticker.mode.remove_revolutionary(H.mind)
if(bloody) //Apply blood
@@ -1085,11 +1119,12 @@
H.glasses.add_mob_blood(H)
H.update_inv_glasses()
- if("chest") //Easier to score a stun but lasts less time
- if(H.stat == CONSCIOUS && I.force && prob(I.force + 10))
- H.visible_message("[H] has been knocked down!", \
+ if("chest")
+ if(H.stat == CONSCIOUS && armor_block < 50)
+ if(prob(I.force))
+ H.visible_message("[H] has been knocked down!", \
"[H] has been knocked down!")
- H.apply_effect(5, WEAKEN, armor_block)
+ H.apply_effect(3, WEAKEN, armor_block)
if(bloody)
if(H.wear_suit)
diff --git a/code/modules/mob/living/carbon/human/species_types.dm b/code/modules/mob/living/carbon/human/species_types.dm
index c3e0bc205e1..97d1a2dd8ab 100644
--- a/code/modules/mob/living/carbon/human/species_types.dm
+++ b/code/modules/mob/living/carbon/human/species_types.dm
@@ -54,9 +54,9 @@
say_mod = "hisses"
default_color = "00FF00"
specflags = list(MUTCOLORS,EYECOLOR,LIPS)
- mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings")
+ mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs")
mutant_organs = list(/obj/item/organ/tongue/lizard)
- default_features = list("mcolor" = "0F0", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None")
+ default_features = list("mcolor" = "0F0", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Normal Legs")
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
@@ -86,7 +86,7 @@
/datum/species/lizard/ashwalker
name = "Ash Walker"
id = "lizard"
- specflags = list(MUTCOLORS,EYECOLOR,LIPS,NOBREATH,NOGUNS)
+ specflags = list(MUTCOLORS,EYECOLOR,LIPS,NOBREATH,NOGUNS,DIGITIGRADE)
/*
PODPEOPLE
*/
@@ -172,6 +172,34 @@
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/shadow
specflags = list(NOBREATH,NOBLOOD,RADIMMUNE,VIRUSIMMUNE)
dangerous_existence = 1
+ var/datum/action/innate/shadow/darkvision/vision_toggle
+
+/datum/action/innate/shadow/darkvision //Darkvision toggle so shadowpeople can actually see where darkness is
+ name = "Toggle Darkvision"
+ check_flags = AB_CHECK_CONSCIOUS
+ background_icon_state = "bg_default"
+ button_icon_state = "blind"
+
+/datum/action/innate/shadow/darkvision/Activate()
+ var/mob/living/carbon/human/H = owner
+ if(H.see_in_dark < 8)
+ H.see_in_dark = 8
+ H.see_invisible = SEE_INVISIBLE_MINIMUM
+ H << "You adjust your vision to pierce the darkness."
+ else
+ H.see_in_dark = 2
+ H.see_invisible = SEE_INVISIBLE_LIVING
+ H << "You adjust your vision to recognize the shadows."
+
+/datum/species/shadow/on_species_gain(mob/living/carbon/C, datum/species/old_species)
+ . = ..()
+ vision_toggle = new
+ vision_toggle.Grant(C)
+
+/datum/species/shadow/on_species_loss(mob/living/carbon/C)
+ . = ..()
+ if(vision_toggle)
+ vision_toggle.Remove(C)
/datum/species/shadow/spec_life(mob/living/carbon/human/H)
var/light_amount = 0
@@ -893,6 +921,33 @@ var/global/image/plasmaman_on_fire = image("icon"='icons/mob/OnFire.dmi', "icon_
return ..()
+/datum/species/android
+ name = "Android"
+ id = "android"
+ say_mod = "states"
+ specflags = list(NOBREATH,RESISTTEMP,NOBLOOD,VIRUSIMMUNE,PIERCEIMMUNE,NOHUNGER,EASYLIMBATTACHMENT)
+ safe_oxygen_min = 0
+ safe_toxins_min = 0
+ safe_toxins_max = 0
+ safe_co2_max = 0
+ SA_para_min = 0
+ SA_sleep_min = 0
+ meat = null
+ damage_overlay_type = "synth"
+ limbs_id = "synth"
+
+/datum/species/android/on_species_gain(mob/living/carbon/C)
+ . = ..()
+ for(var/X in C.bodyparts)
+ var/obj/item/bodypart/O = X
+ O.change_bodypart_status(BODYPART_ROBOTIC)
+
+/datum/species/android/on_species_loss(mob/living/carbon/C)
+ . = ..()
+ for(var/X in C.bodyparts)
+ var/obj/item/bodypart/O = X
+ O.change_bodypart_status(BODYPART_ORGANIC)
+
/*
SYNDICATE BLACK OPS
*/
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 4bbde09513d..1413c6cd2cd 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -117,8 +117,10 @@ There are several things that need to be remembered:
var/t_color = U.item_color
if(!t_color)
t_color = U.icon_state
- if(U.adjusted)
+ if(U.adjusted == ALT_STYLE)
t_color = "[t_color]_d"
+ else if(U.adjusted == DIGITIGRADE_STYLE)
+ t_color = "[t_color]_l"
var/image/standing
@@ -138,6 +140,7 @@ There are several things that need to be remembered:
unEquip(thing)
apply_overlay(UNIFORM_LAYER)
+ update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_wear_id()
@@ -537,13 +540,14 @@ generate/load female uniform sprites matching all previously decided variables
. += "-organic"
else
. += "-robotic"
+ if(BP.use_digitigrade)
+ . += "-digitigrade[BP.use_digitigrade]"
if(disabilities & HUSK)
. += "-husk"
/mob/living/carbon/human/load_limb_from_cache()
..()
- update_mutant_bodyparts()
update_hair()
diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm
index e44a4bad371..e399110909f 100644
--- a/code/modules/mob/living/carbon/inventory.dm
+++ b/code/modules/mob/living/carbon/inventory.dm
@@ -37,6 +37,7 @@
observe.client.screen -= I
I.loc = src
I.layer = ABOVE_HUD_LAYER
+ I.appearance_flags |= NO_CLIENT_COLOR
var/not_handled = FALSE
switch(slot)
if(slot_back)
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index aa701d7f1b3..aa898296f9a 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -9,11 +9,10 @@
damageoverlaytemp = 0
update_damage_hud()
- if(..())
- . = 1
-
+ if(..()) //not dead
handle_blood()
+ if(stat != DEAD)
for(var/X in internal_organs)
var/obj/item/organ/O = X
O.on_life()
@@ -21,6 +20,9 @@
//Updates the number of stored chemicals for powers
handle_changeling()
+ if(stat != DEAD)
+ return 1
+
///////////////
// BREATHING //
///////////////
diff --git a/code/modules/mob/living/carbon/monkey/punpun.dm b/code/modules/mob/living/carbon/monkey/punpun.dm
index d892512aecb..995c30f6fed 100644
--- a/code/modules/mob/living/carbon/monkey/punpun.dm
+++ b/code/modules/mob/living/carbon/monkey/punpun.dm
@@ -11,10 +11,6 @@
/mob/living/carbon/monkey/punpun/New()
Read_Memory()
- if(relic_hat)
- equip_to_slot_or_del(new relic_hat, slot_head)
- if(relic_mask)
- equip_to_slot_or_del(new relic_mask, slot_wear_mask)
if(ancestor_name)
name = ancestor_name
if(ancestor_chain > 1)
@@ -27,6 +23,14 @@
gender = pick(MALE, FEMALE)
..()
+ //These have to be after the parent new to ensure that the monkey
+ //bodyparts are actually created before we try to equip things to
+ //those slots
+ if(relic_hat)
+ equip_to_slot_or_del(new relic_hat, slot_head)
+ if(relic_mask)
+ equip_to_slot_or_del(new relic_mask, slot_wear_mask)
+
/mob/living/carbon/monkey/punpun/Life()
if(ticker.current_state == GAME_STATE_FINISHED && !memory_saved)
Write_Memory(0)
diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm
index dcd5b1a59b2..85df21c0974 100644
--- a/code/modules/mob/living/carbon/update_icons.dm
+++ b/code/modules/mob/living/carbon/update_icons.dm
@@ -263,6 +263,8 @@ var/global/list/limb_icon_cache = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
. += "-[BP.body_zone]"
+ if(BP.use_digitigrade)
+ . += "-digitigrade[BP.use_digitigrade]"
if(BP.animal_origin)
. += "-[BP.animal_origin]"
if(BP.status == BODYPART_ORGANIC)
diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm
index 10c9a2a50f8..6695c4a1271 100644
--- a/code/modules/mob/living/death.dm
+++ b/code/modules/mob/living/death.dm
@@ -3,13 +3,9 @@
if(stat != DEAD)
death(1)
- if(buckled)
- buckled.unbuckle_mob(src,force=1) //to update alien nest overlay, forced because we don't exist anymore
-
if(!prev_lying)
gib_animation()
-
spill_organs(no_brain, no_organs, no_bodyparts)
if(!no_bodyparts)
@@ -64,8 +60,6 @@
living_mob_list -= src
if(!gibbed)
dead_mob_list += src
- else if(buckled)
- buckled.unbuckle_mob(src,force=1)
paralysis = 0
stunned = 0
weakened = 0
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 5d2c0c48535..19cca48a15b 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -19,21 +19,18 @@
var/datum/gas_mixture/environment = loc.return_air()
if(stat != DEAD)
-
//Breathing, if applicable
handle_breathing()
-
+ if(stat != DEAD)
//Mutations and radiation
handle_mutations_and_radiation()
-
+ if(stat != DEAD)
//Chemicals in the body
handle_chemicals_in_body()
-
+ if(stat != DEAD)
//Random events (vomiting etc)
handle_random_events()
- . = 1
-
//Handle temperature/pressure differences between body and environment
if(environment)
handle_environment(environment)
@@ -48,11 +45,14 @@
if(machine)
machine.check_eye(src)
-
if(stat != DEAD)
handle_disabilities() // eye, ear, brain damages
+ if(stat != DEAD)
handle_status_effects() //all special effects, stunned, weakened, jitteryness, hallucination, sleeping, etc
+ if(stat != DEAD)
+ return 1
+
/mob/living/proc/handle_breathing()
return
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index b06fef840ca..74a24079251 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -29,6 +29,9 @@
/mob/living/Destroy()
..()
+ if(buckled)
+ buckled.unbuckle_mob(src,force=1)
+
for(var/mob/living/simple_animal/drone/D in player_list)
for(var/image/I in staticOverlays)
D.staticOverlays.Remove(I)
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 946f2e04900..c4a68499d21 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -4,7 +4,7 @@
#define POWER_RESTORATION_APC_FOUND 3
/mob/living/silicon/ai/Life()
- if (src.stat == DEAD)
+ if (stat == DEAD)
return
else //I'm not removing that shitton of tabs, unneeded as they are. -- Urist
//Being dead doesn't mean your temperature never changes
diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm
index 87e348dd92c..e0c6708d564 100644
--- a/code/modules/mob/living/silicon/login.dm
+++ b/code/modules/mob/living/silicon/login.dm
@@ -3,5 +3,4 @@
ticker.mode.remove_cultist(mind, 0, 0)
ticker.mode.remove_revolutionary(mind, 0)
ticker.mode.remove_gangster(mind, remove_bosses=1)
- ticker.mode.remove_hog_follower(mind,0)
..()
diff --git a/code/modules/mob/living/silicon/pai/life.dm b/code/modules/mob/living/silicon/pai/life.dm
index 191f28d7c37..f934a959316 100644
--- a/code/modules/mob/living/silicon/pai/life.dm
+++ b/code/modules/mob/living/silicon/pai/life.dm
@@ -1,7 +1,7 @@
/mob/living/silicon/pai/Life()
- if (src.stat == DEAD)
+ if(stat == DEAD)
return
- if(src.cable)
+ if(cable)
if(get_dist(src, src.cable) > 1)
var/turf/T = get_turf(src.loc)
T.visible_message("[src.cable] rapidly retracts back into its spool.", "You hear a click and the sound of wire spooling rapidly.")
diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm
index 30712e68b42..59bcff4fa60 100644
--- a/code/modules/mob/living/silicon/robot/login.dm
+++ b/code/modules/mob/living/silicon/robot/login.dm
@@ -6,4 +6,3 @@
if(mind)
ticker.mode.remove_revolutionary(mind)
ticker.mode.remove_gangster(mind,1,remove_bosses=1)
- ticker.mode.remove_hog_follower(mind, 0)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 76f8e90ef6e..6f56ca375b9 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -785,9 +785,8 @@
if(isturf(tile))
tile.clean_blood()
for(var/A in tile)
- if(istype(A, /obj/effect))
- if(is_cleanable(A))
- qdel(A)
+ if(is_cleanable(A))
+ qdel(A)
else if(istype(A, /obj/item))
var/obj/item/cleaned_item = A
cleaned_item.clean_blood()
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 34017a7c64e..7658a71c484 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -402,4 +402,4 @@
/datum/robot_energy_storage/medical
max_energy = 2500
recharge_rate = 250
- name = "Medical Synthesizer"
+ name = "Medical Synthesizer"
diff --git a/code/modules/mob/living/simple_animal/friendly/cockroach.dm b/code/modules/mob/living/simple_animal/friendly/cockroach.dm
index 9d6a9ab7f64..fc4045ae569 100644
--- a/code/modules/mob/living/simple_animal/friendly/cockroach.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cockroach.dm
@@ -53,4 +53,3 @@
icon = 'icons/effects/blood.dmi'
icon_state = "xfloor1"
random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
- layer = ABOVE_OPEN_TURF_LAYER
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index 5dcfcc2b9ed..fb94224fbbf 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -46,7 +46,7 @@
staticOverlays = list()
hud_possible = list(DIAG_STAT_HUD, DIAG_HUD, ANTAG_HUD)
unique_name = TRUE
- faction = list("silicon")
+ faction = list("neutral","silicon")
dextrous = TRUE
dextrous_hud_type = /datum/hud/dextrous/drone
var/staticChoice = "static"
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 2f75310ff25..f5c9269c0d9 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -27,6 +27,7 @@
var/ranged_message = "fires" //Fluff text for ranged mobs
var/ranged_cooldown = 0 //What the current cooldown on ranged attacks is, generally world.time + ranged_cooldown_time
var/ranged_cooldown_time = 30 //How long, in deciseconds, the cooldown of ranged attacks is
+ var/ranged_ignores_vision = FALSE //if it'll fire ranged attacks even if it lacks vision on its target, only works with environment smash
var/check_friendly_fire = 0 // Should the ranged mob check for friendlies when shooting
var/retreat_distance = null //If our mob runs from players when they're too close, set in tile distance. By default, mobs do not retreat.
var/minimum_distance = 1 //Minimum approach distance, so ranged mobs chase targets down, but still keep their distance set in tiles to the target, set higher to make mobs keep distance
@@ -53,6 +54,10 @@
environment_target_typecache = typecacheof(environment_target_typecache)
+/mob/living/simple_animal/hostile/Destroy()
+ targets_from = null
+ return ..()
+
/mob/living/simple_animal/hostile/Life()
. = ..()
if(!.) //dead
@@ -225,12 +230,14 @@
else
Goto(target,move_to_delay,minimum_distance)
if(target)
- if(isturf(targets_from.loc) && target.Adjacent(targets_from)) //If they're next to us, attack
+ if(targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from)) //If they're next to us, attack
AttackingTarget()
return 1
return 0
if(environment_smash)
if(target.loc != null && get_dist(targets_from, target.loc) <= vision_range) //We can't see our target, but he's in our vision range still
+ if(ranged_ignores_vision && ranged_cooldown <= world.time) //we can't see our target... but we can fire at them!
+ OpenFire(target)
if(environment_smash >= 2) //If we're capable of smashing through walls, forget about vision completely after finding our target
Goto(target,move_to_delay,minimum_distance)
FindHidden()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
index 68adb12b3c0..c68cf8a541f 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -9,15 +9,15 @@ Bubblegum's footsteps are heralded by shaking booms, proving its tremendous size
It acts as a melee creature, chasing down and attacking its target while also using different attacks to augment its power that increase as it takes damage.
-It often charges, dealing massive damage to anything unfortunate enough to be standing where it's aiming.
-Whenever it isn't chasing something down, it will sink into nearby blood pools (if possible) and springs out of the closest one to its target.
-To make this possible, it sprays streams of blood at random.
-From these blood pools Bubblegum may summon slaughterlings - weak, low-damage minions designed to impede the target's progress.
+It tries to strike at its target through any bloodpools under them; if it fails to do that, it will spray blood and then attempt to warp to a bloodpool near the target.
+If it fails to warp to a target, it may summon up to 6 slaughterlings from the blood around it.
+If it does not summon all 6 slaughterlings, it will instead charge at its target, dealing massive damage to anything it hits and spraying a stream of blood.
+At half health, it will either charge three times or warp, then charge, instead of doing a single charge.
When Bubblegum dies, it leaves behind a chest that can contain three things:
- 1. A slaughter demon spawner
- 2. A bottle that, when activated, drives everyone nearby into a frenzy
- 3. A contract that marks for death the chosen target
+ 1. A bottle that, when activated, drives everyone nearby into a frenzy
+ 2. A contract that marks for death the chosen target
+ 3. A spellblade that can slice off limbs at range
Difficulty: Hard
@@ -45,6 +45,7 @@ Difficulty: Hard
pixel_x = -32
del_on_death = 1
loot = list(/obj/structure/closet/crate/necropolis/bubblegum)
+ blood_volume = BLOOD_VOLUME_MAXIMUM //BLEED FOR ME
var/charging = 0
medal_type = MEDAL_PREFIX
score_type = BUBBLEGUM_SCORE
@@ -57,6 +58,24 @@ Difficulty: Hard
desc = "You're not quite sure how a signal can be bloody."
invisibility = 100
+/mob/living/simple_animal/hostile/megafauna/bubblegum/adjustBruteLoss(amount)
+ if(amount > 0 && prob(33))
+ var/obj/effect/decal/cleanable/blood/gibs/bubblegum/B = new /obj/effect/decal/cleanable/blood/gibs/bubblegum(loc)
+ if(prob(33))
+ step(B, pick(cardinal))
+ else
+ B.setDir(pick(cardinal))
+ . = ..()
+
+/obj/effect/decal/cleanable/blood/gibs/bubblegum
+ name = "thick blood"
+ desc = "Thick, splattered blood."
+ random_icon_states = list("gib3", "gib5", "gib6")
+ bloodiness = 20
+
+/obj/effect/decal/cleanable/blood/gibs/bubblegum/can_bloodcrawl_in()
+ return TRUE
+
/mob/living/simple_animal/hostile/megafauna/bubblegum/Life()
..()
move_to_delay = Clamp(round((health/maxHealth) * 10), 5, 10)
@@ -67,18 +86,21 @@ Difficulty: Hard
return
ranged_cooldown = world.time + ranged_cooldown_time
- blood_warp()
-
- if(prob(25))
+ var/warped = FALSE
+ if(!try_bloodattack())
addtimer(src, "blood_spray", 0)
+ warped = blood_warp()
+ if(warped && prob(100 - anger_modifier))
+ return
- else if(prob(5+anger_modifier/2))
- slaughterlings()
- else
- if(health > maxHealth/2 && !client)
+ if(prob(90 - anger_modifier) || slaughterlings())
+ if(health > maxHealth * 0.5 || client)
addtimer(src, "charge", 0)
else
- addtimer(src, "triple_charge", 0)
+ if(prob(70) || warped)
+ addtimer(src, "triple_charge", 0)
+ else
+ addtimer(src, "warp_charge", 0)
/mob/living/simple_animal/hostile/megafauna/bubblegum/New()
@@ -109,20 +131,22 @@ Difficulty: Hard
..()
/mob/living/simple_animal/hostile/megafauna/bubblegum/Move()
- if(!stat)
- playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
if(charging)
PoolOrNew(/obj/effect/overlay/temp/decoy/fading, list(loc,src))
DestroySurroundings()
. = ..()
+ if(!stat && .)
+ playsound(src, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
if(charging)
DestroySurroundings()
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/warp_charge()
+ blood_warp()
+ charge()
+
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/triple_charge()
charge()
- sleep(10)
charge()
- sleep(10)
charge()
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge()
@@ -135,11 +159,11 @@ Difficulty: Hard
walk(src, 0)
setDir(get_dir(src, T))
var/obj/effect/overlay/temp/decoy/D = PoolOrNew(/obj/effect/overlay/temp/decoy, list(loc,src))
- D.color = "#FF0000"
- animate(D, alpha = 0, color = initial(D.color), transform = matrix()*2, time = 5)
+ animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 5)
sleep(5)
throw_at(T, get_dist(src, T), 1, src, 0)
charging = 0
+ try_bloodattack()
Goto(target, move_to_delay, minimum_distance)
@@ -167,17 +191,135 @@ Difficulty: Hard
charging = 0
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_mobs_on_blood()
+ var/list/targets = ListTargets()
+ . = list()
+ for(var/mob/living/L in targets)
+ var/list/bloodpool = get_pools(get_turf(L), 0)
+ if(bloodpool.len && (!faction_check(L) || L.stat == DEAD))
+ . += L
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/try_bloodattack()
+ var/list/targets = get_mobs_on_blood()
+ if(targets.len)
+ addtimer(src, "bloodattack", 0, FALSE, targets, prob(50))
+
+ return TRUE
+ return FALSE
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodattack(list/targets, handedness)
+ var/mob/living/target_one = pick_n_take(targets)
+ var/turf/target_one_turf = get_turf(target_one)
+ var/mob/living/target_two
+ if(targets.len)
+ target_two = pick_n_take(targets)
+ var/turf/target_two_turf = get_turf(target_two)
+ if(target_two.stat != CONSCIOUS || prob(10))
+ bloodgrab(target_two_turf, handedness)
+ else
+ bloodsmack(target_two_turf, handedness)
+
+ var/list/pools = get_pools(get_turf(target_one), 0)
+ if(pools.len)
+ target_one_turf = get_turf(target_one)
+ if(target_one_turf)
+ if(target_one.stat != CONSCIOUS || prob(10))
+ bloodgrab(target_one_turf, !handedness)
+ else
+ bloodsmack(target_one_turf, !handedness)
+
+ if(!target_two && target_one)
+ var/list/poolstwo = get_pools(get_turf(target_one), 0)
+ if(poolstwo.len)
+ target_one_turf = get_turf(target_one)
+ if(target_one_turf)
+ if(target_one.stat != CONSCIOUS || prob(10))
+ bloodgrab(target_one_turf, handedness)
+ else
+ bloodsmack(target_one_turf, handedness)
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodsmack(turf/T, handedness)
+ if(handedness)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightsmack, T)
+ else
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftsmack, T)
+ sleep(2.5)
+ for(var/mob/living/L in T)
+ if(!faction_check(L))
+ L << "[src] rends you!"
+ playsound(T, attack_sound, 100, 1, -1)
+ var/limb_to_hit = L.get_bodypart(pick("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg"))
+ L.apply_damage(25, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, "melee", null, null, armour_penetration))
+ sleep(3)
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodgrab(turf/T, handedness)
+ if(handedness)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightpaw, T)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightthumb, T)
+ else
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftpaw, T)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftthumb, T)
+ sleep(6)
+ for(var/mob/living/L in T)
+ if(!faction_check(L))
+ L << "[src] drags you through the blood!"
+ playsound(T, 'sound/magic/enter_blood.ogg', 100, 1, -1)
+ var/turf/targetturf = get_step(src, dir)
+ L.forceMove(targetturf)
+ playsound(targetturf, 'sound/magic/exit_blood.ogg', 100, 1, -1)
+ if(L.stat != CONSCIOUS)
+ addtimer(src, "devour", 2, FALSE, L)
+ sleep(1)
+
+/obj/effect/overlay/temp/bubblegum_hands
+ icon = 'icons/effects/bubblegum.dmi'
+ duration = 9
+
+/obj/effect/overlay/temp/bubblegum_hands/rightthumb
+ icon_state = "rightthumbgrab"
+
+/obj/effect/overlay/temp/bubblegum_hands/leftthumb
+ icon_state = "leftthumbgrab"
+
+/obj/effect/overlay/temp/bubblegum_hands/rightpaw
+ icon_state = "rightpawgrab"
+ layer = BELOW_MOB_LAYER
+
+/obj/effect/overlay/temp/bubblegum_hands/leftpaw
+ icon_state = "leftpawgrab"
+ layer = BELOW_MOB_LAYER
+
+/obj/effect/overlay/temp/bubblegum_hands/rightsmack
+ icon_state = "rightsmack"
+
+/obj/effect/overlay/temp/bubblegum_hands/leftsmack
+ icon_state = "leftsmack"
+
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_warp()
+ if(Adjacent(target))
+ return FALSE
+ var/list/can_jaunt = get_pools(get_turf(src), 1)
+ if(!can_jaunt.len)
+ return FALSE
+
+ var/list/pools = get_pools(get_turf(target), 2)
+ var/list/pools_to_remove = get_pools(get_turf(target), 1)
+ pools -= pools_to_remove
+ if(!pools.len)
+ return FALSE
+
+ var/obj/effect/overlay/temp/decoy/DA = PoolOrNew(/obj/effect/overlay/temp/decoy, list(loc,src))
+ DA.color = "#FF0000"
+ var/oldtransform = DA.transform
+ DA.transform = matrix()*2
+ animate(DA, alpha = 255, color = initial(DA.color), transform = oldtransform, time = 5)
+ sleep(5)
+ qdel(DA)
+
var/obj/effect/decal/cleanable/blood/found_bloodpool
- var/list/pools = list()
- var/can_jaunt = FALSE
- for(var/obj/effect/decal/cleanable/blood/nearby in view(src,2))
- can_jaunt = TRUE
- break
- if(!can_jaunt)
- return
- for(var/obj/effect/decal/cleanable/blood/nearby in view(get_turf(target),2))
- pools += nearby
+ pools = get_pools(get_turf(target), 2)
+ pools_to_remove = get_pools(get_turf(target), 1)
+ pools -= pools_to_remove
if(pools.len)
shuffle(pools)
found_bloodpool = pick(pools)
@@ -187,35 +329,62 @@ Difficulty: Hard
forceMove(get_turf(found_bloodpool))
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
visible_message("And springs back out!")
+ return TRUE
+ return FALSE
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_pools(turf/T, range)
+ . = list()
+ for(var/obj/effect/decal/cleanable/nearby in view(T, range))
+ if(nearby.can_bloodcrawl_in())
+ . += nearby
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_spray()
visible_message("[src] sprays a stream of gore!")
- var/turf/E = get_edge_target_turf(src, src.dir)
- var/range = 10
+ var/range = 6 + round(anger_modifier * 0.4)
var/turf/previousturf = get_turf(src)
- for(var/turf/J in getline(src,E))
- if(!range)
- break
+ var/turf/J = previousturf
+ var/targetdir = get_dir(src, target)
+ if(target.loc == loc)
+ targetdir = dir
+ face_atom(target)
+ new /obj/effect/decal/cleanable/blood/bubblegum(J)
+ for(var/i in 1 to range)
+ J = get_step(previousturf, targetdir)
PoolOrNew(/obj/effect/overlay/temp/dir_setting/bloodsplatter, list(previousturf, get_dir(previousturf, J)))
- if(!previousturf.CanAtmosPass(J))
+ playsound(previousturf,'sound/effects/splat.ogg', 100, 1, -1)
+ if(!J || !previousturf.CanAtmosPass(J))
break
- playsound(J,'sound/effects/splat.ogg', 100, 1, -1)
- new /obj/effect/decal/cleanable/blood(J)
- range--
+ new /obj/effect/decal/cleanable/blood/bubblegum(J)
previousturf = J
sleep(1)
+/obj/effect/decal/cleanable/blood/bubblegum
+ bloodiness = 0
+
+/obj/effect/decal/cleanable/blood/bubblegum/can_bloodcrawl_in()
+ return TRUE
+
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/slaughterlings()
visible_message("[src] summons a shoal of slaughterlings!")
- for(var/obj/effect/decal/cleanable/blood/H in range(src, 10))
- if(prob(25))
- new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter(H.loc)
+ var/max_amount = 6
+ for(var/H in get_pools(get_turf(src), 1))
+ if(!max_amount)
+ break
+ max_amount--
+ var/obj/effect/decal/cleanable/blood/B = H
+ new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter(B.loc)
+ return max_amount
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter
name = "slaughterling"
desc = "Though not yet strong enough to create a true physical form, it's nonetheless determined to murder you."
- faction = list("mining")
+ density = 0
+ faction = list("mining", "boss")
weather_immunities = list("lava","ash")
+/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter/CanPass(atom/movable/mover, turf/target, height = 0)
+ if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum))
+ return 1
+ return 0
+
#undef MEDAL_PREFIX
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index bedb33e3d4a..22719303693 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -121,13 +121,10 @@ Difficulty: Very Hard
..()
/mob/living/simple_animal/hostile/megafauna/colossus/proc/enrage(mob/living/L)
- var/enraged = FALSE
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.martial_art && prob(H.martial_art.deflection_chance))
- enraged = TRUE
-
- return enraged
+ . = TRUE
/mob/living/simple_animal/hostile/megafauna/colossus/proc/alternating_dir_shots()
dir_shots(diagonals)
@@ -188,15 +185,15 @@ Difficulty: Very Hard
else
counter++
if(counter > 16)
- counter = 0
- if(counter < 0)
+ counter = 1
+ if(counter < 1)
counter = 16
shoot_projectile(marker)
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, 1)
sleep(1)
/mob/living/simple_animal/hostile/megafauna/colossus/proc/shoot_projectile(turf/marker)
- if(!marker)
+ if(!marker || marker == loc)
return
var/turf/startloc = get_turf(src)
var/obj/item/projectile/P = new /obj/item/projectile/colossus(startloc)
@@ -220,7 +217,9 @@ Difficulty: Very Hard
/mob/living/simple_animal/hostile/megafauna/colossus/proc/blast()
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 200, 1, 2)
- for(var/turf/turf in range(1, target))
+ var/turf/T = get_turf(target)
+ newtonian_move(get_dir(T, targets_from))
+ for(var/turf/turf in range(1, T))
shoot_projectile(turf)
/mob/living/simple_animal/hostile/megafauna/colossus/proc/dir_shots(list/dirs)
@@ -381,7 +380,7 @@ Difficulty: Very Hard
var/activation_sound = 'sound/effects/break_stone.ogg'
/obj/machinery/anomalous_crystal/New()
- activation_method = pick("touch","laser","bullet","energy","magic","mob_bump","heat","weapon","speech")
+ activation_method = pick("touch","laser","bullet","energy","bomb","mob_bump","heat","weapon","speech")
..()
/obj/machinery/anomalous_crystal/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans)
@@ -423,8 +422,11 @@ Difficulty: Very Hard
if(ismob(AM))
ActivationReaction(AM,"mob_bump")
+/obj/machinery/anomalous_crystal/ex_act()
+ ActivationReaction(null,"bomb")
+
/obj/machinery/anomalous_crystal/random/New()//Just a random crysal spawner for loot
- var/random_crystal = pick(typesof(/obj/machinery/anomalous_crystal) - /obj/machinery/anomalous_crystal/random)
+ var/random_crystal = pick(typesof(/obj/machinery/anomalous_crystal) - /obj/machinery/anomalous_crystal/random - /obj/machinery/anomalous_crystal)
new random_crystal(loc)
qdel(src)
@@ -472,13 +474,14 @@ Difficulty: Very Hard
NewTerrainChairs = /obj/structure/chair/wood/normal
NewTerrainTables = /obj/structure/table/glass
NewFlora = list(/obj/structure/flora/grass/green, /obj/structure/flora/grass/brown, /obj/structure/flora/grass/both)
- if("jungle") //Beneficial due to actually having breathable air. Plus, monkeys.
+ if("jungle") //Beneficial due to actually having breathable air. Plus, monkeys and bows and arrows.
NewTerrainFloors = /turf/open/floor/grass
NewTerrainWalls = /turf/closed/wall/mineral/sandstone
NewTerrainChairs = /obj/structure/chair/wood
NewTerrainTables = /obj/structure/table/wood
NewFlora = list(/obj/structure/flora/ausbushes/sparsegrass, /obj/structure/flora/ausbushes/fernybush, /obj/structure/flora/ausbushes/leafybush,
- /obj/structure/flora/ausbushes/grassybush, /obj/structure/flora/ausbushes/sunnybush, /obj/structure/flora/tree/palm, /mob/living/carbon/monkey)
+ /obj/structure/flora/ausbushes/grassybush, /obj/structure/flora/ausbushes/sunnybush, /obj/structure/flora/tree/palm, /mob/living/carbon/monkey,
+ /obj/item/weapon/gun/projectile/bow, /obj/item/weapon/storage/backpack/quiver/full)
florachance = 20
if("ayy lmao") //Beneficial, turns stuff into alien alloy which is useful to cargo and research. Also repairs atmos.
NewTerrainFloors = /turf/open/floor/plating/abductor
@@ -523,8 +526,8 @@ Difficulty: Very Hard
/obj/machinery/anomalous_crystal/emitter/New()
..()
- generated_projectile = pick(/obj/item/projectile/beam/emitter,/obj/item/projectile/magic/fireball/infernal,/obj/item/projectile/magic/spellblade,
- /obj/item/projectile/energy/net, /obj/item/projectile/bullet/meteorshot, /obj/item/projectile/beam/xray)
+ generated_projectile = pick(/obj/item/projectile/magic/fireball/infernal,/obj/item/projectile/magic/spellblade,
+ /obj/item/projectile/bullet/meteorshot, /obj/item/projectile/beam/xray, /obj/item/projectile/colossus)
/obj/machinery/anomalous_crystal/emitter/ActivationReaction(mob/user, method)
if(..())
@@ -545,17 +548,23 @@ Difficulty: Very Hard
P.xo = 0
P.fire()
-/obj/machinery/anomalous_crystal/dark_reprise //Revives anyone nearby, but turns them into shadowpeople. Cannot revive shadowpeople, so this is a one time thing.
+/obj/machinery/anomalous_crystal/dark_reprise //Revives anyone nearby, but turns them into shadowpeople and renders them uncloneable, so the crystal is your only hope of getting up again if you go down.
activation_method = "touch"
+ activation_sound = 'sound/hallucinations/growl1.ogg'
/obj/machinery/anomalous_crystal/dark_reprise/ActivationReaction(mob/user, method)
if(..())
for(var/i in range(1, src))
+ if(isturf(i))
+ PoolOrNew(/obj/effect/overlay/temp/cult/sparks, i)
+ continue
if(ishuman(i))
var/mob/living/carbon/human/H = i
- if(H.stat == DEAD && !isshadowperson(H))
+ if(H.stat == DEAD)
H.set_species(/datum/species/shadow, 1)
H.revive(1,0)
+ H.disabilities |= NOCLONE //Free revives, but significantly limits your options for reviving except via the crystal
+ H.grab_ghost(force = TRUE)
/obj/machinery/anomalous_crystal/helpers //Lets ghost spawn as helpful creatures that can only heal people slightly. Incredibly fragile and they can't converse with humans
activation_method = "touch"
@@ -564,17 +573,23 @@ Difficulty: Very Hard
/obj/machinery/anomalous_crystal/helpers/ActivationReaction(mob/user, method)
if(..() && !ready_to_deploy)
ready_to_deploy = 1
- notify_ghosts("An anomalous crystal has been activated in [get_area(src)]!", enter_link = "(Click to enter)", source = src, action = NOTIFY_ATTACK)
+ notify_ghosts("An anomalous crystal has been activated in [get_area(src)]! This crystal can always be used by ghosts hereafter.", enter_link = "(Click to enter)", source = src, action = NOTIFY_ATTACK)
/obj/machinery/anomalous_crystal/helpers/attack_ghost(mob/dead/observer/user)
..()
if(ready_to_deploy)
var/be_helper = alert("Become a Lightgeist? (Warning, You can no longer be cloned!)",,"Yes","No")
- if(!be_helper == "No")
+ if(be_helper == "No")
return
var/mob/living/simple_animal/hostile/lightgeist/W = new /mob/living/simple_animal/hostile/lightgeist(get_turf(loc))
W.key = user.key
+/obj/machinery/anomalous_crystal/helpers/Topic(href, href_list)
+ if(href_list["ghostjoin"])
+ var/mob/dead/observer/ghost = usr
+ if(istype(ghost))
+ attack_ghost(ghost)
+
/mob/living/simple_animal/hostile/lightgeist
name = "lightgeist"
desc = "This small floating creature is a completely unknown form of life... being near it fills you with a sense of tranquility."
@@ -603,19 +618,24 @@ Difficulty: Very Hard
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
luminosity = 4
faction = list("neutral")
- languages_spoken = 0
+ languages_spoken = SLIME
languages_understood = ALL
del_on_death = 1
unsuitable_atmos_damage = 0
flying = 1
minbodytemp = 0
maxbodytemp = 1500
+ environment_smash = 0
+ AIStatus = AI_OFF
+ stop_automated_movement = 1
var/heal_power = 5
/mob/living/simple_animal/hostile/lightgeist/New()
..()
verbs -= /mob/living/verb/pulled
verbs -= /mob/verb/me_verb
+ var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED]
+ medsensor.add_hud_to(src)
/mob/living/simple_animal/hostile/lightgeist/AttackingTarget()
..()
@@ -625,29 +645,35 @@ Difficulty: Very Hard
L.heal_overall_damage(heal_power, heal_power)
PoolOrNew(/obj/effect/overlay/temp/heal, list(get_turf(target), "#80F5FF"))
-/mob/living/simple_animal/hostile/lightgeist/Life()
- if(!ckey)
+/mob/living/simple_animal/hostile/lightgeist/ghostize()
+ if(..())
death()
- ..()
-/obj/machinery/anomalous_crystal/refresher //Deletes and recreates a copy of the item, "refreshing" it. Only works once per item.
+/obj/machinery/anomalous_crystal/refresher //Deletes and recreates a copy of the item, "refreshing" it.
activation_method = "touch"
cooldown_add = 50
+ activation_sound = 'sound/magic/TIMEPARADOX2.ogg'
+ var/list/banned_items_typecache = list(/obj/item/weapon/storage, /obj/item/weapon/implant, /obj/item/weapon/implanter, /obj/item/weapon/disk/nuclear, /obj/item/projectile, /obj/item/weapon/spellbook)
+
+/obj/machinery/anomalous_crystal/refresher/New()
+ ..()
+ banned_items_typecache = typecacheof(banned_items_typecache)
+
/obj/machinery/anomalous_crystal/refresher/ActivationReaction(mob/user, method)
if(..())
- var/list/L
+ var/list/L = list()
var/turf/T = get_step(src, dir)
+ PoolOrNew(/obj/effect/overlay/temp/emp/pulse,T)
for(var/i in T)
- if(istype(i, /obj/item) && !istype(i, /obj/item/weapon/storage) && !(i in affected_targets) && !istype(i, /obj/item/weapon/implant) && !istype(i, /obj/item/weapon/implanter) && !istype(i, /obj/item/weapon/disk/nuclear))
+ if(istype(i, /obj/item) && !is_type_in_typecache(i, banned_items_typecache))
var/obj/item/W = i
if(!W.admin_spawned)
L += W
- var/obj/item/CHOSEN = pick(L)
- if(CHOSEN)
- var/A = new CHOSEN.type(T)
- affected_targets += A
+ if(L.len)
+ var/obj/item/CHOSEN = pick(L)
+ new CHOSEN.type(T)
qdel(CHOSEN)
/obj/machinery/anomalous_crystal/possessor //Allows you to bodyjack small animals, then exit them at your leisure, but you can only do this once per activation. Because they blow up. Also, if the bodyjacked animal dies, SO DO YOU.
@@ -665,7 +691,7 @@ Difficulty: Very Hard
mobcheck = 1
break
if(!mobcheck)
- new /mob/living/simple_animal/cockroach(loc) //Just in case there aren't any animals on the station, this will leave you with a terrible option to possess if you feel like it
+ new /mob/living/simple_animal/cockroach(get_step(src,dir)) //Just in case there aren't any animals on the station, this will leave you with a terrible option to possess if you feel like it
/obj/structure/closet/stasis
name = "quantum entanglement stasis warp field"
@@ -673,17 +699,15 @@ Difficulty: Very Hard
icon_state = null //This shouldn't even be visible, so if it DOES show up, at least nobody will notice
density = 1
anchored = 1
- health = 0
+ health = 999
var/mob/living/simple_animal/holder_animal
/obj/structure/closet/stasis/process()
- if(!isanimal(loc))
- dump_contents(1)
- return
if(holder_animal)
- if(holder_animal.stat == DEAD)
- dump_contents(1)
+ if(holder_animal.stat == DEAD && !qdeleted(holder_animal))
+ dump_contents()
holder_animal.gib()
+ return
/obj/structure/closet/stasis/New()
..()
@@ -702,14 +726,15 @@ Difficulty: Very Hard
holder_animal.mind.AddSpell(P)
holder_animal.verbs -= /mob/living/verb/pulled
-/obj/structure/closet/stasis/dump_contents(var/kill = 0)
+/obj/structure/closet/stasis/dump_contents(var/kill = 1)
STOP_PROCESSING(SSobj, src)
for(var/mob/living/L in src)
L.disabilities &= ~MUTE
L.status_flags &= ~GODMODE
L.notransform = 0
- holder_animal.mind.transfer_to(L)
- L.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/exit_possession)
+ if(holder_animal && !qdeleted(holder_animal))
+ holder_animal.mind.transfer_to(L)
+ L.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/exit_possession)
if(kill || !isanimal(loc))
L.death(0)
..()
@@ -717,6 +742,9 @@ Difficulty: Very Hard
/obj/structure/closet/stasis/emp_act()
return
+/obj/structure/closet/stasis/ex_act()
+ return
+
/obj/effect/proc_holder/spell/targeted/exit_possession
name = "Exit Possession"
desc = "Exits the body you are possessing"
@@ -737,7 +765,7 @@ Difficulty: Very Hard
for(var/i in user)
if(istype(i, /obj/structure/closet/stasis))
var/obj/structure/closet/stasis/S = i
- S.dump_contents()
+ S.dump_contents(0)
qdel(S)
break
user.gib()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm
index 237116ed835..cfeb0a19e9d 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm
@@ -229,8 +229,11 @@ Difficulty: Medium
else
L.adjustBruteLoss(75)
if(L && !qdeleted(L)) // Some mobs are deleted on death
- var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
- L.throw_at_fast(throwtarget)
+ var/throw_dir = get_dir(src, L)
+ if(L.loc == loc)
+ throw_dir = pick(alldirs)
+ var/throwtarget = get_edge_target_turf(src, throw_dir)
+ L.throw_at_fast(throwtarget, 3)
visible_message("[L] is thrown clear of [src]!")
for(var/mob/M in range(7, src))
@@ -244,7 +247,7 @@ Difficulty: Medium
if(!istype(A))
return
if(swoop_cooldown >= world.time)
- src << "You need to wait 20 seconds between swoop attacks!M/span>"
+ src << "You need to wait 20 seconds between swoop attacks!"
return
swoop_attack(1, A)
@@ -258,6 +261,7 @@ Difficulty: Medium
name = "lesser ash drake"
maxHealth = 300
health = 300
+ faction = list("neutral")
melee_damage_upper = 30
melee_damage_lower = 30
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index ee7e70bdcf2..37aa5575a9b 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -87,7 +87,7 @@ Difficulty: Hard
did_reset = TRUE
//visible_message("\"Vixyvrmrk xs fewi...\"")
blink(spawned_rune)
- adjustHealth(max((health - maxHealth) * 0.5, 25)) //heal for 50% of our missing health
+ adjustHealth(min((health - maxHealth) * 0.5, -50)) //heal for 50% of our missing health
wander = FALSE
/*if(health > maxHealth * 0.9)
visible_message("\"Vitemvw gsqtpixi. Stivexmrk ex qebmqyq ijjmgmirgc.\"")
@@ -279,6 +279,8 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/diagonal_blasts(mob/victim) //fire diagonal cross blasts with a delay
var/turf/T = get_turf(victim)
+ if(!T)
+ return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/diagonal, list(T, src))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
@@ -289,6 +291,8 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/cardinal_blasts(mob/victim) //fire cardinal cross blasts with a delay
var/turf/T = get_turf(victim)
+ if(!T)
+ return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/cardinal, list(T, src))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
@@ -299,6 +303,8 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/alldir_blasts(mob/victim) //fire alldir cross blasts with a delay
var/turf/T = get_turf(victim)
+ if(!T)
+ return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(T, src))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
@@ -396,6 +402,7 @@ Difficulty: Hard
/obj/effect/overlay/temp/hierophant/chaser //a hierophant's chaser. follows target around, moving and producing a blast every speed deciseconds.
duration = 98
var/mob/living/target //what it's following
+ var/turf/targetturf //what turf the target is actually on
var/moving_dir //what dir it's moving in
var/previous_moving_dir //what dir it was moving in before that
var/more_previouser_moving_dir //what dir it was moving in before THAT
@@ -415,7 +422,7 @@ Difficulty: Hard
addtimer(src, "seek_target", 1)
/obj/effect/overlay/temp/hierophant/chaser/proc/get_target_dir()
- . = get_cardinal_dir(src, target)
+ . = get_cardinal_dir(src, targetturf)
if((. != previous_moving_dir && . == more_previouser_moving_dir) || . == 0) //we're alternating, recalculate
var/list/cardinal_copy = cardinal.Copy()
cardinal_copy -= more_previouser_moving_dir
@@ -424,12 +431,13 @@ Difficulty: Hard
/obj/effect/overlay/temp/hierophant/chaser/proc/seek_target()
if(!currently_seeking)
currently_seeking = TRUE
- while(target && src && !qdeleted(src) && currently_seeking && x && y && target.x && target.y) //can this target actually be sook out
+ targetturf = get_turf(target)
+ while(target && src && !qdeleted(src) && currently_seeking && x && y && targetturf) //can this target actually be sook out
if(!moving) //we're out of tiles to move, find more and where the target is!
more_previouser_moving_dir = previous_moving_dir
previous_moving_dir = moving_dir
moving_dir = get_target_dir()
- var/standard_target_dir = get_cardinal_dir(src, target)
+ var/standard_target_dir = get_cardinal_dir(src, targetturf)
if((standard_target_dir != previous_moving_dir && standard_target_dir == more_previouser_moving_dir) || standard_target_dir == 0)
moving = 1 //we would be repeating, only move a tile before checking
else
@@ -446,6 +454,7 @@ Difficulty: Hard
make_blast() //make a blast, too
moving--
sleep(speed)
+ targetturf = get_turf(target)
/obj/effect/overlay/temp/hierophant/chaser/proc/make_blast()
PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(loc, caster, friendly_fire_check))
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
index 948f01e56eb..b63b421ae83 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -15,6 +15,7 @@
weather_immunities = list("lava","ash")
flying = 1
robust_searching = 1
+ ranged_ignores_vision = TRUE
stat_attack = 2
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
damage_coeff = list(BRUTE = 1, BURN = 0.5, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
diff --git a/code/modules/mob/living/simple_animal/hostile/skeleton.dm b/code/modules/mob/living/simple_animal/hostile/skeleton.dm
index ad20e68458e..4664a41082c 100644
--- a/code/modules/mob/living/simple_animal/hostile/skeleton.dm
+++ b/code/modules/mob/living/simple_animal/hostile/skeleton.dm
@@ -70,7 +70,7 @@
loot = list(/obj/effect/decal/remains/human,
/obj/item/clothing/suit/armor/riot/knight/templar,
/obj/item/clothing/head/helmet/knight/templar,
- /obj/item/weapon/claymore/hog{name = "holy sword"})
+ /obj/item/weapon/claymore/weak{name = "holy sword"})
/mob/living/simple_animal/hostile/skeleton/ice
name = "ice skeleton"
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index edca0beac1d..8de22d32685 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -104,10 +104,14 @@
/mob/living/simple_animal/Life()
if(..()) //alive
if(!ckey)
- handle_automated_movement()
- handle_automated_action()
- handle_automated_speech()
- return 1
+ if(stat != DEAD)
+ handle_automated_movement()
+ if(stat != DEAD)
+ handle_automated_action()
+ if(stat != DEAD)
+ handle_automated_speech()
+ if(stat != DEAD)
+ return 1
/mob/living/simple_animal/updatehealth()
..()
@@ -301,7 +305,11 @@
if(del_on_death)
ghostize()
stat = DEAD
+ //Prevent infinite loops if the mob Destroy() is overriden in such
+ //a manner as to cause a call to death() again
+ del_on_death = FALSE
qdel(src)
+ return
else
health = 0
icon_state = icon_dead
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 4744180d207..1b1808518f8 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -499,8 +499,8 @@ var/next_mob_id = 0
return
var/mob/mob_eye = creatures[eye_name]
-
- if(client && mob_eye)
+ //Istype so we filter out points of interest that are not mobs
+ if(client && mob_eye && istype(mob_eye))
client.eye = mob_eye
if(isobserver(src))
src.client.screen = list()
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 40d23ea638d..e59f4708e90 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -465,3 +465,15 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
M << "There were no ghosts willing to take control."
message_admins("No ghosts were willing to take control of [key_name_admin(M)])")
return FALSE
+
+//toggles the talk wheel
+/mob/verb/toggle_talk_wheel()
+ set name = "talk-wheel"
+ set hidden = 1
+
+ if(isliving(src))
+ var/mob/living/L = src
+ if(L.hud_used)
+ for(var/obj/screen/wheel/talk/TW in L.hud_used.wheels)
+ TW.Click()
+
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 3c2c95fbbf8..e947d24c1a7 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -332,6 +332,9 @@
data_core.manifest_inject(humanc)
AnnounceArrival(humanc, rank)
AddEmploymentContract(humanc)
+ if(highlander)
+ humanc << "THERE CAN BE ONLY ONE!!!"
+ humanc.make_scottish()
joined_player_list += character.ckey
diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm
index 054bb354824..9c5a1242b4a 100644
--- a/code/modules/mob/new_player/sprite_accessories.dm
+++ b/code/modules/mob/new_player/sprite_accessories.dm
@@ -1135,29 +1135,15 @@
name = "None"
icon_state = "none"
-/datum/sprite_accessory/body_markings/dstripe
- name = "Dark Stripe"
- icon_state = "dstripe"
-
-/datum/sprite_accessory/body_markings/lstripe
- name = "Light Stripe"
- icon_state = "lstripe"
-
/datum/sprite_accessory/body_markings/dtiger
name = "Dark Tiger Body"
icon_state = "dtiger"
-
-/datum/sprite_accessory/body_markings/dtigerhead
- name = "Dark Tiger Body + Head"
- icon_state = "dtigerhead"
+ gender_specific = 1
/datum/sprite_accessory/body_markings/ltiger
name = "Light Tiger Body"
icon_state = "ltiger"
-
-/datum/sprite_accessory/body_markings/ltigerhead
- name = "Light Tiger Body + Head"
- icon_state = "ltigerhead"
+ gender_specific = 1
/datum/sprite_accessory/body_markings/lbelly
name = "Light Belly"
@@ -1178,30 +1164,6 @@
name = "Smooth"
icon_state = "smooth"
-/datum/sprite_accessory/tails/lizard/light
- name = "Light"
- icon_state = "light"
-
-/datum/sprite_accessory/tails_animated/lizard/light
- name = "Light"
- icon_state = "light"
-
-/datum/sprite_accessory/tails/lizard/dstripe
- name = "Dark Stripe"
- icon_state = "dstripe"
-
-/datum/sprite_accessory/tails_animated/lizard/dstripe
- name = "Dark Stripe"
- icon_state = "dstripe"
-
-/datum/sprite_accessory/tails/lizard/lstripe
- name = "Light Stripe"
- icon_state = "lstripe"
-
-/datum/sprite_accessory/tails_animated/lizard/lstripe
- name = "Light Stripe"
- icon_state = "lstripe"
-
/datum/sprite_accessory/tails/lizard/dtiger
name = "Dark Tiger"
icon_state = "dtiger"
@@ -1218,21 +1180,13 @@
name = "Light Tiger"
icon_state = "ltiger"
-/datum/sprite_accessory/tails/lizard/club
- name = "Club"
- icon_state = "club"
+/datum/sprite_accessory/tails/lizard/spikes
+ name = "Spikes"
+ icon_state = "spikes"
-/datum/sprite_accessory/tails_animated/lizard/club
- name = "Club"
- icon_state = "club"
-
-/datum/sprite_accessory/tails/lizard/aqua
- name = "Aquatic"
- icon_state = "aqua"
-
-/datum/sprite_accessory/tails_animated/lizard/aqua
- name = "Aquatic"
- icon_state = "aqua"
+/datum/sprite_accessory/tails_animated/lizard/spikes
+ name = "Spikes"
+ icon_state = "spikes"
/datum/sprite_accessory/tails/human/none
name = "None"
@@ -1410,3 +1364,12 @@
/datum/sprite_accessory/spines_animated/aqautic
name = "Aquatic"
icon_state = "aqua"
+
+/datum/sprite_accessory/legs //legs are a special case, they aren't actually sprite_accessories but are updated with them.
+ icon = null //These datums exist for selecting legs on preference, and little else
+
+/datum/sprite_accessory/legs/none
+ name = "Normal Legs"
+
+/datum/sprite_accessory/legs/digitigrade_lizard
+ name = "Digitigrade Legs"
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index 9ba2db5975b..6f662412c65 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -486,23 +486,6 @@
qdel(src)
-/mob/proc/become_god(var/side_colour)
- var/mob/camera/god/G = new /mob/camera/god(loc)
- G.side = side_colour
- if(mind)
- mind.transfer_to(G)
- else
- G.key = key
-
- G.job = "Deity"
- G.rename_self("deity")
- G.update_icons()
-
- . = G
- qdel(src)
-
-
-
/mob/living/carbon/human/proc/corgize()
if (notransform)
return
diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm
index 516293bfc27..942a114dc56 100644
--- a/code/modules/modular_computers/computers/item/computer.dm
+++ b/code/modules/modular_computers/computers/item/computer.dm
@@ -36,22 +36,12 @@
var/max_damage = 100 // Damage level at which the computer breaks apart.
// Important hardware (must be installed for computer to work)
- var/obj/item/weapon/computer_hardware/processor_unit/processor_unit // CPU. Without it the computer won't run. Better CPUs can run more programs at once.
- var/obj/item/weapon/computer_hardware/hard_drive/hard_drive // Hard Drive component of this computer. Stores programs and files.
-
- var/obj/item/weapon/computer_hardware/battery/battery_module // Power cell connector. Power cell can be recharged.
- // OR
- var/obj/item/weapon/computer_hardware/recharger/recharger // Recharger. Can be used to recharge power cell or power the PC without it.
// Optional hardware (improves functionality, but is not critical for computer to work)
- var/obj/item/weapon/computer_hardware/network_card/network_card // Network Card component of this computer. Allows connection to NTNet.
- var/obj/item/weapon/computer_hardware/card_slot/card_slot // ID Card slot component of this computer.
- var/obj/item/weapon/computer_hardware/printer/printer // Printer component of this computer, for your everyday paperwork needs.
- var/obj/item/weapon/computer_hardware/hard_drive/portable/portable_drive // Portable data storage
- var/list/all_components = list()
+ var/list/all_components // List of "connection ports" in this computer and the components with which they are plugged
- var/list/idle_threads = list() // Idle programs on background. They still receive process calls but can't be interacted with.
+ var/list/idle_threads // Idle programs on background. They still receive process calls but can't be interacted with.
var/obj/physical = null // Object that represents our computer. It's used for Adjacent() and UI visibility checks.
@@ -63,30 +53,48 @@
physical = src
..()
+ all_components = list()
+ idle_threads = list()
+
/obj/item/device/modular_computer/Destroy()
kill_program(forced = TRUE)
STOP_PROCESSING(SSobj, src)
for(var/H in all_components)
- var/obj/item/weapon/computer_hardware/CH = H
+ var/obj/item/weapon/computer_hardware/CH = all_components[H]
if(CH.holder == src)
CH.holder = null
qdel(CH)
return ..()
+
+/obj/item/device/modular_computer/proc/add_verb(var/path)
+ switch(path)
+ if(MC_CARD)
+ verbs += /obj/item/device/modular_computer/proc/eject_id
+ if(MC_SDD)
+ verbs += /obj/item/device/modular_computer/proc/eject_disk
+
+/obj/item/device/modular_computer/proc/remove_verb(path)
+ switch(path)
+ if(MC_CARD)
+ verbs -= /obj/item/device/modular_computer/proc/eject_id
+ if(MC_SDD)
+ verbs -= /obj/item/device/modular_computer/proc/eject_disk
+
// Eject ID card from computer, if it has ID slot with card inside.
-/obj/item/device/modular_computer/verb/eject_id()
+/obj/item/device/modular_computer/proc/eject_id()
set name = "Eject ID"
set category = "Object"
set src in view(1)
if(issilicon(usr))
return
-
- if (usr.canUseTopic(src))
- proc_eject_id(usr)
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
+ if(usr.canUseTopic(src))
+ card_slot.try_eject(, usr)
// Eject ID card from computer, if it has ID slot with card inside.
-/obj/item/device/modular_computer/verb/eject_disk()
+/obj/item/device/modular_computer/proc/eject_disk()
set name = "Eject Data Disk"
set category = "Object"
set src in view(1)
@@ -94,30 +102,10 @@
if(issilicon(usr))
return
- if (usr.canUseTopic(src))
- proc_eject_disk(usr)
-
-/obj/item/device/modular_computer/proc/proc_eject_id(mob/user, slot)
- if(!user)
- user = usr
-
- if(!card_slot)
- user << "\The [src] does not have an ID card slot!"
- return
-
- card_slot.try_eject(slot, user)
-
-/obj/item/device/modular_computer/proc/proc_eject_disk(mob/user)
- if(!user)
- user = usr
-
- if(!portable_drive)
- user << "There is no data disk in \the [src]!"
- return
-
- var/obj/item/I = portable_drive
- if(uninstall_component(portable_drive, user))
- I.verb_pickup()
+ if(usr.canUseTopic(src))
+ var/obj/item/weapon/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD]
+ if(uninstall_component(portable_drive, usr))
+ portable_drive.verb_pickup()
/obj/item/device/modular_computer/AltClick(mob/user)
..()
@@ -125,19 +113,24 @@
return
if(user.canUseTopic(src))
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
+ var/obj/item/weapon/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD]
if(portable_drive)
- proc_eject_disk(user)
+ if(uninstall_component(portable_drive, user))
+ portable_drive.verb_pickup()
else if(card_slot)
- proc_eject_id(user)
+ card_slot.try_eject(, user)
// Gets IDs/access levels from card slot. Would be useful when/if PDAs would become modular PCs.
/obj/item/device/modular_computer/GetAccess()
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
if(card_slot)
return card_slot.GetAccess()
return ..()
/obj/item/device/modular_computer/GetID()
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
if(card_slot)
return card_slot.GetID()
return ..()
@@ -208,10 +201,11 @@
return
// If we have a recharger, enable it automatically. Lets computer without a battery work.
+ var/obj/item/weapon/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
if(recharger)
recharger.enabled = 1
- if(processor_unit && use_power()) // use_power() checks if the PC is powered
+ if(all_components[MC_CPU] && use_power()) // use_power() checks if the PC is powered
if(issynth)
user << "You send an activation signal to \the [src], turning it on."
else
@@ -265,6 +259,9 @@
/obj/item/device/modular_computer/proc/get_header_data()
var/list/data = list()
+ var/obj/item/weapon/computer_hardware/battery/battery_module = all_components[MC_CELL]
+ var/obj/item/weapon/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
+
if(battery_module && battery_module.battery)
switch(battery_module.battery.percent())
if(80 to 200) // 100 should be maximal but just in case..
@@ -328,6 +325,7 @@
// Returns 0 for No Signal, 1 for Low Signal and 2 for Good Signal. 3 is for wired connection (always-on)
/obj/item/device/modular_computer/proc/get_ntnet_status(specific_action = 0)
+ var/obj/item/weapon/computer_hardware/network_card/network_card = all_components[MC_NET]
if(network_card)
return network_card.get_signal(specific_action)
else
@@ -336,6 +334,7 @@
/obj/item/device/modular_computer/proc/add_log(text)
if(!get_ntnet_status())
return FALSE
+ var/obj/item/weapon/computer_hardware/network_card/network_card = all_components[MC_NET]
return ntnet_global.add_log(text, network_card)
/obj/item/device/modular_computer/proc/shutdown_computer(loud = 1)
@@ -352,7 +351,7 @@
/obj/item/device/modular_computer/attackby(obj/item/weapon/W as obj, mob/user as mob)
// Insert items into the components
for(var/h in all_components)
- var/obj/item/weapon/computer_hardware/H = h
+ var/obj/item/weapon/computer_hardware/H = all_components[h]
if(H.try_insert(W, user))
return
diff --git a/code/modules/modular_computers/computers/item/computer_components.dm b/code/modules/modular_computers/computers/item/computer_components.dm
index 3a5b68579e1..0f27580a27f 100644
--- a/code/modules/modular_computers/computers/item/computer_components.dm
+++ b/code/modules/modular_computers/computers/item/computer_components.dm
@@ -6,32 +6,8 @@
user << "This component is too large for \the [src]!"
return FALSE
- if(istype(H, /obj/item/weapon/computer_hardware/hard_drive/portable) && portable_drive)
- user << "This computer's FDD is already occupied by \the [portable_drive]."
- return FALSE
-
- else if(istype(H, /obj/item/weapon/computer_hardware/processor_unit) && processor_unit)
- user << "This computer's CPU slot is already occupied by \the [processor_unit]."
- return FALSE
- else if(istype(H, /obj/item/weapon/computer_hardware/hard_drive) && hard_drive)
- user << "This computer's data port is already occupied by \the [hard_drive]."
- return FALSE
-
- else if(istype(H, /obj/item/weapon/computer_hardware/battery) && battery_module)
- user << "This computer's power converter slot is already occupied by \the [battery_module]."
- return FALSE
- else if(istype(H, /obj/item/weapon/computer_hardware/recharger) && recharger)
- user << "This computer's recharger slot is already occupied by \the [recharger]."
- return FALSE
-
- else if(istype(H, /obj/item/weapon/computer_hardware/card_slot) && card_slot)
- user << "This computer's card reader slot is already occupied by \the [card_slot]."
- return FALSE
- else if(istype(H, /obj/item/weapon/computer_hardware/network_card) && network_card)
- user << "This computer's network card is already occupied by \the [network_card]."
- return FALSE
- else if(istype(H, /obj/item/weapon/computer_hardware/printer) && printer)
- user << "This computer's printer slot is already occupied by \the [printer]."
+ if(all_components[H.device_type])
+ user << "This computer's hardware slot is already occupied by \the [all_components[H.device_type]]."
return FALSE
return TRUE
@@ -44,32 +20,12 @@
if(user && !user.unEquip(H))
return FALSE
- if(istype(H, /obj/item/weapon/computer_hardware/hard_drive/portable))
- portable_drive = H
-
- else if(istype(H, /obj/item/weapon/computer_hardware/processor_unit))
- processor_unit = H
- else if(istype(H, /obj/item/weapon/computer_hardware/hard_drive))
- hard_drive = H
-
- else if(istype(H, /obj/item/weapon/computer_hardware/battery))
- battery_module = H
- else if(istype(H, /obj/item/weapon/computer_hardware/recharger))
- recharger = H
-
- else if(istype(H, /obj/item/weapon/computer_hardware/card_slot))
- card_slot = H
- else if(istype(H, /obj/item/weapon/computer_hardware/network_card))
- network_card = H
- else if(istype(H, /obj/item/weapon/computer_hardware/printer))
- printer = H
+ all_components[H.device_type] = H
user << "You install \the [H] into \the [src]."
H.forceMove(src)
H.holder = src
- all_components |= H
H.on_install(src, user)
- return TRUE
// Uninstalls component.
@@ -77,41 +33,22 @@
if(H.holder != src) // Not our component at all.
return FALSE
- if(processor_unit == H)
- processor_unit = null
- if(hard_drive == H)
- hard_drive = null
-
- if(battery_module == H)
- battery_module = null
- if(recharger == H)
- recharger = null
-
- if(card_slot == H)
- card_slot = null
- if(network_card == H)
- network_card = null
- if(printer == H)
- printer = null
- if(portable_drive == H)
- portable_drive = null
+ all_components.Remove(H.device_type)
user << "You remove \the [H] from \the [src]."
H.forceMove(get_turf(src))
H.holder = null
- all_components -= H
H.on_remove(src, user)
- if(enabled && (!processor_unit || !hard_drive || !use_power()))
+ if(enabled && !use_power())
shutdown_computer()
update_icon()
- return TRUE
// Checks all hardware pieces to determine if name matches, if yes, returns the hardware piece, otherwise returns null
/obj/item/device/modular_computer/proc/find_hardware_by_name(name)
for(var/i in all_components)
- var/obj/O = i
+ var/obj/O = all_components[i]
if(O.name == name)
return O
return null
diff --git a/code/modules/modular_computers/computers/item/computer_damage.dm b/code/modules/modular_computers/computers/item/computer_damage.dm
index 8214840bc2b..d27ec0a750f 100644
--- a/code/modules/modular_computers/computers/item/computer_damage.dm
+++ b/code/modules/modular_computers/computers/item/computer_damage.dm
@@ -9,7 +9,7 @@
if(component_probability)
for(var/I in all_components)
- var/obj/item/weapon/computer_hardware/H = I
+ var/obj/item/weapon/computer_hardware/H = all_components[I]
if(prob(component_probability))
H.take_damage(round(amount / 2))
@@ -40,7 +40,7 @@
var/turf/newloc = get_turf(src)
new /obj/item/stack/sheet/metal(newloc, round(steel_sheet_cost/2))
for(var/C in all_components)
- var/obj/item/weapon/computer_hardware/H = C
+ var/obj/item/weapon/computer_hardware/H = all_components[C]
uninstall_component(H)
H.forceMove(newloc)
if(prob(25))
diff --git a/code/modules/modular_computers/computers/item/computer_power.dm b/code/modules/modular_computers/computers/item/computer_power.dm
index f6196477000..c5aab99ce57 100644
--- a/code/modules/modular_computers/computers/item/computer_power.dm
+++ b/code/modules/modular_computers/computers/item/computer_power.dm
@@ -3,10 +3,14 @@
if(check_power_override())
return TRUE
+ var/obj/item/weapon/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
+
if(recharger && recharger.check_functionality())
if(recharger.use_power(amount))
return TRUE
+ var/obj/item/weapon/computer_hardware/battery/battery_module = all_components[MC_CELL]
+
if(battery_module && battery_module.battery && battery_module.battery.charge)
var/obj/item/weapon/stock_parts/cell/cell = battery_module.battery
if(cell.use(amount * CELLRATE))
@@ -17,6 +21,7 @@
return FALSE
/obj/item/device/modular_computer/proc/give_power(amount)
+ var/obj/item/weapon/computer_hardware/battery/battery_module = all_components[MC_CELL]
if(battery_module && battery_module.battery)
return battery_module.battery.give(amount)
return 0
@@ -34,6 +39,7 @@
// Handles power-related things, such as battery interaction, recharging, shutdown when it's discharged
/obj/item/device/modular_computer/proc/handle_power()
+ var/obj/item/weapon/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
if(recharger)
recharger.process()
diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm
index a89e84b31f4..b551b98ede7 100644
--- a/code/modules/modular_computers/computers/item/computer_ui.dm
+++ b/code/modules/modular_computers/computers/item/computer_ui.dm
@@ -24,6 +24,7 @@
// We are still here, that means there is no program loaded. Load the BIOS/ROM/OS/whatever you want to call it.
// This screen simply lists available programs and user may select them.
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
if(!hard_drive || !hard_drive.stored_files || !hard_drive.stored_files.len)
physical.visible_message("\The [src] beeps three times, it's screen displaying \"DISK ERROR\" warning.")
return // No HDD, No HDD files list or no stored files. Something is very broken.
@@ -41,6 +42,7 @@
/obj/item/device/modular_computer/ui_data(mob/user)
var/list/data = get_header_data()
data["programs"] = list()
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
for(var/datum/computer_file/program/P in hard_drive.stored_files)
var/running = 0
if(P in idle_threads)
@@ -55,6 +57,7 @@
/obj/item/device/modular_computer/ui_act(action, params)
if(..())
return
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
switch(action)
if("PC_exit")
kill_program()
@@ -64,7 +67,7 @@
return 1
if("PC_minimize")
var/mob/user = usr
- if(!active_program || !processor_unit)
+ if(!active_program || !all_components[MC_CPU])
return
idle_threads.Add(active_program)
@@ -112,7 +115,9 @@
update_icon()
return
- if(idle_threads.len >= processor_unit.max_idle_programs+1)
+ var/obj/item/weapon/computer_hardware/processor_unit/PU = all_components[MC_CPU]
+
+ if(idle_threads.len > PU.max_idle_programs)
user << "\The [src] displays a \"Maximal CPU load reached. Unable to run another program.\" error."
return
diff --git a/code/modules/modular_computers/computers/item/processor.dm b/code/modules/modular_computers/computers/item/processor.dm
index 65712546ef6..d50b9f9fd30 100644
--- a/code/modules/modular_computers/computers/item/processor.dm
+++ b/code/modules/modular_computers/computers/item/processor.dm
@@ -23,6 +23,8 @@
CRASH("Inapropriate type passed to obj/item/device/modular_computer/processor/New()! Aborting.")
return
// Obtain reference to machinery computer
+ all_components = list()
+ idle_threads = list()
machinery_computer = comp
machinery_computer.cpu = src
hardware_flag = machinery_computer.hardware_flag
@@ -53,3 +55,17 @@
..()
machinery_computer.update_icon()
return
+
+/obj/item/device/modular_computer/processor/add_verb(path)
+ switch(path)
+ if(MC_CARD)
+ machinery_computer.verbs += /obj/machinery/modular_computer/proc/eject_id
+ if(MC_SDD)
+ machinery_computer.verbs += /obj/machinery/modular_computer/proc/eject_disk
+
+/obj/item/device/modular_computer/processor/remove_verb(path)
+ switch(path)
+ if(MC_CARD)
+ machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_id
+ if(MC_SDD)
+ machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_disk
\ No newline at end of file
diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm
index 0c8cad838de..54e27ea1d15 100644
--- a/code/modules/modular_computers/computers/item/tablet.dm
+++ b/code/modules/modular_computers/computers/item/tablet.dm
@@ -1,4 +1,4 @@
-/obj/item/device/modular_computer/tablet
+/obj/item/device/modular_computer/tablet //Its called tablet for theme of 90ies but actually its a "big smartphone" sized
name = "tablet computer"
icon = 'icons/obj/modular_tablet.dmi'
icon_state = "tablet"
@@ -9,3 +9,4 @@
max_hardware_size = 1
w_class = 2
steel_sheet_cost = 1
+ slot_flags = SLOT_ID | SLOT_BELT
\ No newline at end of file
diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm
index a4741b16745..7f16199f53f 100644
--- a/code/modules/modular_computers/computers/machinery/console_presets.dm
+++ b/code/modules/modular_computers/computers/machinery/console_presets.dm
@@ -30,8 +30,9 @@
desc = "A stationary computer. This one comes preloaded with engineering programs."
/obj/machinery/modular_computer/console/preset/engineering/install_programs()
- cpu.hard_drive.store_file(new/datum/computer_file/program/power_monitor())
- cpu.hard_drive.store_file(new/datum/computer_file/program/alarm_monitor())
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
+ hard_drive.store_file(new/datum/computer_file/program/power_monitor())
+ hard_drive.store_file(new/datum/computer_file/program/alarm_monitor())
// ===== RESEARCH CONSOLE =====
/obj/machinery/modular_computer/console/preset/research
@@ -39,9 +40,10 @@
desc = "A stationary computer. This one comes preloaded with research programs."
/obj/machinery/modular_computer/console/preset/research/install_programs()
- cpu.hard_drive.store_file(new/datum/computer_file/program/ntnetmonitor())
- cpu.hard_drive.store_file(new/datum/computer_file/program/nttransfer())
- cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
+ hard_drive.store_file(new/datum/computer_file/program/ntnetmonitor())
+ hard_drive.store_file(new/datum/computer_file/program/nttransfer())
+ hard_drive.store_file(new/datum/computer_file/program/chatclient())
// ===== COMMAND CONSOLE =====
@@ -52,8 +54,9 @@
_has_printer = 1
/obj/machinery/modular_computer/console/preset/command/install_programs()
- cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
- cpu.hard_drive.store_file(new/datum/computer_file/program/card_mod())
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
+ hard_drive.store_file(new/datum/computer_file/program/chatclient())
+ hard_drive.store_file(new/datum/computer_file/program/card_mod())
// ===== CIVILIAN CONSOLE =====
/obj/machinery/modular_computer/console/preset/civilian
@@ -61,6 +64,6 @@
desc = "A stationary computer. This one comes preloaded with generic programs."
/obj/machinery/modular_computer/console/preset/civilian/install_programs()
- cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
- cpu.hard_drive.store_file(new/datum/computer_file/program/nttransfer())
-
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
+ hard_drive.store_file(new/datum/computer_file/program/chatclient())
+ hard_drive.store_file(new/datum/computer_file/program/nttransfer())
\ No newline at end of file
diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm
index 2aada0b5860..e04bc0cee73 100644
--- a/code/modules/modular_computers/computers/machinery/modular_computer.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm
@@ -74,7 +74,7 @@ var/list/global_modular_computers = list()
add_overlay("broken")
// Eject ID card from computer, if it has ID slot with card inside.
-/obj/machinery/modular_computer/verb/eject_id()
+/obj/machinery/modular_computer/proc/eject_id()
set name = "Eject ID"
set category = "Object"
set src in view(1)
@@ -83,7 +83,7 @@ var/list/global_modular_computers = list()
cpu.eject_id()
// Eject ID card from computer, if it has ID slot with card inside.
-/obj/machinery/modular_computer/verb/eject_disk()
+/obj/machinery/modular_computer/proc/eject_disk()
set name = "Eject Data Disk"
set category = "Object"
set src in view(1)
@@ -109,8 +109,9 @@ var/list/global_modular_computers = list()
// Used in following function to reduce copypaste
/obj/machinery/modular_computer/proc/power_failure(malfunction = 0)
+ var/obj/item/weapon/computer_hardware/battery/battery_module = cpu.all_components[MC_CELL]
if(cpu && cpu.enabled) // Shut down the computer
- visible_message("\The [src]'s screen flickers [cpu.battery_module ? "\"BATTERY [malfunction ? "MALFUNCTION" : "CRITICAL"]\"" : "\"EXTERNAL POWER LOSS\""] warning as it shuts down unexpectedly.")
+ visible_message("\The [src]'s screen flickers [battery_module ? "\"BATTERY [malfunction ? "MALFUNCTION" : "CRITICAL"]\"" : "\"EXTERNAL POWER LOSS\""] warning as it shuts down unexpectedly.")
if(cpu)
cpu.shutdown_computer(0)
stat |= NOPOWER
@@ -119,7 +120,7 @@ var/list/global_modular_computers = list()
// Modular computers can have battery in them, we handle power in previous proc, so prevent this from messing it up for us.
/obj/machinery/modular_computer/power_change()
- if(cpu && cpu.use_power()) // If "CPU" still has a power source, PC wouldn't go offline.
+ if(cpu && cpu.use_power()) // If MC_CPU still has a power source, PC wouldn't go offline.
stat &= ~NOPOWER
update_icon()
return
diff --git a/code/modules/modular_computers/computers/machinery/modular_console.dm b/code/modules/modular_computers/computers/machinery/modular_console.dm
index b5b6fe7b143..cebb1f4d715 100644
--- a/code/modules/modular_computers/computers/machinery/modular_console.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_console.dm
@@ -22,29 +22,35 @@
/obj/machinery/modular_computer/console/buildable/New()
..()
// User-built consoles start as empty frames.
- qdel(cpu.recharger)
- qdel(cpu.network_card)
- qdel(cpu.hard_drive)
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
+ var/obj/item/weapon/computer_hardware/hard_drive/network_card = cpu.all_components[MC_NET]
+ var/obj/item/weapon/computer_hardware/hard_drive/recharger = cpu.all_components[MC_CHARGE]
+ qdel(recharger)
+ qdel(network_card)
+ qdel(hard_drive)
/obj/machinery/modular_computer/console/New()
..()
- if(cpu.battery_module)
- qdel(cpu.battery_module)
+ var/obj/item/weapon/computer_hardware/battery/battery_module = cpu.all_components[MC_CELL]
+ if(battery_module)
+ qdel(battery_module)
- cpu.install_component(new /obj/item/weapon/computer_hardware/network_card/wired)
+ var/obj/item/weapon/computer_hardware/network_card/wired/network_card = new()
+
+ cpu.install_component(network_card)
cpu.install_component(new /obj/item/weapon/computer_hardware/recharger/APC)
cpu.install_component(new /obj/item/weapon/computer_hardware/hard_drive/super) // Consoles generally have better HDDs due to lower space limitations
var/area/A = get_area(src)
// Attempts to set this console's tag according to our area. Since some areas have stuff like "XX - YY" in their names we try to remove that too.
if(A && console_department)
- cpu.network_card.identification_string = replacetext(replacetext(replacetext("[A.name] [console_department] Console", " ", "_"), "-", ""), "__", "_") // Replace spaces with "_"
+ network_card.identification_string = replacetext(replacetext(replacetext("[A.name] [console_department] Console", " ", "_"), "-", ""), "__", "_") // Replace spaces with "_"
else if(A)
- cpu.network_card.identification_string = replacetext(replacetext(replacetext("[A.name] Console", " ", "_"), "-", ""), "__", "_")
+ network_card.identification_string = replacetext(replacetext(replacetext("[A.name] Console", " ", "_"), "-", ""), "__", "_")
else if(console_department)
- cpu.network_card.identification_string = replacetext(replacetext(replacetext("[console_department] Console", " ", "_"), "-", ""), "__", "_")
+ network_card.identification_string = replacetext(replacetext(replacetext("[console_department] Console", " ", "_"), "-", ""), "__", "_")
else
- cpu.network_card.identification_string = "Unknown Console"
+ network_card.identification_string = "Unknown Console"
if(cpu)
cpu.screen_on = 1
update_icon()
\ No newline at end of file
diff --git a/code/modules/modular_computers/documentation.dm b/code/modules/modular_computers/documentation.dm
deleted file mode 100644
index 94e02f8125c..00000000000
--- a/code/modules/modular_computers/documentation.dm
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-
-Ok. so a quick rundown on how to make a program. This is kind of a shitty documentation, but oh well I was asked to.
-
-
-This is how the base program is setup. the rest is mostly tgui stuff. I'll use the ntnetmonitor as a base
-
-/datum/computer_file/program/ntnetmonitor
- filename = "ntmonitor" <- This is obviously the name of the file itself. not much to be said
- filedesc = "NTNet Diagnostics and Monitoring" <- This sort of the official name. it's what shows up on the main menu
- program_icon_state = "comm_monitor" <- This is what the screen will look like when the program is active
- extended_desc = "This program is a dummy. <- This is a sort of description, visible when looking on the ntnet
- size = 12 <- size of the program. Big programs need more hard drive space. Don't make it too big though.
- requires_ntnet = 1 <- if this is set, the program will not run and will close if ntnet connection is lost. mainly for primarily online programs.
- required_access = access_network <- This is access required to run the program itself. ONLY SET THIS FOR SUPER SECURE SHIT. This also acts as transfer_access as well.
- transfer_access = access_change_ids <- this is the access needed to download from ntnet or host on the ptp program. This is what you want to use most of the time.
- available_on_ntnet = 1 <- If it's available to download on ntnet. pretty self explanatory.
- available_on_syndinet = 0 <- ditto but on emagged syndie net. Use this for antag programs
- usage_flags = PROGRAM_ALL // Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL
- ^^- The comment above sorta explains it. Use this to limit what kind of machines can run the program. For example, comms program should be limited to consoles and laptops.
- var/ui_header = "downloader_finished.gif" <- this one is kinda cool. If you have the program minimized, this will show up in the header of the computer screen.
- you can even have the program change what the header is based on the situation! see alarm.dm for an example.
-
-
-Now. for pre-installing stuff.
-
-Primarily done for consoles, there's an install_programs() proc in the console presets file in the machines folder.
-
-for example, the command console one.
-
-/obj/machinery/modular_computer/console/preset/command/install_programs()
- cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
- cpu.hard_drive.store_file(new/datum/computer_file/program/card_mod())
-
-Basically, you want to do cpu.hard_drive.store_file(new/*program path here*()) and put it in the subtype's install_programs().
-Probably pretty self explanatory, but just in case.
-
-Will probably be expanded when new features come around or I get asked to mention something.
-
-*/
\ No newline at end of file
diff --git a/code/modules/modular_computers/documentation.md b/code/modules/modular_computers/documentation.md
new file mode 100644
index 00000000000..88d8602729d
--- /dev/null
+++ b/code/modules/modular_computers/documentation.md
@@ -0,0 +1,45 @@
+
+
+#Modular computer programs
+Ok. so a quick rundown on how to make a program. This is kind of a shitty documentation, but oh well I was asked to.
+
+
+## Base setup
+This is how the base program is setup. the rest is mostly tgui stuff. I'll use the ntnetmonitor as a base
+
+
+```DM
+/datum/computer_file/program/ntnetmonitor
+ filename = "ntmonitor" //This is obviously the name of the file itself. not much to be said
+ filedesc = "NTNet Diagnostics and Monitoring" // This is sort of the official name. it's what shows up on the main menu
+ program_icon_state = "comm_monitor" // This is what the screen will look like when the program is active
+ extended_desc = "This program is a dummy. // This is a sort of a description, visible when looking on the ntnet
+ size = 12 // size of the program. Big programs need more hard drive space. Don't make it too big though.
+ requires_ntnet = 1 // If this is set, the program will not run without an ntnet connection, and will close if the connection is lost. Mainly for primarily online programs.
+ required_access = access_network //This is access required to run the program itself. ONLY SET THIS FOR SUPER SECURE SHIT. This also acts as transfer_access as well.
+ transfer_access = access_change_ids // This is the access needed to download from ntnet or host on the ptp program. This is what you want to use most of the time.
+ available_on_ntnet = 1 //If it's available to download on ntnet. pretty self explanatory.
+ available_on_syndinet = 0 // ditto but on emagged syndie net. Use this for antag programs
+ usage_flags = PROGRAM_ALL // Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL
+ //^^- The comment above sorta explains it. Use this to limit what kind of machines can run the program. For example, comms program should be limited to consoles and laptops.
+ var/ui_header = "downloader_finished.gif" //This one is kinda cool. If you have the program minimized, this will show up in the header of the computer screen.
+ //you can even have the program change what the header is based on the situation! see alarm.dm for an example.
+```
+
+##Preinstalls
+Now. for pre-installing stuff.
+
+Primarily done for consoles, there's an install_programs() proc in the console presets file in the machines folder.
+
+for example, the command console one.
+
+```DM
+/obj/machinery/modular_computer/console/preset/command/install_programs()
+ cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
+ cpu.hard_drive.store_file(new/datum/computer_file/program/card_mod())
+```
+Basically, you want to do cpu.hard_drive.store_file(new/*program path here*()) and put it in the subtype's install_programs().
+Probably pretty self explanatory, but just in case.
+
+Will probably be expanded when new features come around or I get asked to mention something.
+
diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm
index 8ddff02fb64..46a9ea8ebc8 100644
--- a/code/modules/modular_computers/file_system/program.dm
+++ b/code/modules/modular_computers/file_system/program.dm
@@ -87,6 +87,11 @@
return 1
if(ishuman(user))
+ var/obj/item/weapon/card/id/D
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot
+ if(computer && card_slot)
+ card_slot = computer.all_components[MC_CARD]
+ D = card_slot.GetID()
var/mob/living/carbon/human/h = user
var/obj/item/weapon/card/id/I = h.get_idcard()
var/obj/item/weapon/card/id/C = h.get_active_held_item()
@@ -95,7 +100,7 @@
if(!(C && istype(C)))
C = null
- if(!I && !C)
+ if(!I && !C && !D)
if(loud)
user << "\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning."
return 0
@@ -106,6 +111,9 @@
else if(C)
if(access_to_check in C.GetAccess())
return 1
+ else if(D)
+ if(access_to_check in D.GetAccess())
+ return 1
if(loud)
user << "\The [computer] flashes an \"Access Denied\" warning."
return 0
@@ -162,7 +170,7 @@
return 1
if("PC_minimize")
var/mob/user = usr
- if(!computer.active_program || !computer.processor_unit)
+ if(!computer.active_program || !computer.all_components[MC_CPU])
return
computer.idle_threads.Add(computer.active_program)
diff --git a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm
index d14bb885bfe..3d54938ba11 100644
--- a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm
+++ b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm
@@ -69,7 +69,8 @@
executed = 1
target.dos_sources.Add(src)
if(ntnet_global.intrusion_detection_enabled)
- ntnet_global.add_log("IDS WARNING - Excess traffic flood targeting relay [target.uid] detected from device: [computer.network_card.get_network_tag()]")
+ var/obj/item/weapon/computer_hardware/network_card/network_card = computer.all_components[MC_NET]
+ ntnet_global.add_log("IDS WARNING - Excess traffic flood targeting relay [target.uid] detected from device: [network_card.get_network_tag()]")
ntnet_global.intrusion_detection_alarm = 1
return 1
diff --git a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
index f5ae0766f74..89040ca7ae7 100644
--- a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
+++ b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
@@ -19,16 +19,19 @@
computer.visible_message("\The [computer]'s screen brightly flashes and loud electrical buzzing is heard.")
computer.enabled = 0
computer.update_icon()
- qdel(computer.hard_drive)
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
+ var/obj/item/weapon/computer_hardware/battery/battery_module = computer.all_components[MC_CELL]
+ var/obj/item/weapon/computer_hardware/recharger/recharger = computer.all_components[MC_CHARGE]
+ qdel(hard_drive)
computer.take_damage(25, 10, 1, 1)
- if(computer.battery_module && prob(25))
- qdel(computer.battery_module)
+ if(battery_module && prob(25))
+ qdel(battery_module)
computer.visible_message("\The [computer]'s battery explodes in rain of sparks.")
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
spark_system.start()
- if(computer.recharger && prob(50))
- qdel(computer.recharger)
+ if(recharger && prob(50))
+ qdel(recharger)
computer.visible_message("\The [computer]'s recharger explodes in rain of sparks.")
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
spark_system.start()
diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm
index 780045d8b73..0f1b03f4b38 100644
--- a/code/modules/modular_computers/file_system/programs/card.dm
+++ b/code/modules/modular_computers/file_system/programs/card.dm
@@ -88,7 +88,8 @@
/datum/computer_file/program/card_mod/proc/format_jobs(list/jobs)
- var/obj/item/weapon/card/id/id_card = computer.card_slot.stored_card
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
+ var/obj/item/weapon/card/id/id_card = card_slot.stored_card
var/list/formatted = list()
for(var/job in jobs)
formatted.Add(list(list(
@@ -102,11 +103,19 @@
if(..())
return 1
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot
+ var/obj/item/weapon/computer_hardware/printer/printer
+ if(computer)
+ card_slot = computer.all_components[MC_CARD]
+ printer = computer.all_components[MC_PRINT]
+ if(!card_slot)
+ return
+
var/obj/item/weapon/card/id/user_id_card = null
var/mob/user = usr
- var/obj/item/weapon/card/id/id_card = computer.card_slot.stored_card
- var/obj/item/weapon/card/id/auth_card = computer.card_slot.stored_card2
+ var/obj/item/weapon/card/id/id_card = card_slot.stored_card
+ var/obj/item/weapon/card/id/auth_card = card_slot.stored_card2
if(auth_card)
user_id_card = auth_card
@@ -129,7 +138,7 @@
else
show_assignments = 1
if("PRG_print")
- if(computer && computer.printer) //This option should never be called if there is no printer
+ if(computer && printer) //This option should never be called if there is no printer
if(mod_mode)
if(authorized())
var/contents = {"ltZjtg>Z~AZk&^2UA|NHz^1*+B4?A&}~!Z*#v
zkbv(w&|YujI<4>feDJB6!!z2^tgV3GatIE%MHhlZ5Bs +)4BXb>!G1)N;+4z5&{jrbNO2xd9rI m|SwEA;WwXiah^}0+&N?;FMO2w2VqC*+2^@
zK$OdlQR5Uh=N5&ETX!IX0tik}^?e{lUl~^J->NiyI^Zr)FP~$lOyolh |