Merge remote-tracking branch 'upstream/master' into heretic-tweaks

This commit is contained in:
DeltaFire
2020-12-07 21:18:11 +01:00
783 changed files with 40932 additions and 10750 deletions
+2 -1
View File
@@ -783,7 +783,8 @@
if(ispath(chosen, /turf))
T.ChangeTurf(chosen)
else
var/obj/structure/closet/supplypod/centcompod/pod = new()
var/area/pod_storage_area = locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas
var/obj/structure/closet/supplypod/centcompod/pod = new(pick(get_area_turfs(pod_storage_area))) //Lets just have it in the pod bay for a moment instead of runtiming
var/atom/A = new chosen(pod)
A.flags_1 |= ADMIN_SPAWNED_1
new /obj/effect/pod_landingzone(T, pod)
+1 -1
View File
@@ -212,4 +212,4 @@
dat += build_antag_listing()
dat += "</body></html>"
usr << browse(dat.Join(), "window=roundstatus;size=500x500")
usr << browse(dat.Join(), "window=roundstatus;size=500x500")
+3 -1
View File
@@ -33,7 +33,9 @@
H.saved_socks = H.socks
// Mutant randomizing, doesn't affect the mob appearance unless it's the specific mutant.
H.dna.features["mcolor"] = random_short_color()
H.dna.features["mcolor"] = sanitize_hexcolor(random_short_color(), 6)
H.dna.features["mcolor2"] = sanitize_hexcolor(random_short_color(), 6)
H.dna.features["mcolor3"] = sanitize_hexcolor(random_short_color(), 6)
H.dna.features["tail_lizard"] = pick(GLOB.tails_list_lizard)
H.dna.features["snout"] = pick(GLOB.snouts_list)
H.dna.features["horns"] = pick(GLOB.horns_list)
+1 -1
View File
@@ -287,7 +287,7 @@
R = rank_names[new_rank]
if(!R) //rank with that name doesn't exist yet - make it
if(D)
R = new(new_rank, D.rank.rights) //duplicate our previous admin_rank but with a new name
R = new(new_rank, D.rank.rights, D.rank.exclude_rights, D.rank.can_edit_rights) //duplicate our previous admin_rank but with a new name
else
R = new(new_rank) //blank new admin_rank
GLOB.admin_ranks += R
+1 -1
View File
@@ -508,7 +508,7 @@
if("constructwraith")
M.change_mob_type( /mob/living/simple_animal/hostile/construct/wraith , null, null, delmob )
if("shade")
M.change_mob_type( /mob/living/simple_animal/shade , null, null, delmob )
M.change_mob_type( /mob/living/simple_animal/hostile/construct/shade , null, null, delmob )
/////////////////////////////////////new ban stuff
+1 -1
View File
@@ -8,4 +8,4 @@
var/datum/cinematic/choice = input(src,"Cinematic","Choose",null) as anything in subtypesof(/datum/cinematic)
if(choice)
Cinematic(initial(choice.id),world,null)
Cinematic(initial(choice.id),world,null)
+16 -11
View File
@@ -5,7 +5,7 @@
var/ntype = text2num(type)
//Add client links
var/dat = ""
var/list/dat = list()
if(M.client)
dat += "<center><p>Client</p></center>"
dat += "<center>"
@@ -46,22 +46,27 @@
var/log_source = M.logging;
if(source == LOGSRC_CLIENT && M.client) //if client doesn't exist just fall back to the mob log
log_source = M.client.player_details.logging //should exist, if it doesn't that's a bug, don't check for it not existing
var/list/concatenated_logs = list()
for(var/log_type in log_source)
var/nlog_type = text2num(log_type)
if(nlog_type & ntype)
var/list/reversed = log_source[log_type]
if(islist(reversed))
reversed = reverseRange(reversed.Copy())
for(var/entry in reversed)
dat += "<font size=2px><b>[entry]</b><br>[reversed[entry]]</font><br>"
dat += "<hr>"
var/list/all_the_entrys = log_source[log_type]
for(var/entry in all_the_entrys)
concatenated_logs += "<b>[entry]</b><br>[all_the_entrys[entry]]"
if(length(concatenated_logs))
sortTim(concatenated_logs, cmp = /proc/cmp_text_dsc) //Sort by timestamp.
dat += "<font size=2px>"
dat += concatenated_logs.Join("<br>")
dat += "</font>"
usr << browse(dat, "window=invidual_logging_[key_name(M)];size=600x480")
var/datum/browser/popup = new(usr, "invidual_logging_[key_name(M)]", "Individual Logs", 600, 600)
popup.set_content(dat.Join())
popup.open()
/proc/individual_logging_panel_link(mob/M, log_type, log_src, label, selected_src, selected_type)
var/slabel = label
if(selected_type == log_type && selected_src == log_src)
slabel = "<b>\[[label]\]</b>"
return "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[log_type];log_src=[log_src]'>[slabel]</a>"
//This is necessary because num2text drops digits and rounds on big numbers. If more defines get added in the future it could break again.
log_type = num2text(log_type, MAX_BITFLAG_DIGITS)
return "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[log_type];log_src=[log_src]'>[slabel]</a>"
+1 -1
View File
@@ -41,4 +41,4 @@
message_admins("[key_name_admin(usr)] is changing the map to [VM.map_name]")
log_admin("[key_name(usr)] is changing the map to [VM.map_name]")
if (SSmapping.changemap(VM) == 0)
message_admins("[key_name_admin(usr)] has changed the map to [VM.map_name]")
message_admins("[key_name_admin(usr)] has changed the map to [VM.map_name]")
+1 -1
View File
@@ -28,4 +28,4 @@ GLOBAL_VAR_INIT(highlander, FALSE)
addtimer(CALLBACK(src, .proc/only_one), 420)
/mob/living/carbon/human/proc/make_scottish()
mind.add_antag_datum(/datum/antagonist/highlander)
mind.add_antag_datum(/datum/antagonist/highlander)
+2 -1
View File
@@ -1347,7 +1347,8 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
new /obj/effect/immovablerod(startT, endT,target)
if(ADMIN_PUNISHMENT_SUPPLYPOD_QUICK)
var/target_path = input(usr,"Enter typepath of an atom you'd like to send with the pod (type \"empty\" to send an empty pod):" ,"Typepath","/obj/item/reagent_containers/food/snacks/grown/harebell") as null|text
var/obj/structure/closet/supplypod/centcompod/pod = new()
var/area/pod_storage_area = locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas
var/obj/structure/closet/supplypod/centcompod/pod = new(pick(get_area_turfs(pod_storage_area))) //Lets not runtime
pod.damage = 40
pod.explosionSize = list(0,0,0,2)
pod.effectStun = TRUE
@@ -27,4 +27,4 @@
if(!SSdbcore.Connect())
message_admins("Database connection failed: " + SSdbcore.ErrorMsg())
else
message_admins("Database connection re-established")
message_admins("Database connection re-established")
@@ -93,4 +93,4 @@
return "[header][item]</li>"
#undef VV_HTML_ENCODE
#undef VV_HTML_ENCODE
+1 -1
View File
@@ -98,7 +98,7 @@
L.adjustFireLoss(amount)
newamt = L.getFireLoss()
if("toxin")
L.adjustToxLoss(amount)
L.adjustToxLoss(amount, toxins_type = TOX_OMNI)
newamt = L.getToxLoss()
if("oxygen")
L.adjustOxyLoss(amount)
@@ -16,4 +16,4 @@
continue
var/datum/team/T = A.get_team()
if(!team_type || istype(T,team_type))
. |= T
. |= T
@@ -50,4 +50,4 @@
/datum/mind/proc/leave_all_antag_huds()
for(var/datum/atom_hud/antag/hud in GLOB.huds)
if(hud.hudusers[current])
hud.leave_hud(current)
hud.leave_hud(current)
@@ -52,4 +52,4 @@
user.temporarilyRemoveItemFromInventory(tool, TRUE)
var/obj/item/organ/heart/gland/gland = tool
gland.Insert(target, 2)
return 1
return 1
@@ -110,4 +110,4 @@
active = 0
/obj/item/organ/heart/gland/proc/activate()
return
return
@@ -17,4 +17,4 @@
/obj/item/organ/heart/gland/access/Remove(special = FALSE)
if(!QDELETED(owner))
UnregisterSignal(owner, COMSIG_MOB_ALLOWED)
return ..()
return ..()
@@ -15,4 +15,4 @@
var/mob/living/carbon/human/H = owner
var/datum/species/species = H.dna.species
to_chat(H, "<span class='warning'>You feel your blood heat up for a moment.</span>")
species.exotic_blood = get_random_reagent_id()
species.exotic_blood = get_random_reagent_id()
@@ -17,4 +17,4 @@
var/chem_to_add = pick(possible_reagents)
owner.reagents.add_reagent(chem_to_add, 2)
owner.adjustToxLoss(-5, TRUE, TRUE)
..()
..()
@@ -12,4 +12,4 @@
/obj/item/organ/heart/gland/egg/activate()
owner.visible_message("<span class='alertalien'>[owner] [pick(EGG_LAYING_MESSAGES)]</span>")
var/turf/T = owner.drop_location()
new /obj/item/reagent_containers/food/snacks/egg/gland(T)
new /obj/item/reagent_containers/food/snacks/egg/gland(T)
@@ -24,4 +24,4 @@
/obj/item/organ/heart/gland/electric/proc/zap()
tesla_zap(owner, 4, 8000, ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_MOB_STUN)
playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, TRUE)
playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, TRUE)
@@ -175,4 +175,4 @@
var/obj/item/bodypart/chest/new_chest = new(null)
new_chest.replace_limb(owner, TRUE)
qdel(chest)
qdel(chest)
@@ -61,4 +61,4 @@
to_chat(H, "<span class='userdanger'>You feel the compulsion fade, and you <i>completely forget</i> about your previous orders.</span>")
H.clear_alert("mind_control")
active_mind_control = FALSE
return TRUE
return TRUE
@@ -19,4 +19,4 @@
var/turf/open/T = get_turf(owner)
if(istype(T))
T.atmos_spawn_air("plasma=50;TEMP=[T20C]")
owner.vomit()
owner.vomit()
@@ -44,4 +44,4 @@
if(active_mind_control)
to_chat(entangled_mob, "<span class='userdanger'>You feel the compulsion fade, and you completely forget about your previous orders.</span>")
entangled_mob.clear_alert("mind_control")
..()
..()
@@ -23,4 +23,4 @@
var/mob/living/simple_animal/slime/Slime = new(get_turf(owner), "grey")
Slime.Friends = list(owner)
Slime.Leader = owner
Slime.Leader = owner
@@ -11,4 +11,4 @@
to_chat(owner, "<span class='warning'>You feel something crawling in your skin.</span>")
owner.faction |= "spiders"
var/obj/structure/spider/spiderling/S = new(owner.drop_location())
S.directive = "Protect your nest inside [owner.real_name]."
S.directive = "Protect your nest inside [owner.real_name]."
@@ -12,4 +12,4 @@
to_chat(owner, "<span class='notice'>You feel unlike yourself.</span>")
randomize_human(owner)
var/species = pick(list(/datum/species/human, /datum/species/lizard, /datum/species/insect, /datum/species/fly))
owner.set_species(species)
owner.set_species(species)
@@ -9,4 +9,4 @@
/obj/item/organ/heart/gland/ventcrawling/activate()
to_chat(owner, "<span class='notice'>You feel very stretchy.</span>")
owner.ventcrawler = VENTCRAWLER_ALWAYS
owner.ventcrawler = VENTCRAWLER_ALWAYS
@@ -31,4 +31,4 @@
var/datum/symptom/S = new chosen_symptom
A.symptoms += S
A.Refresh() //just in case someone already made and named the same disease
return A
return A
@@ -9,4 +9,4 @@
/obj/structure/fluff/iced_abductor/Destroy()
var/turf/T = get_turf(src)
new /obj/effect/mob_spawn/human/abductor(T)
. = ..()
. = ..()
@@ -81,4 +81,4 @@
/datum/antagonist/bloodsucker/proc/AssignRandomBane()
return
return
@@ -113,4 +113,4 @@
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
popup.open()
*/
*/
@@ -18,7 +18,6 @@
var/list/stored_profiles = list() //list of datum/changelingprofile
var/datum/changelingprofile/first_prof = null
var/dna_max = 6 //How many extra DNA strands the changeling can store for transformation.
var/absorbedcount = 0
/// did we get succed by another changeling
var/hostile_absorbed = FALSE
@@ -252,12 +251,6 @@
var/mob/living/carbon/user = owner.current
if(!istype(user))
return
if(stored_profiles.len)
var/datum/changelingprofile/prof = stored_profiles[1]
if(prof.dna == user.dna && stored_profiles.len >= dna_max)//If our current DNA is the stalest, we gotta ditch it.
if(verbose)
to_chat(user, "<span class='warning'>We have reached our capacity to store genetic information! We must transform before absorbing more.</span>")
return
if(!target)
return
if(NO_DNA_COPY in target.dna.species.species_traits)
@@ -317,9 +310,6 @@
return prof
/datum/antagonist/changeling/proc/add_profile(datum/changelingprofile/prof)
if(stored_profiles.len > dna_max)
if(!push_out_profile())
return
if(!first_prof)
first_prof = prof
@@ -340,19 +330,6 @@
stored_profiles -= prof
qdel(prof)
/datum/antagonist/changeling/proc/get_profile_to_remove()
for(var/datum/changelingprofile/prof in stored_profiles)
if(!prof.protected)
return prof
/datum/antagonist/changeling/proc/push_out_profile()
var/datum/changelingprofile/removeprofile = get_profile_to_remove()
if(removeprofile)
stored_profiles -= removeprofile
return 1
return 0
/datum/antagonist/changeling/proc/create_initial_profile()
var/mob/living/carbon/C = owner.current //only carbons have dna now, so we have to typecaste
if(ishuman(C))
@@ -24,4 +24,4 @@
/obj/effect/proc_holder/changeling/digitalcamo/on_refund(mob/user)
action.Remove(user)
user.digitalcamo = 0
user.digitalinvis = 0
user.digitalinvis = 0
@@ -679,25 +679,26 @@
item_state = "ling_gauntlets"
desc = "Rough bone and chitin, pulsing with an abomination barely called \"life\". Good for punching people, not so much for firearms."
transfer_prints = TRUE
item_flags = DROPDEL // whoops
body_parts_covered = ARMS|HANDS
cold_protection = ARMS|HANDS
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
armor = list("melee" = 20, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 35, "bio" = 35, "rad" = 35, "fire" = 0, "acid" = 0)
enhancement = 9 // first, do harm. all of it. all of the harm. just fuck em up.
wound_enhancement = 9
var/fast_enhancement = 9
var/fast_wound_enhancement = 9
enhancement = 6 // first, do harm. all of it. all of the harm. just fuck em up.
wound_enhancement = 6
var/fast_enhancement = 6
var/fast_wound_enhancement = 6
var/slow_enhancement = 20
var/slow_wound_enhancement = 20
silent = TRUE
inherited_trait = TRAIT_CHUNKYFINGERS // dummy thicc bone hands
secondary_trait = TRAIT_MAULER // its only violence from here, bucko
inherited_trait = TRAIT_CHUNKYFINGERS // how do you expect to shoot anyone with bone covered hands
secondary_trait = TRAIT_MAULER // just punch them idiot
var/fasthands = TRUE
/obj/item/clothing/gloves/fingerless/pugilist/cling/examine(mob/user)
. = ..()
. += "[src] are formed to allow for [fasthands ? "fast, precise strikes" : "crippling, damaging blows"]."
. += "[src] are shaped for [fasthands ? "fast, precise strikes" : "crippling, damaging blows"]."
. += "Alt-click them to change between rapid strikes and strong blows."
/obj/item/clothing/gloves/fingerless/pugilist/cling/AltClick(mob/user)
@@ -57,4 +57,4 @@
/obj/screen/alert/status_effect/agent_pinpointer/changeling
name = "Pheromone Scent"
desc = "The nose always knows."
desc = "The nose always knows."
@@ -22,4 +22,4 @@
if((is_servant_of_ratvar(user) || isobserver(user)) && clockwork_desc)
desc = clockwork_desc
. = ..()
desc = initial(desc)
desc = initial(desc)
@@ -48,4 +48,4 @@
plane = FLOOR_PLANE
/obj/effect/clockwork/overlay/floor/bloodcult //this is used by BLOOD CULT, it shouldn't use such a path...
icon_state = "cult"
icon_state = "cult"
@@ -216,6 +216,14 @@
else if(get_clockwork_power())
to_chat(L, "<span class='brass'>You feel a slight, static shock.</span>")
/obj/effect/clockwork/sigil/transmission/Initialize()
. = ..()
START_PROCESSING(SSobj, src)
/obj/effect/clockwork/sigil/transmission/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/effect/clockwork/sigil/transmission/process()
var/power_drained = 0
var/power_mod = 0.005
@@ -408,7 +416,7 @@
/obj/effect/clockwork/sigil/rite
name = "radiant sigil"
desc = "A glowing sigil glowing with barely-contained power."
desc = "A sigil glowing with barely-contained power."
clockwork_desc = "A sigil that will allow you to perform certain rites on it, provided you have access to sufficient power and materials."
icon_state = "sigiltransmission" //am big lazy - recolored transmission sigil
sigil_name = "Sigil of Rites"
@@ -432,7 +440,8 @@
return
var/list/possible_rites = list()
for(var/datum/clockwork_rite/R in GLOB.all_clockwork_rites)
possible_rites[R] = R
if(is_servant_of_ratvar(user, require_full_power = TRUE) || !R.requires_full_power)
possible_rites[R] = R
var/input_key = input(user, "Choose a rite", "Choosing a rite") as null|anything in possible_rites
if(!input_key)
return
@@ -287,4 +287,4 @@
linked_gateway.visible_message("<span class='warning'>[linked_gateway] begins to destabilise!</span>")
/obj/effect/clockwork/spatial_gateway/stable/pass_through_gateway(atom/movable/A, no_cost = TRUE)
return ..()
return ..()
@@ -1,41 +1,57 @@
//horrifying power drain proc made for clockcult's power drain in lieu of six istypes or six for(x in view) loops
/atom/movable/proc/power_drain(clockcult_user, drain_weapons = FALSE) //This proc as of now is only in use for void volt
/*
horrifying power drain proc made for clockcult's power drain in lieu of six istypes or six for(x in view) loops
args:
clockcult_user: If the user / source has to do with clockcult stuff
drain_weapons: If this drains weaponry, such as batons and guns
recursive: If this recurses through mob / storage contents. ONLY USE THIS IF IT'S NOT CALLED TOO FREQUENTLY, or I'm not liable for any lag / functional issues caused
drain_amount: How much is drained by default; Influenced by a multiplier on most things depending on how much power they usually hold.
*/
/atom/movable/proc/power_drain(clockcult_user, drain_weapons = FALSE, recursive = FALSE, drain_amount = MIN_CLOCKCULT_POWER) //This proc as of now is only in use for void volt and transmission sigils
if(recursive)
var/succ = 0
for(var/V in contents)
var/atom/movable/target = V
succ += target.power_drain(clockcult_user, drain_weapons, recursive, drain_amount)
return succ
var/obj/item/stock_parts/cell/cell = get_cell()
if(cell)
return cell.power_drain(clockcult_user)
return cell.power_drain(clockcult_user, drain_weapons, recursive, drain_amount)
return 0 //Returns 0 instead of FALSE to symbolise it returning the power amount in other cases, not TRUE aka 1
/obj/item/melee/baton/power_drain(clockcult_user, drain_weapons = FALSE) //balance memes
/obj/item/melee/baton/power_drain(clockcult_user, drain_weapons = FALSE, recursive = FALSE, drain_amount = MIN_CLOCKCULT_POWER) //balance memes
if(!drain_weapons)
return 0
return ..()
var/obj/item/stock_parts/cell/cell = get_cell()
if(cell)
return cell.power_drain(clockcult_user, drain_weapons, recursive, drain_amount)
return 0 //No need to recurse further in batons
/obj/item/gun/power_drain(clockcult_user, drain_weapons = FALSE) //balance memes
/obj/item/gun/power_drain(clockcult_user, drain_weapons = FALSE, recursive = FALSE, drain_amount = MIN_CLOCKCULT_POWER) //balance memes
if(!drain_weapons)
return 0
var/obj/item/stock_parts/cell/cell = get_cell()
if(!cell)
return 0
if(cell.charge)
. = min(cell.charge, MIN_CLOCKCULT_POWER*4) //Done snowflakey because guns have far smaller cells than batons / other equipment
. = min(cell.charge, drain_amount*4) //Done snowflakey because guns have far smaller cells than batons / other equipment, also no need to recurse further in guns
cell.use(.)
update_icon()
/obj/machinery/power/apc/power_drain(clockcult_user, drain_weapons = FALSE)
/obj/machinery/power/apc/power_drain(clockcult_user, drain_weapons = FALSE, recursive = FALSE, drain_amount = MIN_CLOCKCULT_POWER)
if(cell && cell.charge)
playsound(src, "sparks", 50, 1)
flick("apc-spark", src)
. = min(cell.charge, MIN_CLOCKCULT_POWER*4)
cell.use(.) //Better than a power sink!
. = min(cell.charge, drain_amount*4)
cell.use(min(cell.charge, . * 4)) //Better than a power sink!
if(!cell.charge && !shorted)
shorted = 1
visible_message("<span class='warning'>The [name]'s screen blurs with static.</span>")
update()
update_icon()
/obj/machinery/power/smes/power_drain(clockcult_user, drain_weapons = FALSE)
/obj/machinery/power/smes/power_drain(clockcult_user, drain_weapons = FALSE, recursive = FALSE, drain_amount = MIN_CLOCKCULT_POWER)
if(charge)
. = min(charge, MIN_CLOCKCULT_POWER*4)
. = min(charge, drain_amount*4)
charge -= . * 50
if(!charge && !panel_open)
panel_open = TRUE
@@ -44,20 +60,26 @@
visible_message("<span class='warning'>[src]'s panel flies open with a flurry of sparks!</span>")
update_icon()
/obj/item/stock_parts/cell/power_drain(clockcult_user, drain_weapons = FALSE)
/obj/item/stock_parts/cell/power_drain(clockcult_user, drain_weapons = FALSE, recursive = FALSE, drain_amount = MIN_CLOCKCULT_POWER)
if(charge)
. = min(charge, MIN_CLOCKCULT_POWER * 4) //Done like this because normal cells are usually quite a bit bigger than the ones used in guns / APCs
. = min(charge, drain_amount * 4) //Done like this because normal cells are usually quite a bit bigger than the ones used in guns / APCs
use(min(charge, . * 10)) //Usually cell-powered equipment that is not a gun has at least ten times the capacity of a gun / 5 times the amount of an APC. This adjusts the drain to account for that.
update_icon()
/mob/living/silicon/robot/power_drain(clockcult_user, drain_weapons = FALSE)
/mob/living/silicon/robot/power_drain(clockcult_user, drain_weapons = FALSE, recursive = FALSE, drain_amount = MIN_CLOCKCULT_POWER)
if((!clockcult_user || !is_servant_of_ratvar(src)) && cell && cell.charge)
. = min(cell.charge, MIN_CLOCKCULT_POWER*4)
. = min(cell.charge, drain_amount*8) //Silicons are very susceptible to Ratvar's might
cell.use(.)
spark_system.start()
/obj/mecha/power_drain(clockcult_user, drain_weapons = FALSE)
if((!clockcult_user || (occupant && !is_servant_of_ratvar(occupant))) && cell && cell.charge)
. = min(cell.charge, MIN_CLOCKCULT_POWER*4)
cell.use(.)
spark_system.start()
/obj/mecha/power_drain(clockcult_user, drain_weapons = FALSE, recursive = FALSE, drain_amount = MIN_CLOCKCULT_POWER)
if(!clockcult_user || (occupant && !is_servant_of_ratvar(occupant)))
if(recursive)
var/succ = 0
for(var/atom/movable/target in contents) //Hiding in your mech won't save you.
succ += target.power_drain(clockcult_user, drain_weapons, recursive, drain_amount)
. = succ
else if(cell && cell.charge)
. = min(cell.charge, drain_amount*4)
cell.use(.)
spark_system.start()
@@ -6,12 +6,13 @@
//The base clockwork rite. This should never be visible
/datum/clockwork_rite
var/name = "Rite of THE frog" //The name of the rite
var/desc = "This rite is used to summon the legendary frog whose-name-shall-not-be-spoken, ender of many worlds." //What does this rite do? Shown to cultists if they choose 'Show Info' after selecting the rite.
var/desc = "This rite is used to summon the legendary frog whose-name-shall-not-be-spoken, ender of many worlds." //What does this rite do? Shown to servants if they choose 'Show Info' after selecting the rite.
var/list/required_ingredients = list(/obj/item/clockwork) //What does this rite require?
var/power_cost = 0 //How much power does this rite cost.. or does it even add power?
var/requires_human = FALSE //Does the rite require a ../carbon/human on the rune?
var/requires_human = FALSE //Does the rite require a ../carbon/human on the sigil?
var/must_be_servant = TRUE //If the above is true, does the human need to be a servant?
var/target_can_be_invoker = TRUE //Does this rite work if the invoker is also the target?
var/requires_full_power = FALSE //Does the invoker need to be an actual full-on servant, or is this available to neutered ones aswell?
var/cast_time = 0 //How long does the rite take to cast?
var/limit = INFINITE //How often can this rite be used per round? Set this to INFINITE for unlimited, 0 for disallowed, anything above 0 for a limit
var/times_used = 0 //How often has the rite already been used this shift?
@@ -99,7 +99,7 @@
else
..()
/obj/item/clockwork/slab/cyborg/ratvar_act()
/obj/item/clockwork/slab/cyborg/ui_act()
..()
if(!GLOB.ratvar_awakens)
SStgui.close_uis(src)
@@ -167,7 +167,7 @@ Judgement 5 converts
set waitfor = FALSE
chanting = TRUE
for(var/invocation in invocations)
sleep(channel_time / invocations.len)
sleep(channel_time / (invocations.len + 1)) //So it always finishes the invocation
if(QDELETED(src) || QDELETED(slab) || !chanting)
return
if(multiple_invokers_used)
@@ -349,4 +349,4 @@
if(GLOB.ratvar_awakens)
portal_uses = max(portal_uses, 100) //Very powerful if Ratvar has been summoned
duration = max(duration, 100)
return slab.procure_gateway(invoker, duration, portal_uses)
return slab.procure_gateway(invoker, duration, portal_uses)
@@ -393,45 +393,49 @@
<b>Left-click a target to fire, quickly!</b></span>"
timeout_time = 20
/datum/clockwork_scripture/channeled/void_volt
descname = "Channeled, Power Drain"
/datum/clockwork_scripture/void_volt
descname = "Pulse, Power Drain"
name = "Void Volt"
desc = "A channeled spell that quickly drains any powercells in a radius of eight tiles, but burns the invoker. \
Can be channeled with more cultists to increase range and split the caused damage evenly over all invokers. \
desc = "A spell that releases a pulse which drains the power of anything in a radius of eight tiles, but burns the invoker. \
Can be used with more servants to increase range and split the caused damage evenly among all invokers. \
Also charges clockwork power by a small percentage of the drained power amount, which can help offset this scriptures powercost."
invocations = list("Channel their energy through my body... ", "... so it may fuel Engine!")
chant_invocations = list("Make their lights fall dark!", "They shall be powerless!", "Rob them of their power!")
chant_amount = 20
chant_interval = 10 //100KW drain per pulse for guns / APCs / 1MW for other cells = 10 chants / 100ds / 10s to drain a charged weapon or a baton with a nonupgraded cell
channel_time = 50
power_cost = 300
invocations = list("Take the energy...", "...of their inventions...", "...and grant it to Engine...", "...for they already live in utter darkness!")
channel_time = 130 //You need alot of time, but it pays off. - ten times as powerful as a regular drain (done by transmission sigils) and recurses + affects weapons - incredibly useful if you can pull this off before a big fight.
power_cost = 500 //Relatively medium powercost, but can be offset due to it adding a part of drained power to the power pool.
multiple_invokers_used = TRUE
multiple_invokers_optional = TRUE
usage_tip = "It may be useful to end channelling early if the burning becomes too much to handle.."
usage_tip = "Be sure to not be injured when using this, or the power channeled through you may overwhelm your body."
tier = SCRIPTURE_SCRIPT
primary_component = GEIS_CAPACITOR
sort_priority = 11
quickbind = TRUE
quickbind_desc = "Quickly drains power in an area around the invoker, causing burns proportional to the amount of energy drained.<br><b>Maximum of 20 chants.</b>"
quickbind_desc = "Quickly drains power in an area around the invoker, causing burns proportional to the amount of energy drained."
/datum/clockwork_scripture/channeled/void_volt/scripture_effects()
/datum/clockwork_scripture/void_volt/chant()
invoker.visible_message("<span class='warning'>[invoker] glows in a brilliant golden light!</span>")
invoker.add_atom_colour("#FFD700", ADMIN_COLOUR_PRIORITY)
invoker.light_power = 2
invoker.light_range = 4
invoker.light_color = LIGHT_COLOR_FIRE
invoker.update_light()
return ..()
addtimer(CALLBACK(invoker, /mob.proc/stop_void_volt_glow), channel_time)
..()//Do the timer & Chant
/mob/proc/stop_void_volt_glow() //Needed so the scripture being qdel()d doesn't prevent it.
visible_message("<span class='warning'>[src] stops glowing...</span>")
remove_atom_colour(ADMIN_COLOUR_PRIORITY)
light_power = 0
light_range = 0
update_light()
/datum/clockwork_scripture/channeled/void_volt/chant_effects(chant_number)
/datum/clockwork_scripture/void_volt/scripture_effects()
var/power_drained = 0
var/power_mod = 0.005 //Amount of power drained (generally) is multiplied with this, and subsequently dealt in damage to the invoker, then 15 times that is added to the clockwork cult's power reserves.
var/drain_range = 8
var/drain_range = 12
var/additional_chanters = 0
var/list/chanters = list()
chanters += invoker
for(var/mob/living/L in range(1, invoker))
for(var/mob/living/L in orange(1, invoker))
if(!L.stat && is_servant_of_ratvar(L))
additional_chanters++
chanters += L
@@ -440,22 +444,14 @@
var/turf/T = t
for(var/M in T)
var/atom/movable/A = M
power_drained += A.power_drain(TRUE, TRUE) //Yes, this absolutely does drain weaponry. 10 pulses to drain guns / batons, though of course they can just be recharged.
power_drained += A.power_drain(TRUE, TRUE, TRUE, MIN_CLOCKCULT_POWER * 10) //Yes, this absolutely does drain weaponry, aswell as recurse through objects. No more hiding in lockers / mechs to avoid it.
new /obj/effect/temp_visual/ratvar/sigil/transgression(invoker.loc, 1 + (power_drained * power_mod))
var/datum/effect_system/spark_spread/S = new
S.set_up(round(1 + (power_drained * power_mod), 1), 0, get_turf(invoker))
S.start()
adjust_clockwork_power(power_drained * power_mod * 15)
for(var/mob/living/L in chanters)
L.adjustFireLoss(round(clamp(power_drained * power_mod / (1 + additional_chanters), 0, 20), 0.1)) //No you won't just immediately melt if you do this in a very power-rich area
L.adjustFireLoss(round(clamp(power_drained * power_mod / (1 + additional_chanters), 0, 70), 0.1)) //No you won't just immediately melt if you do this in a very power-rich area, but it'll be close.
return TRUE
/datum/clockwork_scripture/channeled/void_volt/chant_end_effects()
invoker.visible_message("<span class='warning'>[invoker] stops glowing...</span>")
invoker.remove_atom_colour(ADMIN_COLOUR_PRIORITY)
invoker.light_power = 0
invoker.light_range = 0
invoker.update_light()
return ..()
@@ -83,4 +83,4 @@
anchored = !anchored
to_chat(user, "<span class='notice'>You [anchored ? "secure" : "unsecure"] \the [src].</span>")
I.play_tool_sound(src)
return TRUE
return TRUE
@@ -17,4 +17,4 @@
return
audible_message("<i>*click*</i>")
playsound(src, 'sound/items/screwdriver2.ogg', 50, TRUE)
activate()
activate()
+3 -1
View File
@@ -100,7 +100,7 @@
var/T = new item_path(mob)
var/item_name = initial(item_path.name)
var/where = mob.equip_in_one_of_slots(T, slots)
var/where = mob.equip_in_one_of_slots(T, slots, critical = TRUE)
if(!where)
to_chat(mob, "<span class='userdanger'>Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).</span>")
return 0
@@ -295,6 +295,8 @@
++cultplayers
else
++alive
if(!alive)
return
var/ratio = cultplayers/alive
if(ratio > CULT_RISEN && !cult_risen)
for(var/datum/mind/B in members)
@@ -115,4 +115,4 @@
rune_word_type = /obj/effect/temp_visual/cult/rune_spawn/rune1
rune_innerring_type = /obj/effect/temp_visual/cult/rune_spawn/rune1/inner
rune_center_type = /obj/effect/temp_visual/cult/rune_spawn/rune1/center
rune_color = RUNE_COLOR_MEDIUMRED
rune_color = RUNE_COLOR_MEDIUMRED
+18 -9
View File
@@ -82,7 +82,7 @@ Runes can either be invoked by one's self or with many different cultists. Each
fail_invoke()
/obj/effect/rune/attack_animal(mob/living/simple_animal/M)
if(istype(M, /mob/living/simple_animal/shade) || istype(M, /mob/living/simple_animal/hostile/construct))
if(isshade(M) || istype(M, /mob/living/simple_animal/hostile/construct))
if(construct_invoke || !iscultist(M)) //if you're not a cult construct we want the normal fail message
attack_hand(M)
else
@@ -191,7 +191,7 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/convert/do_invoke_glow()
return
/obj/effect/rune/convert/invoke(var/list/invokers)
/obj/effect/rune/convert/invoke(list/invokers)
if(rune_in_use)
return
var/list/myriad_targets = list()
@@ -203,11 +203,16 @@ structure_check() searches for nearby cultist structures required for the invoca
fail_invoke()
log_game("Offer rune failed - no eligible targets")
return
var/mob/living/L = pick(myriad_targets)
if(HAS_TRAIT(L, TRAIT_SACRIFICED))
fail_invoke()
log_game("Offer rune failed - target has already been sacrificed")
to_chat(invokers, "<span class='warning'>[L] has already been sacrificed!</span>")
return
rune_in_use = TRUE
visible_message("<span class='warning'>[src] pulses blood red!</span>")
var/oldcolor = color
color = RUNE_COLOR_DARKRED
var/mob/living/L = pick(myriad_targets)
var/is_clock = is_servant_of_ratvar(L)
var/mob/living/F = invokers[1]
@@ -264,7 +269,7 @@ structure_check() searches for nearby cultist structures required for the invoca
H.uncuff()
H.stuttering = 0
H.cultslurring = 0
return 1
return TRUE
/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers)
var/mob/living/first_invoker = invokers[1]
@@ -308,12 +313,16 @@ structure_check() searches for nearby cultist structures required for the invoca
stone.invisibility = 0
if(sacrificial)
ADD_TRAIT(sacrificial, TRAIT_SACRIFICED, "sacrificed")
if(iscyborg(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()
var/mob/living/silicon/robot/bot = sacrificial
playsound(sacrificial, 'sound/magic/disable_tech.ogg', 100, TRUE)
bot.deconstruct()
else if(ishuman(sacrificial))
playsound(sacrificial, 'sound/magic/disintegrate.ogg', 100, TRUE)
var/mob/living/carbon/human/H = sacrificial
H.spew_organ(2, 6)
return TRUE
/obj/effect/rune/empower
@@ -35,4 +35,4 @@
DefaultCombatKnockdown(40)
qdel(weapon)
return 2
return 1
return 1
@@ -20,4 +20,4 @@
explanation_text = "You are the BEST thing on the station. Make sure everyone knows it."
/datum/objective/sintouched/acedia
explanation_text = "Angels, devils, good, evil... who cares? Just ignore any hellish threats and do your job."
explanation_text = "Angels, devils, good, evil... who cares? Just ignore any hellish threats and do your job."
@@ -105,7 +105,7 @@
/mob/living/carbon/true_devil/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
return 666
/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash, override_protection = 0)
if(mind && has_bane(BANE_LIGHT))
mind.disrupt_spells(-500)
return ..() //flashes don't stop devils UNLESS it's their bane.
@@ -75,7 +75,7 @@
var/T = new item_path(H)
var/item_name = initial(item_path.name)
var/where = H.equip_in_one_of_slots(T, slots)
var/where = H.equip_in_one_of_slots(T, slots, critical = TRUE)
if(!where)
to_chat(H, "<span class='userdanger'>Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).</span>")
return FALSE
@@ -136,6 +136,7 @@
hoodtype = /obj/item/clothing/head/hooded/cult_hoodie/eldritch
// slightly better than normal cult robes
armor = list("melee" = 50, "bullet" = 50, "laser" = 50,"energy" = 50, "bomb" = 35, "bio" = 20, "rad" = 0, "fire" = 20, "acid" = 20)
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
/obj/item/reagent_containers/glass/beaker/eldritch
name = "flask of eldritch essence"
@@ -6,4 +6,4 @@
/datum/antagonist/magic_servant/proc/setup_master(mob/M)
var/datum/objective/O = new("Serve [M.real_name].")
O.owner = owner
objectives |= O
objectives |= O
@@ -178,4 +178,4 @@
/obj/item/borg_chameleon/proc/disrupt(mob/living/silicon/robot/user)
if(active)
to_chat(user, "<span class='danger'>Your chameleon field deactivates.</span>")
deactivate(user)
deactivate(user)
@@ -131,14 +131,14 @@
"left pocket" = SLOT_L_STORE,
"right pocket" = SLOT_R_STORE
)
var/where = H.equip_in_one_of_slots(O, slots)
var/where = H.equip_in_one_of_slots(O, slots, critical = TRUE)
if (!where)
to_chat(H, "The Syndicate were unfortunately unable to get you the AI module.")
else
to_chat(H, "Use the AI board in your [where] to take control of the AI, as requested by the Syndicate.")
// Give the implant converter
var/obj/item/overthrow_converter/I = new(H)
where = H.equip_in_one_of_slots(I, slots)
where = H.equip_in_one_of_slots(I, slots, critical = TRUE)
if (!where)
to_chat(H, "The Syndicate were unfortunately unable to get you a converter implant.")
else
@@ -251,7 +251,7 @@
"left pocket" = SLOT_L_STORE,
"right pocket" = SLOT_R_STORE
)
var/where = H.equip_in_one_of_slots(T, slots)
var/where = H.equip_in_one_of_slots(T, slots, critical = TRUE)
if (!where)
to_chat(H, "The Syndicate were unfortunately unable to get you a flash.")
else
+1 -1
View File
@@ -28,4 +28,4 @@
santa_objective.explanation_text = "Bring joy and presents to the station!"
santa_objective.completed = 1 //lets cut our santas some slack.
santa_objective.owner = owner
objectives |= santa_objective
objectives |= santa_objective
@@ -16,4 +16,4 @@
return nation
/datum/antagonist/separatist/greet()
to_chat(owner, "<B>You are a separatist! [nation.name] forever! Protect the sovereignty of your newfound land with your comrades in arms!</B>")
to_chat(owner, "<B>You are a separatist! [nation.name] forever! Protect the sovereignty of your newfound land with your comrades in arms!</B>")
@@ -212,7 +212,7 @@
)
var/where = "At your feet"
var/equipped_slot = mob.equip_in_one_of_slots(folder, slots)
var/equipped_slot = mob.equip_in_one_of_slots(folder, slots, critical = TRUE)
if (equipped_slot)
where = "In your [equipped_slot]"
to_chat(mob, "<BR><BR><span class='info'>[where] is a folder containing <b>secret documents</b> that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile.</span><BR>")
@@ -187,8 +187,8 @@
partner_outfit.equip(partner)
var/obj/structure/closet/supplypod/arrival_pod = new()
var/area/pod_storage_area = locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas
var/obj/structure/closet/supplypod/arrival_pod = new(pick(get_area_turfs(pod_storage_area)))
arrival_pod.style = STYLE_SYNDICATE
arrival_pod.explosionSize = list(0,0,0,1)
arrival_pod.bluespace = TRUE
@@ -59,7 +59,8 @@
// Launch the pod to collect our victim.
/datum/syndicate_contract/proc/launch_extraction_pod(turf/empty_pod_turf)
var/obj/structure/closet/supplypod/extractionpod/empty_pod = new()
var/area/pod_storage_area = locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas
var/obj/structure/closet/supplypod/extractionpod/empty_pod = new(pick(get_area_turfs(pod_storage_area))) //Lets not runtime
RegisterSignal(empty_pod, COMSIG_ATOM_ENTERED, .proc/enter_check)
@@ -180,8 +181,8 @@
if(possible_drop_loc.len > 0)
var/pod_rand_loc = rand(1, possible_drop_loc.len)
var/obj/structure/closet/supplypod/return_pod = new()
var/area/pod_storage_area = locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas
var/obj/structure/closet/supplypod/return_pod = new(pick(get_area_turfs(pod_storage_area)))
return_pod.bluespace = TRUE
return_pod.explosionSize = list(0,0,0,0)
return_pod.style = STYLE_SYNDICATE
@@ -16,4 +16,4 @@
/datum/antagonist/heartbreaker/greet()
to_chat(owner, "<span class='warning'><B>You didn't get a date! They're all having fun without you! you'll show them though...</B></span>")
owner.announce_objectives()
owner.announce_objectives()
@@ -36,7 +36,7 @@
/obj/item/soulstone/examine(mob/user)
. = ..()
if(usability || iscultist(user, TRUE) || iswizard(user) || isobserver(user))
if(usability || iscultist(user) || iswizard(user) || isobserver(user))
if (old_shard)
. += "<span class='cult'>A soulstone, used to capture a soul, either from dead humans or from freed shades.</span>"
else
@@ -46,7 +46,7 @@
. += "<span class='cult'>This shard is spent; it is now just a creepy rock.</span>"
/obj/item/soulstone/Destroy() //Stops the shade from being qdel'd immediately and their ghost being sent back to the arrival shuttle.
for(var/mob/living/simple_animal/shade/A in src)
for(var/mob/living/simple_animal/hostile/construct/shade/A in src)
A.death()
return ..()
@@ -58,7 +58,7 @@
to_chat(user, "<span class='userdanger'>Your body is wracked with debilitating pain!</span>")
return
if(spent)
to_chat(user, "<span class='warning'>There is no power left in the shard.</span>")
to_chat(user, "<span class='warning'>There is no power left in [src].</span>")
return
if(!ishuman(M))//If target is not a human.
return ..()
@@ -81,7 +81,7 @@
release_shades(user)
/obj/item/soulstone/proc/release_shades(mob/user)
for(var/mob/living/simple_animal/shade/A in src)
for(var/mob/living/simple_animal/hostile/construct/shade/A in src)
A.status_flags &= ~GODMODE
A.forceMove(get_turf(user))
A.mobility_flags = MOBILITY_FLAGS_DEFAULT
@@ -103,12 +103,12 @@
/obj/structure/constructshell/examine(mob/user)
. = ..()
if(iscultist(user, TRUE) || iswizard(user) || user.stat == DEAD)
. += "<span class='cult'>A construct shell, used to house bound souls from a soulstone.</span>"
. += "<span class='cult'>Placing a soulstone with a soul into this shell allows you to produce your choice of the following:</span>"
. += "<span class='cult'>An <b>Artificer</b>, which can produce <b>more shells and soulstones</b>, as well as fortifications.</span>"
. += "<span class='cult'>A <b>Wraith</b>, which does high damage and can jaunt through walls, though it is quite fragile.</span>"
. += "<span class='cult'>A <b>Juggernaut</b>, which is very hard to kill and can produce temporary walls, but is slow.</span>"
if(iscultist(user) || iswizard(user) || user.stat == DEAD)
. += {"<span class='cult'>A construct shell, used to house bound souls from a soulstone.\n
Placing a soulstone with a soul into this shell allows you to produce your choice of the following:\n
An <b>Artificer</b>, which can produce <b>more shells and soulstones</b>, as well as fortifications.\n
A <b>Wraith</b>, which does high damage and can jaunt through walls, though it is quite fragile.\n
A <b>Juggernaut</b>, which is very hard to kill and can produce temporary walls, but is slow.</span>"}
/obj/structure/constructshell/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/soulstone))
@@ -145,14 +145,14 @@
if("VICTIM")
var/mob/living/carbon/human/T = target
var/datum/antagonist/cult/C = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(C && C.cult_team?.is_sacrifice_target(T.mind))
if(C?.cult_team.is_sacrifice_target(T.mind))
if(iscultist(user))
to_chat(user, "<span class='cult'><b>\"This soul is mine.</b></span> <span class='cultlarge'>SACRIFICE THEM!\"</span>")
else
to_chat(user, "<span class='danger'>The soulstone seems to reject this soul.</span>")
to_chat(user, "<span class='danger'>[src] seems to reject this soul.</span>")
return FALSE
if(contents.len)
to_chat(user, "<span class='userdanger'>Capture failed!</span>: The soulstone is full! Free an existing soul to make room.")
to_chat(user, "<span class='userdanger'>Capture failed!</span>: [src] is full! Free an existing soul to make room.")
else
if((!old_shard && T.stat != CONSCIOUS) || (old_shard && T.stat == DEAD))
if(T.client == null)
@@ -167,7 +167,7 @@
to_chat(user, "<span class='userdanger'>Capture failed!</span>: Kill or maim the victim first!")
if("SHADE")
var/mob/living/simple_animal/shade/T = target
var/mob/living/simple_animal/hostile/construct/shade/T = target
if(contents.len)
to_chat(user, "<span class='userdanger'>Capture failed!</span>: The soulstone is full! Free an existing soul to make room.")
else
@@ -177,13 +177,13 @@
T.health = T.maxHealth
icon_state = "soulstone2"
name = "soulstone: Shade of [T.real_name]"
to_chat(T, "<span class='notice'>Your soul has been captured by the soulstone. Its arcane energies are reknitting your ethereal form.</span>")
to_chat(T, "<span class='notice'>Your soul has been captured by [src]. Its arcane energies are reknitting your ethereal form.</span>")
if(user != T)
to_chat(user, "<span class='info'><b>Capture successful!</b>:</span> [T.real_name]'s soul has been captured and stored within the soulstone.")
to_chat(user, "<span class='info'><b>Capture successful!</b>:</span> [T.real_name]'s soul has been captured and stored within [src].")
if("CONSTRUCT")
var/obj/structure/constructshell/T = target
var/mob/living/simple_animal/shade/A = locate() in src
var/mob/living/simple_animal/hostile/construct/shade/A = locate() in src
if(A)
var/construct_class = alert(user, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer")
if(!T || !T.loc)
@@ -199,8 +199,8 @@
if(iscultist(user) || iswizard(user))
makeNewConstruct(/mob/living/simple_animal/hostile/construct/builder, A, user, 0, T.loc)
else
makeNewConstruct(/mob/living/simple_animal/hostile/construct/builder/noncult, A, user, 0, T.loc)
else
return
for(var/datum/mind/B in SSticker.mode.cult)
if(B == A.mind)
SSticker.mode.cult -= A.mind
@@ -208,19 +208,24 @@
qdel(T)
qdel(src)
else
to_chat(user, "<span class='userdanger'>Creation failed!</span>: The soul stone is empty! Go kill someone!")
to_chat(user, "<span class='userdanger'>Creation failed!</span>: [src] is empty! Go kill someone!")
/proc/makeNewConstruct(mob/living/simple_animal/hostile/construct/ctype, mob/target, mob/stoner = null, cultoverride = 0, loc_override = null)
if(QDELETED(target))
return
var/mob/living/simple_animal/hostile/construct/newstruct = new ctype((loc_override) ? (loc_override) : (get_turf(target)))
if(stoner)
newstruct.faction |= "[REF(stoner)]"
newstruct.master = stoner
var/datum/action/innate/seek_master/SM = new()
SM.Grant(newstruct)
target.transfer_ckey(newstruct)
newstruct.key = target.key
if(target.type == /mob/living/simple_animal/hostile/construct/shade) //Make sure we remember which body belonged to the shade
var/mob/living/simple_animal/hostile/construct/shade/shade = target
newstruct.original_mind = shade.original_mind
var/obj/screen/alert/bloodsense/BS
if(newstruct.mind && ((stoner && iscultist(stoner)) || cultoverride) && SSticker && SSticker.mode)
if(newstruct.mind && ((stoner && iscultist(stoner)) || cultoverride) && SSticker?.mode)
SSticker.mode.add_cultist(newstruct.mind, 0)
if(iscultist(stoner) || cultoverride)
to_chat(newstruct, "<b>You are still bound to serve the cult[stoner ? " and [stoner]":""], follow [stoner ? stoner.p_their() : "their"] orders and help [stoner ? stoner.p_them() : "them"] complete [stoner ? stoner.p_their() : "their"] goals at all costs.</b>")
@@ -234,19 +239,18 @@
/obj/item/soulstone/proc/init_shade(mob/living/carbon/human/T, mob/user, vic = 0)
new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton
if(HAS_TRAIT_FROM(T, TRAIT_SACRIFICED, "sacrificed"))
if(user)
to_chat(user, "This body has already been harvested!")
return
ADD_TRAIT(T, TRAIT_SACRIFICED, "sacrificed")
T.stop_sound_channel(CHANNEL_HEARTBEAT)
T.invisibility = INVISIBILITY_ABSTRACT
T.dust_animation()
QDEL_IN(T, 5)
var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade(src)
S.status_flags |= GODMODE //So they won't die inside the stone somehow
S.mobility_flags = NONE //Can't move out of the soul stone
var/mob/living/simple_animal/hostile/construct/shade/S = new /mob/living/simple_animal/hostile/construct/shade(src)
S.name = "Shade of [T.real_name]"
S.real_name = "Shade of [T.real_name]"
T.transfer_ckey(S)
S.original_mind = T.mind
S.copy_languages(T, LANGUAGE_MIND)//Copies the old mobs languages into the new mob holder.
S.copy_languages(user, LANGUAGE_MASTER)
S.update_atom_languages()
grant_all_languages(FALSE, FALSE, TRUE) //Grants omnitongue
if(user)
@@ -264,7 +268,7 @@
to_chat(user, "<span class='info'><b>Capture successful!</b>:</span> [T.real_name]'s soul has been ripped from [T.p_their()] body and stored within the soul stone.")
/obj/item/soulstone/proc/getCultGhost(mob/living/carbon/human/T, mob/U)
/obj/item/soulstone/proc/getCultGhost(mob/living/carbon/human/T, mob/user)
var/mob/dead/observer/chosen_ghost
for(var/mob/dead/observer/ghost in GLOB.player_list) //We put them back in their body
@@ -279,13 +283,12 @@
if(!T)
return FALSE
if(!chosen_ghost)
to_chat(U, "<span class='danger'>There were no spirits willing to become a shade.</span>")
to_chat(user, "<span class='danger'>There were no spirits willing to become a shade.</span>")
return FALSE
if(contents.len) //If they used the soulstone on someone else in the meantime
return FALSE
T.ckey = chosen_ghost.ckey
for(var/obj/item/W in T)
T.dropItemToGround(W)
init_shade(T, U)
qdel(T)
init_shade(T, user)
return TRUE
+1 -1
View File
@@ -134,4 +134,4 @@
toggle_visibility(D.features["breasts_visibility"], FALSE)
#undef BREASTS_ICON_MIN_SIZE
#undef BREASTS_ICON_MAX_SIZE
#undef BREASTS_ICON_MAX_SIZE
+1 -1
View File
@@ -106,4 +106,4 @@
diameter_ratio = D.features["cock_diameter_ratio"]
shape = D.features["cock_shape"]
prev_length = length
toggle_visibility(D.features["cock_visibility"], FALSE)
toggle_visibility(D.features["cock_visibility"], FALSE)
+1 -1
View File
@@ -13,4 +13,4 @@ Name: IsAssemblyHolder
Desc: If true is an object that can hold an assemblyholder object
*/
/obj/proc/IsAssemblyHolder()
return FALSE
return FALSE
+1 -1
View File
@@ -48,4 +48,4 @@
/obj/item/assembly/playback/toggle_secure()
. = ..()
listening = FALSE
listening = FALSE
@@ -237,12 +237,21 @@
. += "<span class='notice'>Alt-click to [locked ? "unlock" : "lock"] the interface.</span>"
/obj/machinery/airalarm/ui_status(mob/user)
if(hasSiliconAccessInArea(user) && aidisabled)
to_chat(user, "AI control has been disabled.")
else if(!shorted)
if(hasSiliconAccessInArea(user))
if(aidisabled)
to_chat(user, "AI control has been disabled")
return UI_CLOSE
else if(!issilicon(user)) //True sillycones use ..()
return UI_INTERACTIVE
if(!shorted)
return ..()
return UI_CLOSE
/obj/machinery/airalarm/can_interact(mob/user)
. = ..()
if (!issilicon(user) && hasSiliconAccessInArea(user))
return TRUE
/obj/machinery/airalarm/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -336,4 +336,4 @@
return TRUE
/obj/machinery/atmospherics/proc/update_layer()
layer = initial(layer) + (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE
layer = initial(layer) + (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE
@@ -106,4 +106,4 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
/obj/machinery/atmospherics/components/binary/valve/digital/on/layer3
piping_layer = 3
icon_state = "dvalve_map-3"
icon_state = "dvalve_map-3"
@@ -170,4 +170,4 @@
/obj/machinery/atmospherics/components/analyzer_act(mob/living/user, obj/item/I)
atmosanalyzer_scan(airs, user, src)
return TRUE
return TRUE
@@ -196,8 +196,8 @@
icon_state = "inje_map-1"
/obj/machinery/atmospherics/components/unary/outlet_injector/layer3
piping_layer = 2
icon_state = "inje_map-2"
piping_layer = 3
icon_state = "inje_map-3"
/obj/machinery/atmospherics/components/unary/outlet_injector/on
on = TRUE
@@ -207,8 +207,8 @@
icon_state = "inje_map-1"
/obj/machinery/atmospherics/components/unary/outlet_injector/on/layer3
piping_layer = 2
icon_state = "inje_map-2"
piping_layer = 3
icon_state = "inje_map-3"
/obj/machinery/atmospherics/components/unary/outlet_injector/atmos
frequency = FREQ_ATMOS_STORAGE
@@ -208,7 +208,11 @@
stack_trace("[src]([REF(src)]) has one or more null gas mixtures, which may cause bugs. Null mixtures will not be considered in reconcile_air().")
return listclearnulls(.)
/datum/pipeline/proc/reconcile_air()
/datum/pipeline/proc/empty()
for(var/datum/gas_mixture/GM in get_all_connected_airs())
GM.clear()
/datum/pipeline/proc/get_all_connected_airs()
var/list/datum/gas_mixture/GL = list()
var/list/datum/pipeline/PL = list()
PL += src
@@ -233,6 +237,10 @@
var/obj/machinery/atmospherics/components/unary/portables_connector/C = atmosmch
if(C.connected_device)
GL += C.portableConnectorReturnAir()
return GL
/datum/pipeline/proc/reconcile_air()
var/list/datum/gas_mixture/GL = get_all_connected_airs()
var/total_thermal_energy = 0
var/total_heat_capacity = 0
@@ -42,4 +42,4 @@
/obj/machinery/atmospherics/pipe/heat_exchanging/junction/layer3
piping_layer = 3
icon_state = "pipe11-3"
icon_state = "pipe11-3"
@@ -35,4 +35,4 @@
/obj/machinery/atmospherics/pipe/heat_exchanging/simple/layer3
piping_layer = 3
icon_state = "pipe11-3"
icon_state = "pipe11-3"
@@ -38,4 +38,4 @@
if(nodes[i])
add_overlay( getpipeimage(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) )
update_layer()
update_alpha()
update_alpha()
@@ -36,4 +36,4 @@
if(nodes[i])
add_overlay( getpipeimage(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) )
update_layer()
update_alpha()
update_alpha()
@@ -30,4 +30,4 @@
/obj/machinery/atmospherics/pipe/simple/update_icon()
icon_state = "pipe[nodes[1] ? "1" : "0"][nodes[2] ? "1" : "0"]-[piping_layer]"
update_layer()
update_alpha()
update_alpha()
+1 -1
View File
@@ -26,4 +26,4 @@ obj/machinery/atmospherics/pipe/simple/multiz ///This is an atmospherics pipe wh
above.nodes += src //Two way travel :)
return ..()
else
return ..()
return ..()
+1 -1
View File
@@ -27,4 +27,4 @@
/obj/effect/wind/process()
var/turf/open/T = get_turf(src)
if(istype(T))
T.consider_pressure_difference(get_step(T,dir),strength)
T.consider_pressure_difference(get_step(T,dir),strength)
+1 -1
View File
@@ -10,4 +10,4 @@
new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
@@ -155,4 +155,4 @@
endTurfX = 159
endTurfY = 157
startTurfX = 37
startTurfY = 35
startTurfY = 35
@@ -60,4 +60,4 @@
teams never did figure out what happened that last time... and I can't wrap my head \
around it myself. Why would a shuttle full of evacuees all snap and beat each other \
to death the moment they reached safety?<br>\
- D. Cereza"
- D. Cereza"
@@ -0,0 +1,44 @@
// welcome to the jungle, we got fun and games
//areas
/area/awaymission/jungleresort
name = "Jungle Resort"
icon_state = "awaycontent30"
//objects
/obj/item/paper/crumpled/awaymissions/jungleresort/notice
name = "Resort Notice"
info = "Due to unforeseen circumstances and the disappearance of several resort employees and visitors, the resort shall be closed to the public until further notice. - <i>Resort Manager Joe Lawrence</i.>"
/obj/item/melee/chainofcommand/jungle
name = "treasure hunter's whip"
desc = "The tool of a fallen treasure hunter, old and outdated, it still stings like hell to be hit by."
hitsound = 'sound/weapons/whip.ogg'
icon_state = "whip"
//turfs
/turf/open/water/jungle
initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
/turf/open/floor/plating/dirt/jungle
initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
/turf/open/floor/plating/dirt/dark/jungle
initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
/turf/closed/mineral/random/labormineral/jungle
baseturfs = /turf/open/floor/plating/asteroid
turf_type = /turf/open/floor/plating/asteroid
//mobs
/mob/living/carbon/monkey/punpun/curiousgorge
name = "Curious Gorge"
pet_monkey_names = list("Curious Gorge", "Jungle Gorge", "Jungah Joe", "Mr. Monke")
rare_pet_monkey_names = list("Sun Mukong", "Monkey Kong")
/mob/living/simple_animal/hostile/jungle/leaper/boss
health = 450
@@ -150,4 +150,4 @@ GLOBAL_VAR_INIT(sc_safecode5, "[rand(0,9)]")
mezzer()
/obj/singularity/narsie/mini/ex_act()
return
return
+1 -1
View File
@@ -65,4 +65,4 @@ BSQL_DEL_PROC(/datum/BSQL_Connection)
return null;
. = world._BSQL_Internal_Call("QuoteString", id, "[str]")
if(!.)
BSQL_ERROR("Library failed to provide quote for [str]!")
BSQL_ERROR("Library failed to provide quote for [str]!")
+1 -1
View File
@@ -88,4 +88,4 @@
deselect_region()
return
/datum/buildmode_mode/proc/handle_selected_area(client/c, params)
/datum/buildmode_mode/proc/handle_selected_area(client/c, params)
+1 -1
View File
@@ -158,4 +158,4 @@
#undef BM_SWITCHSTATE_NONE
#undef BM_SWITCHSTATE_MODE
#undef BM_SWITCHSTATE_DIR
#undef BM_SWITCHSTATE_DIR
+1 -1
View File
@@ -86,4 +86,4 @@
/obj/screen/buildmode/quit/Click()
bd.quit()
return 1
return 1
+1 -1
View File
@@ -25,4 +25,4 @@
cl.images -= I
cl = null
QDEL_NULL(I)
return ..()
return ..()
+1 -1
View File
@@ -59,4 +59,4 @@
else
var/obj/A = new objholder(T)
A.setDir(BM.build_dir)
log_admin("Build Mode: [key_name(c)] with path [objholder], filled the region from [AREACOORD(cornerA)] through [AREACOORD(cornerB)]")
log_admin("Build Mode: [key_name(c)] with path [objholder], filled the region from [AREACOORD(cornerA)] through [AREACOORD(cornerB)]")
+1 -1
View File
@@ -45,4 +45,4 @@
var/confirm = alert("Are you sure you want run the map generator?", "Run generator", "Yes", "No")
if(confirm == "Yes")
G.generate()
log_admin("Build Mode: [key_name(c)] ran the map generator '[G.buildmode_name]' in the region from [AREACOORD(cornerA)] to [AREACOORD(cornerB)]")
log_admin("Build Mode: [key_name(c)] ran the map generator '[G.buildmode_name]' in the region from [AREACOORD(cornerA)] to [AREACOORD(cornerB)]")
+1 -1
View File
@@ -227,4 +227,4 @@
wanted_types = list(/obj/item/reagent_containers/food/snacks/grown/cannabis/ultimate)
multiplier = 6
bonus_desc = "Under no circumstances mention this shipment to security."
foodtype = "\"meal\""
foodtype = "\"meal\""
+1 -1
View File
@@ -136,4 +136,4 @@
description = "There's a debate around command as to weather or not ribs should be considered finger food, and we need a few delicious racks to process."
reward = 2250
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/bbqribs)
wanted_types = list(/obj/item/reagent_containers/food/snacks/bbqribs)

Some files were not shown because too many files have changed in this diff Show More