Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into turfs

# Conflicts:
#	icons/mob/actions/actions.dmi
#	icons/mob/inhands/items_lefthand.dmi
#	icons/mob/inhands/items_righthand.dmi
#	paradise.dme
This commit is contained in:
Mark van Alphen
2019-05-17 17:37:18 +02:00
69 changed files with 710 additions and 331 deletions
+1 -5
View File
@@ -161,12 +161,8 @@ GLOBAL_VAR(syndicate_code_response) //Code response for traitors.
if(1)//1 and 2 can only be selected once each to prevent more than two specific names/places/etc.
switch(rand(1,2))//Mainly to add more options later.
if(1)
if(names.len&&prob(70))
if(names.len)
code_phrase += pick(names)
else
code_phrase += pick(pick(GLOB.first_names_male,GLOB.first_names_female))
code_phrase += " "
code_phrase += pick(GLOB.last_names)
if(2)
code_phrase += pick(GLOB.joblist)//Returns a job.
safety -= 1
+2 -1
View File
@@ -34,7 +34,7 @@
/obj/screen/plane_master/game_world
name = "game world plane master"
plane = GAME_PLANE
appearance_flags = PLANE_MASTER //should use client color
appearance_flags = PLANE_MASTER
blend_mode = BLEND_OVERLAY
/obj/screen/plane_master/game_world/backdrop(mob/mymob)
@@ -45,6 +45,7 @@
/obj/screen/plane_master/lighting
name = "lighting plane master"
plane = LIGHTING_PLANE
appearance_flags = PLANE_MASTER
blend_mode = BLEND_MULTIPLY
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+115
View File
@@ -0,0 +1,115 @@
/proc/input_async(mob/user=usr, prompt, list/choices)
var/datum/async_input/A = new(choices, prompt)
A.show(user)
return A
/proc/input_ranked_async(mob/user=usr, prompt="Order by greatest to least preference", list/choices)
var/datum/async_input/ranked/A = new(choices, prompt)
A.show(user)
return A
/datum/async_input
var/datum/browser/popup
var/list/choices
var/flash = TRUE
var/immediate_submit = FALSE
var/prompt
var/result = null
var/style = "text-align: center;"
var/window_id
var/height = 200
var/width = 400
/datum/async_input/New(list/new_choices, new_prompt="Pick an option:", new_window_id="async_input")
choices = new_choices
prompt = new_prompt
window_id = new_window_id
/datum/async_input/proc/close()
if(popup)
popup.close()
return result
/datum/async_input/proc/show(mob/user)
var/dat = create_ui(user)
popup = new(user, window_id, , width, height, src)
popup.set_content(dat)
if(flash && result == null)
window_flash(user.client)
popup.open()
/datum/async_input/proc/create_ui(mob/user)
var/dat = "<div style=\"[style]\">"
dat += render_prompt(user)
dat += render_choices(user)
dat += "<br>"
dat += "<br>"
dat += button("Submit", "submit=1", , result == null && !immediate_submit)
dat += "</div>"
return dat
/datum/async_input/proc/render_prompt(mob/user)
return "<h2>[prompt]</h2>"
/datum/async_input/proc/render_choices(mob/user)
var/dat = " "
for(var/choice in choices)
dat += button(choice, "choice=[choice]", choice == result)
dat += " "
return dat
/datum/async_input/proc/button(label, topic, on=FALSE, disabled=FALSE)
var/class = ""
if(on)
class = "linkOn"
if(disabled)
class = "linkOff"
topic = ""
return "<a class=\"[class]\" href='?src=[UID()];[topic]'>[label]</a>"
/datum/async_input/Topic(href, href_list)
if(href_list["submit"] || href_list["close"])
close()
return
if(href_list["choice"])
result = href_list["choice"]
show(usr)
return
/datum/async_input/ranked
height = 400
immediate_submit = TRUE
/datum/async_input/ranked/render_choices(mob/user)
var/dat = "<div>"
dat += "<table style='margin: auto; text-align: left;'>"
for(var/i = 1, i <= choices.len, i++)
var/choice = choices[i]
dat += "<tr>"
dat += "<td>[button("+", i != 1 ? "upvote=[i]" : "", , i == 1)]</td>"
dat += "<td>[button("-", i != choices.len ? "downvote=[i]" : "", , i == choices.len)]</td>"
dat += "<td>[i]. [choice]</td>"
dat += "</tr>"
dat += "</table>"
dat += "</div>"
return dat
/datum/async_input/ranked/Topic(href, href_list)
if(!href_list["close"])
// Mark that user interacted with interface
result = choices
if(href_list["upvote"])
var/index = text2num(href_list["upvote"])
choices.Swap(index, index - 1)
show(usr)
return
if(href_list["downvote"])
var/index = text2num(href_list["downvote"])
choices.Swap(index, index + 1)
show(usr)
return
..()
+6
View File
@@ -18,6 +18,7 @@
However if you want that mind to have any special properties like being a traitor etc you will have to do that
yourself.
*/
#define SUMMON_POSSIBILITIES 3
/datum/mind
var/key
@@ -824,6 +825,11 @@
to_chat(current, "<span class='cultitalic'>Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve [SSticker.cultdat.entity_title2] above all else. Bring It back.</span>")
log_admin("[key_name(usr)] has culted [key_name(current)]")
message_admins("[key_name_admin(usr)] has culted [key_name_admin(current)]")
if(!summon_spots.len)
while(summon_spots.len < SUMMON_POSSIBILITIES)
var/area/summon = pick(return_sorted_areas() - summon_spots)
if(summon && is_station_level(summon.z) && summon.valid_territory)
summon_spots += summon
if("tome")
var/mob/living/carbon/human/H = current
if(istype(H))
+3 -3
View File
@@ -240,10 +240,10 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
var/geneticpoints = 10
var/purchasedpowers = list()
var/mimicing = ""
var/canrespec = 0
var/canrespec = FALSE //set to TRUE in absorb.dm
var/changeling_speak = 0
var/datum/dna/chosen_dna
var/obj/effect/proc_holder/changeling/sting/chosen_sting
var/datum/action/changeling/sting/chosen_sting
var/regenerating = FALSE
/datum/changeling/New(gender=FEMALE)
@@ -329,4 +329,4 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
return 1
/proc/can_absorb_species(datum/species/S)
return !(NO_DNA in S.species_traits)
return !(NO_DNA in S.species_traits)
@@ -3,10 +3,10 @@
* TODO: combine atleast some of the functionality with /proc_holder/spell
*/
/obj/effect/proc_holder/changeling
panel = "Changeling"
/datum/action/changeling
name = "Prototype Sting"
desc = "" // Fluff
background_icon_state = "bg_changeling"
var/helptext = "" // Details
var/chemical_cost = 0 // negative chemical cost is for passive abilities (chemical glands)
var/dna_cost = -1 //cost of the sting in dna points. 0 = auto-purchase, -1 = cannot be purchased
@@ -16,20 +16,26 @@
var/genetic_damage = 0 // genetic damage caused by using the sting. Nothing to do with cloneloss.
var/max_genetic_damage = 100 // hard counter for spamming abilities. Not used/balanced much yet.
var/always_keep = 0 // important for abilities like regenerate that screw you if you lose them.
var/needs_button = TRUE // for passive abilities like hivemind that dont need a button
var/active = FALSE // used by a few powers that toggle
/obj/effect/proc_holder/changeling/proc/on_purchase(var/mob/user)
return
/*
changeling code now relies on on_purchase to grant powers.
if you override it, MAKE SURE you call parent or it will not be usable
the same goes for Remove(). if you override Remove(), call parent or else your power wont be removed on respec
*/
/obj/effect/proc_holder/changeling/proc/on_refund(mob/user)
return
/datum/action/changeling/proc/on_purchase(var/mob/user)
if(needs_button)
Grant(user)
/obj/effect/proc_holder/changeling/Click()
var/mob/user = usr
/datum/action/changeling/Trigger()
var/mob/user = owner
if(!user || !user.mind || !user.mind.changeling)
return
try_to_sting(user)
/obj/effect/proc_holder/changeling/proc/try_to_sting(var/mob/user, var/mob/target)
/datum/action/changeling/proc/try_to_sting(var/mob/user, var/mob/target)
if(!user.mind || !user.mind.changeling)
return
if(!can_sting(user, target))
@@ -39,18 +45,18 @@
sting_feedback(user, target)
take_chemical_cost(c)
/obj/effect/proc_holder/changeling/proc/sting_action(var/mob/user, var/mob/target)
/datum/action/changeling/proc/sting_action(var/mob/user, var/mob/target)
return 0
/obj/effect/proc_holder/changeling/proc/sting_feedback(var/mob/user, var/mob/target)
/datum/action/changeling/proc/sting_feedback(var/mob/user, var/mob/target)
return 0
/obj/effect/proc_holder/changeling/proc/take_chemical_cost(var/datum/changeling/changeling)
/datum/action/changeling/proc/take_chemical_cost(var/datum/changeling/changeling)
changeling.chem_charges -= chemical_cost
changeling.geneticdamage += genetic_damage
//Fairly important to remember to return 1 on success >.<
/obj/effect/proc_holder/changeling/proc/can_sting(var/mob/user, var/mob/target)
/datum/action/changeling/proc/can_sting(var/mob/user, var/mob/target)
if(!ishuman(user)) //typecast everything from mob to carbon from this point onwards
return 0
if(req_human && (!ishuman(user) || issmall(user)))
@@ -75,7 +81,7 @@
return 1
//used in /mob/Stat()
/obj/effect/proc_holder/changeling/proc/can_be_used_by(var/mob/user)
/datum/action/changeling/proc/can_be_used_by(var/mob/user)
if(!ishuman(user))
return 0
if(req_human && !ishuman(user))
@@ -83,10 +89,10 @@
return 1
// Transform the target to the chosen dna. Used in transform.dm and tiny_prick.dm (handy for changes since it's the same thing done twice)
/obj/effect/proc_holder/changeling/proc/transform_dna(var/mob/living/carbon/human/H, var/datum/dna/D)
/datum/action/changeling/proc/transform_dna(var/mob/living/carbon/human/H, var/datum/dna/D)
if(!D)
return
H.set_species(D.species.type, retain_damage = TRUE)
H.dna = D.Clone()
H.real_name = D.real_name
@@ -1,24 +1,25 @@
var/list/sting_paths
// totally stolen from the new player panel. YAYY
/obj/effect/proc_holder/changeling/evolution_menu
/datum/action/changeling/evolution_menu
name = "-Evolution Menu-" //Dashes are so it's listed before all the other abilities.
desc = "Choose our method of subjugation."
button_icon_state = "changelingsting"
dna_cost = 0
/obj/effect/proc_holder/changeling/evolution_menu/Click()
/datum/action/changeling/evolution_menu/Trigger()
if(!usr || !usr.mind || !usr.mind.changeling)
return
var/datum/changeling/changeling = usr.mind.changeling
if(!sting_paths)
sting_paths = init_subtypes(/obj/effect/proc_holder/changeling)
sting_paths = init_subtypes(/datum/action/changeling)
var/dat = create_menu(changeling)
usr << browse(dat, "window=powers;size=600x700")//900x480
/obj/effect/proc_holder/changeling/evolution_menu/proc/create_menu(var/datum/changeling/changeling)
/datum/action/changeling/evolution_menu/proc/create_menu(var/datum/changeling/changeling)
var/dat
dat +="<html><head><title>Changeling Evolution Menu</title></head>"
@@ -230,7 +231,7 @@ var/list/sting_paths
<table width='560' align='center' cellspacing='0' cellpadding='5' id='maintable_data'>"}
var/i = 1
for(var/obj/effect/proc_holder/changeling/cling_power in sting_paths)
for(var/datum/action/changeling/cling_power in sting_paths)
if(cling_power.dna_cost <= 0) //Let's skip the crap we start with. Keeps the evolution menu uncluttered.
continue
@@ -283,7 +284,7 @@ var/list/sting_paths
return dat
/obj/effect/proc_holder/changeling/evolution_menu/Topic(href, href_list)
/datum/action/changeling/evolution_menu/Topic(href, href_list)
..()
if(!(iscarbon(usr) && usr.mind && usr.mind.changeling))
return
@@ -298,11 +299,11 @@ var/list/sting_paths
/datum/changeling/proc/purchasePower(var/mob/living/carbon/user, var/sting_name)
var/obj/effect/proc_holder/changeling/thepower = null
var/datum/action/changeling/thepower = null
if(!sting_paths)
sting_paths = init_subtypes(/obj/effect/proc_holder/changeling)
for(var/obj/effect/proc_holder/changeling/cling_sting in sting_paths)
sting_paths = init_subtypes(/datum/action/changeling)
for(var/datum/action/changeling/cling_sting in sting_paths)
if(cling_sting.name == sting_name)
thepower = cling_sting
@@ -357,7 +358,7 @@ var/list/sting_paths
if(!mind.changeling)
mind.changeling = new /datum/changeling(gender)
if(!sting_paths)
sting_paths = init_subtypes(/obj/effect/proc_holder/changeling)
sting_paths = init_subtypes(/datum/action/changeling)
if(mind.changeling.purchasedpowers)
remove_changeling_powers(1)
@@ -367,8 +368,8 @@ var/list/sting_paths
mind.changeling.absorbed_languages |= language
// purchase free powers.
for(var/obj/effect/proc_holder/changeling/path in sting_paths)
//var/obj/effect/proc_holder/changeling/S = new path()
for(var/datum/action/changeling/path in sting_paths)
//var/datum/action/changeling/S = new path()
if(!path.dna_cost)
if(!mind.changeling.has_sting(path))
mind.changeling.purchasedpowers += path
@@ -406,18 +407,18 @@ var/list/sting_paths
digitalcamo = 0
mind.changeling.changeling_speak = 0
mind.changeling.reset()
for(var/obj/effect/proc_holder/changeling/p in mind.changeling.purchasedpowers)
for(var/datum/action/changeling/p in mind.changeling.purchasedpowers)
if((p.dna_cost == 0 && keep_free_powers) || p.always_keep)
continue
mind.changeling.purchasedpowers -= p
p.on_refund(src)
p.Remove(src)
remove_language("Changeling")
if(hud_used)
hud_used.lingstingdisplay.icon_state = null
hud_used.lingstingdisplay.invisibility = 101
/datum/changeling/proc/has_sting(obj/effect/proc_holder/changeling/power)
for(var/obj/effect/proc_holder/changeling/P in purchasedpowers)
/datum/changeling/proc/has_sting(datum/action/power)
for(var/datum/action/P in purchasedpowers)
if(power.name == P.name)
return 1
return 0
@@ -1,12 +1,13 @@
/obj/effect/proc_holder/changeling/absorbDNA
/datum/action/changeling/absorbDNA
name = "Absorb DNA"
desc = "Absorb the DNA of our victim."
desc = "Absorb the DNA of our victim. Requires us to strangle them."
button_icon_state = "absorb_dna"
chemical_cost = 0
dna_cost = 0
req_human = 1
max_genetic_damage = 100
/obj/effect/proc_holder/changeling/absorbDNA/can_sting(var/mob/living/carbon/user)
/datum/action/changeling/absorbDNA/can_sting(mob/living/carbon/user)
if(!..())
return
@@ -26,7 +27,7 @@
var/mob/living/carbon/target = G.affecting
return changeling.can_absorb_dna(user,target)
/obj/effect/proc_holder/changeling/absorbDNA/sting_action(var/mob/user)
/datum/action/changeling/absorbDNA/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling
var/obj/item/grab/G = user.get_active_hand()
var/mob/living/carbon/human/target = G.affecting
@@ -1,14 +1,15 @@
//Augmented Eyesight: Gives you thermal and night vision - bye bye, flashlights. Also, high DNA cost because of how powerful it is.
//Possible todo: make a custom message for directing a penlight/flashlight at the eyes - not sure what would display though.
/obj/effect/proc_holder/changeling/augmented_eyesight
/datum/action/changeling/augmented_eyesight
name = "Augmented Eyesight"
desc = "Creates heat receptors in our eyes and dramatically increases light sensing ability."
helptext = "Grants us thermal vision or flash protection. We will become a lot more vulnerable to flash-based devices while thermal vision is active."
helptext = "Grants us thermal vision or flash protection. We will become a lot more vulnerable to flash based devices while thermal vision is active."
button_icon_state = "augmented_eyesight"
chemical_cost = 0
dna_cost = 2 //Would be 1 without thermal vision
/obj/effect/proc_holder/changeling/augmented_eyesight/sting_action(mob/living/carbon/human/user)
/datum/action/changeling/augmented_eyesight/sting_action(mob/living/carbon/human/user)
if(!istype(user))
return
if(user.get_int_organ(/obj/item/organ/internal/cyberimp/eyes/thermals/ling))
@@ -21,16 +22,12 @@
return 1
/obj/effect/proc_holder/changeling/augmented_eyesight/on_refund(mob/user)
/datum/action/changeling/augmented_eyesight/Remove(mob/user)
var/obj/item/organ/internal/cyberimp/eyes/O = user.get_organ_slot("eye_ling")
if(O)
O.remove(user)
qdel(O)
..()
/obj/item/organ/internal/cyberimp/eyes/shield/ling
name = "protective membranes"
@@ -1,12 +1,13 @@
/obj/effect/proc_holder/changeling/biodegrade
/datum/action/changeling/biodegrade
name = "Biodegrade"
desc = "Dissolves restraints or other objects preventing free movement."
desc = "Dissolves restraints or other objects preventing free movement. Costs 30 chemicals."
helptext = "This is obvious to nearby people, and can destroy standard restraints and closets."
button_icon_state = "biodegrade"
chemical_cost = 30 //High cost to prevent spam
dna_cost = 2
req_human = 1
/obj/effect/proc_holder/changeling/biodegrade/sting_action(mob/living/carbon/human/user)
/datum/action/changeling/biodegrade/sting_action(mob/living/carbon/human/user)
var/used = FALSE // only one form of shackles removed per use
if(!user.restrained() && !istype(user.loc, /obj/structure/closet) && !istype(user.loc, /obj/structure/spider/cocoon))
to_chat(user, "<span class='warning'>We are already free!</span>")
@@ -30,7 +31,6 @@
addtimer(CALLBACK(src, .proc/dissolve_straightjacket, user, S), 30)
used = TRUE
if(istype(user.loc, /obj/structure/closet) && !used)
var/obj/structure/closet/C = user.loc
if(!istype(C))
@@ -53,21 +53,21 @@
feedback_add_details("changeling_powers","BD")
return TRUE
/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_handcuffs(mob/living/carbon/human/user, obj/O)
/datum/action/changeling/biodegrade/proc/dissolve_handcuffs(mob/living/carbon/human/user, obj/O)
if(O && user.handcuffed == O)
user.unEquip(O)
O.visible_message("<span class='warning'>[O] dissolves into a puddle of sizzling goop.</span>")
O.forceMove(get_turf(user))
qdel(O)
/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_straightjacket(mob/living/carbon/human/user, obj/S)
/datum/action/changeling/biodegrade/proc/dissolve_straightjacket(mob/living/carbon/human/user, obj/S)
if(S && user.wear_suit == S)
user.unEquip(S)
S.visible_message("<span class='warning'>[S] dissolves into a puddle of sizzling goop.</span>")
S.forceMove(get_turf(user))
qdel(S)
/obj/effect/proc_holder/changeling/biodegrade/proc/open_closet(mob/living/carbon/human/user, obj/structure/closet/C)
/datum/action/changeling/biodegrade/proc/open_closet(mob/living/carbon/human/user, obj/structure/closet/C)
if(C && user.loc == C)
C.visible_message("<span class='warning'>[C]'s door breaks and opens!</span>")
C.welded = FALSE
@@ -76,7 +76,7 @@
C.open()
to_chat(user, "<span class='warning'>We open the container restraining us!</span>")
/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_cocoon(mob/living/carbon/human/user, obj/structure/spider/cocoon/C)
/datum/action/changeling/biodegrade/proc/dissolve_cocoon(mob/living/carbon/human/user, obj/structure/spider/cocoon/C)
if(C && user.loc == C)
qdel(C) //The cocoon's destroy will move the changeling outside of it without interference
to_chat(user, "<span class='warning'>We dissolve the cocoon!</span>")
@@ -1,12 +1,13 @@
/obj/effect/proc_holder/changeling/chameleon_skin
/datum/action/changeling/chameleon_skin
name = "Chameleon Skin"
desc = "Our skin pigmentation rapidly changes to suit our current environment."
desc = "Our skin pigmentation rapidly changes to suit our current environment. Costs 25 chemicals."
helptext = "Allows us to become invisible after a few seconds of standing still. Can be toggled on and off."
button_icon_state = "chameleon_skin"
dna_cost = 2
chemical_cost = 25
req_human = 1
/obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user)
/datum/action/changeling/chameleon_skin/sting_action(mob/user)
var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1
if(!istype(H)) // req_human could be done in can_sting stuff.
return
@@ -20,8 +21,9 @@
feedback_add_details("changeling_powers","CS")
return TRUE
/obj/effect/proc_holder/changeling/chameleon_skin/on_refund(mob/user)
/datum/action/changeling/chameleon_skin/Remove(mob/user)
var/mob/living/carbon/C = user
if(C.dna.GetSEState(CHAMELEONBLOCK))
C.dna.SetSEState(CHAMELEONBLOCK, 0)
genemutcheck(C, CHAMELEONBLOCK, null, MUTCHK_FORCED)
..()
@@ -1,11 +1,12 @@
/obj/effect/proc_holder/changeling/digitalcamo
/datum/action/changeling/digitalcamo
name = "Digital Camouflage"
desc = "By evolving the ability to distort our form and proprotions, we defeat common altgorithms used to detect lifeforms on cameras."
helptext = "We cannot be tracked by camera while using this skill. However, humans looking at us will find us... uncanny."
button_icon_state = "digital_camo"
dna_cost = 1
//Prevents AIs tracking you but makes you easily detectable to the human-eye.
/obj/effect/proc_holder/changeling/digitalcamo/sting_action(var/mob/user)
/datum/action/changeling/digitalcamo/sting_action(var/mob/user)
if(user.digitalcamo)
to_chat(user, "<span class='notice'>We return to normal.</span>")
@@ -1,19 +1,21 @@
/obj/effect/proc_holder/changeling/epinephrine
/datum/action/changeling/epinephrine
name = "Epinephrine Overdose"
desc = "We evolve additional sacs of adrenaline throughout our body."
helptext = "Removes all stuns instantly and adds a short-term reduction in further stuns. Can be used while unconscious. Continued use poisons the body."
desc = "We evolve additional sacs of adrenaline throughout our body. Costs 30 chemicals."
helptext = "Removes all stuns instantly and adds a short term reduction in further stuns. Can be used while unconscious. Continued use poisons the body."
button_icon_state = "adrenaline"
chemical_cost = 30
dna_cost = 2
req_human = 1
req_stat = UNCONSCIOUS
//Recover from stuns.
/obj/effect/proc_holder/changeling/epinephrine/sting_action(var/mob/living/user)
/datum/action/changeling/epinephrine/sting_action(var/mob/living/user)
if(user.lying)
to_chat(user, "<span class='notice'>We arise.</span>")
else
to_chat(user, "<span class='notice'>Adrenaline rushes through us.</span>")
user.SetSleeping(0)
user.stat = 0
user.SetParalysis(0)
user.SetStunned(0)
@@ -1,6 +1,7 @@
/obj/effect/proc_holder/changeling/fakedeath
/datum/action/changeling/fakedeath
name = "Regenerative Stasis"
desc = "We fall into a stasis, allowing us to regenerate."
desc = "We fall into a stasis, allowing us to regenerate and trick our enemies. Costs 15 chemicals."
button_icon_state = "fake_death"
chemical_cost = 15
dna_cost = 0
req_dna = 1
@@ -8,7 +9,7 @@
max_genetic_damage = 100
//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay.
/obj/effect/proc_holder/changeling/fakedeath/sting_action(var/mob/living/user)
/datum/action/changeling/fakedeath/sting_action(var/mob/living/user)
to_chat(user, "<span class='notice'>We begin our stasis, preparing energy to arise once more.</span>")
if(user.stat != DEAD)
@@ -26,12 +27,13 @@
feedback_add_details("changeling_powers","FD")
return 1
/obj/effect/proc_holder/changeling/fakedeath/proc/ready_to_regenerate(mob/user)
/datum/action/changeling/fakedeath/proc/ready_to_regenerate(mob/user)
if(user && user.mind && user.mind.changeling && user.mind.changeling.purchasedpowers)
to_chat(user, "<span class='notice'>We are ready to regenerate.</span>")
user.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/revive(null)
var/datum/action/changeling/revive/R = new
R.Grant(user)
/obj/effect/proc_holder/changeling/fakedeath/can_sting(var/mob/user)
/datum/action/changeling/fakedeath/can_sting(var/mob/user)
if(user.status_flags & FAKEDEATH)
to_chat(user, "<span class='warning'>We are already regenerating.</span>")
return
@@ -1,7 +1,8 @@
/obj/effect/proc_holder/changeling/fleshmend
/datum/action/changeling/fleshmend
name = "Fleshmend"
desc = "Our flesh rapidly regenerates, healing our wounds."
helptext = "Heals a moderate amount of damage over a short period of time. Can be used while unconscious."
desc = "Our flesh rapidly regenerates, healing our burns, bruises, and shortness of breath. Costs 20 chemicals."
helptext = "If we are on fire, the healing effect will not function. Does not regrow limbs or restore lost blood. Functions while unconscious."
button_icon_state = "fleshmend"
chemical_cost = 20
dna_cost = 2
req_stat = UNCONSCIOUS
@@ -11,20 +12,20 @@
// divided by healing_ticks to get heal/tick
var/total_healing = 100
/obj/effect/proc_holder/changeling/fleshmend/New()
/datum/action/changeling/fleshmend/New()
..()
START_PROCESSING(SSobj, src)
/obj/effect/proc_holder/changeling/fleshmend/Destroy()
/datum/action/changeling/fleshmend/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/effect/proc_holder/changeling/fleshmend/process()
/datum/action/changeling/fleshmend/process()
if(recent_uses > 1)
recent_uses = max(1, recent_uses - (1 / healing_ticks))
//Starts healing you every second for 10 seconds. Can be used whilst unconscious.
/obj/effect/proc_holder/changeling/fleshmend/sting_action(var/mob/living/user)
/datum/action/changeling/fleshmend/sting_action(var/mob/living/user)
to_chat(user, "<span class='notice'>We begin to heal rapidly.</span>")
if(recent_uses > 1)
to_chat(user, "<span class='warning'>Our healing's effectiveness is reduced \
@@ -35,7 +36,7 @@
feedback_add_details("changeling_powers","RR")
return TRUE
/obj/effect/proc_holder/changeling/fleshmend/proc/fleshmend(mob/living/user)
/datum/action/changeling/fleshmend/proc/fleshmend(mob/living/user)
// The healing itself - doesn't heal toxin damage
// (that's anatomic panacea) and the effectiveness decreases with
@@ -1,17 +1,18 @@
/obj/effect/proc_holder/changeling/headcrab
/datum/action/changeling/headcrab
name = "Last Resort"
desc = "We sacrifice our current body in a moment of need, placing us in control of a vessel."
desc = "We sacrifice our current body in a moment of need, placing us in control of a vessel that can plant our likeness in a new host. Costs 20 chemicals."
helptext = "We will be placed in control of a small, fragile creature. We may attack a corpse like this to plant an egg which will slowly mature into a new form for us."
button_icon_state = "last_resort"
chemical_cost = 20
dna_cost = 1
req_human = 1
/obj/effect/proc_holder/changeling/headcrab/try_to_sting(mob/user, mob/target)
/datum/action/changeling/headcrab/try_to_sting(mob/user, mob/target)
if(alert("Are you sure you wish to do this? This action cannot be undone.",,"Yes","No")=="No")
return
..()
/obj/effect/proc_holder/changeling/headcrab/sting_action(mob/user)
/datum/action/changeling/headcrab/sting_action(mob/user)
var/datum/mind/M = user.mind
var/list/organs = user.get_organs_zone("head", 1)
@@ -42,4 +43,4 @@
to_chat(crab, "<span class='warning'>You burst out of the remains of your former body in a shower of gore!</span>")
user.gib()
feedback_add_details("changeling_powers","LR")
return 1
return 1
@@ -1,34 +1,38 @@
//HIVEMIND COMMUNICATION (:g)
/obj/effect/proc_holder/changeling/hivemind_comms
/datum/action/changeling/hivemind_comms
name = "Hivemind Communication"
desc = "We tune our senses to the airwaves to allow us to discreetly communicate and exchange DNA with other changelings."
helptext = "We will be able to talk with other changelings with :g. Exchanged DNA do not count towards absorb objectives."
dna_cost = 0
chemical_cost = -1
needs_button = FALSE
/obj/effect/proc_holder/changeling/hivemind_comms/on_purchase(var/mob/user)
/datum/action/changeling/hivemind_comms/on_purchase(var/mob/user)
..()
var/datum/changeling/changeling=user.mind.changeling
changeling.changeling_speak = 1
to_chat(user, "<i><font color=#800080>Use say \":g message\" to communicate with the other changelings.</font></i>")
var/obj/effect/proc_holder/changeling/hivemind_upload/S1 = new
var/datum/action/changeling/hivemind_upload/S1 = new
if(!changeling.has_sting(S1))
changeling.purchasedpowers+=S1
var/obj/effect/proc_holder/changeling/hivemind_download/S2 = new
S1.Grant(user)
var/datum/action/changeling/hivemind_download/S2 = new
if(!changeling.has_sting(S2))
S2.Grant(user)
changeling.purchasedpowers+=S2
return
// HIVE MIND UPLOAD/DOWNLOAD DNA
var/list/datum/dna/hivemind_bank = list()
/obj/effect/proc_holder/changeling/hivemind_upload
/datum/action/changeling/hivemind_upload
name = "Hive Channel DNA"
desc = "Allows us to channel DNA in the airwaves to allow other changelings to absorb it."
desc = "Allows us to channel DNA in the airwaves to allow other changelings to absorb it. Costs 10 chemicals."
button_icon_state = "hivemind_channel"
chemical_cost = 10
dna_cost = -1
/obj/effect/proc_holder/changeling/hivemind_upload/sting_action(var/mob/user)
/datum/action/changeling/hivemind_upload/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling
var/list/names = list()
for(var/datum/dna/DNA in (changeling.absorbed_dna+changeling.protected_dna))
@@ -52,13 +56,14 @@ var/list/datum/dna/hivemind_bank = list()
feedback_add_details("changeling_powers","HU")
return 1
/obj/effect/proc_holder/changeling/hivemind_download
/datum/action/changeling/hivemind_download
name = "Hive Absorb DNA"
desc = "Allows us to absorb DNA that has been channeled to the airwaves. Does not count towards absorb objectives."
desc = "Allows us to absorb DNA that has been channeled to the airwaves. Does not count towards absorb objectives. Costs 10 chemicals."
button_icon_state = "hive_absorb"
chemical_cost = 10
dna_cost = -1
/obj/effect/proc_holder/changeling/hivemind_download/can_sting(var/mob/living/carbon/user)
/datum/action/changeling/hivemind_download/can_sting(var/mob/living/carbon/user)
if(!..())
return
var/datum/changeling/changeling = user.mind.changeling
@@ -67,7 +72,7 @@ var/list/datum/dna/hivemind_bank = list()
return
return 1
/obj/effect/proc_holder/changeling/hivemind_download/sting_action(var/mob/user)
/datum/action/changeling/hivemind_download/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling
var/list/names = list()
for(var/datum/dna/DNA in hivemind_bank)
@@ -87,4 +92,4 @@ var/list/datum/dna/hivemind_bank = list()
changeling.store_dna(chosen_dna, user)
to_chat(user, "<span class='notice'>We absorb the DNA of [S] from the air.</span>")
feedback_add_details("changeling_powers","HD")
return 1
return 1
@@ -1,14 +1,14 @@
/obj/effect/proc_holder/changeling/humanform
/datum/action/changeling/humanform
name = "Human form"
desc = "We change into a human."
desc = "We change into a human. Costs 5 chemicals."
button_icon_state = "human_form"
chemical_cost = 5
genetic_damage = 3
req_dna = 1
max_genetic_damage = 3
//Transform into a human.
/obj/effect/proc_holder/changeling/humanform/sting_action(var/mob/living/carbon/human/user)
/datum/action/changeling/humanform/sting_action(var/mob/living/carbon/human/user)
var/datum/changeling/changeling = user.mind.changeling
var/list/names = list()
for(var/datum/dna/DNA in (changeling.absorbed_dna+changeling.protected_dna))
@@ -38,7 +38,7 @@
user.UpdateAppearance()
changeling.purchasedpowers -= src
//O.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/lesserform(null)
//O.mind.changeling.purchasedpowers += new /datum/action/changeling/lesserform(null)
src.Remove(user)
feedback_add_details("changeling_powers","LFT")
return 1
@@ -1,13 +1,15 @@
/obj/effect/proc_holder/changeling/lesserform
/datum/action/changeling/lesserform
name = "Lesser form"
desc = "We debase ourselves and become lesser. We become a monkey."
desc = "We debase ourselves and become lesser. We become a monkey. Costs 5 chemicals."
helptext = "The transformation greatly reduces our size, allowing us to slip out of cuffs and climb through vents."
button_icon_state = "lesser_form"
chemical_cost = 5
dna_cost = 1
genetic_damage = 3
req_human = 1
//Transform into a monkey.
/obj/effect/proc_holder/changeling/lesserform/sting_action(var/mob/living/carbon/human/user)
/datum/action/changeling/lesserform/sting_action(var/mob/living/carbon/human/user)
var/datum/changeling/changeling = user.mind.changeling
if(!user)
return 0
@@ -25,6 +27,10 @@
changeling.geneticdamage = 30
to_chat(H, "<span class='warning'>Our genes cry out!</span>")
H.monkeyize()
changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null)
var/datum/action/changeling/humanform/HF = new
changeling.purchasedpowers += HF
HF.Grant(user)
feedback_add_details("changeling_powers","LF")
return 1
@@ -1,12 +1,14 @@
/obj/effect/proc_holder/changeling/linglink
/datum/action/changeling/linglink
name = "Hivemind Link"
desc = "Link your victim's mind into the hivemind for personal interrogation"
desc = "We link our victim's mind into the hivemind for personal interrogation."
helptext = "If we find a human mad enough to support our cause, this can be a helpful tool to stay in touch."
button_icon_state = "hivemind_link"
chemical_cost = 0
dna_cost = 0
req_human = 1
max_genetic_damage = 100
/obj/effect/proc_holder/changeling/linglink/can_sting(mob/living/carbon/user)
/datum/action/changeling/linglink/can_sting(mob/living/carbon/user)
if(!..())
return
var/datum/changeling/changeling = user.mind.changeling
@@ -34,7 +36,7 @@
return
return changeling.can_absorb_dna(user,target)
/obj/effect/proc_holder/changeling/linglink/sting_action(mob/user)
/datum/action/changeling/linglink/sting_action(mob/user)
var/datum/changeling/changeling = user.mind.changeling
var/obj/item/grab/G = user.get_active_hand()
var/mob/living/carbon/target = G.affecting
@@ -1,14 +1,15 @@
/obj/effect/proc_holder/changeling/mimicvoice
/datum/action/changeling/mimicvoice
name = "Mimic Voice"
desc = "We shape our vocal glands to sound like a desired voice."
desc = "We shape our vocal glands to sound like a desired voice. Maintaining this power slows chemical production."
helptext = "Will turn your voice into the name that you enter. We must constantly expend chemicals to maintain our form like this."
button_icon_state = "mimic_voice"
chemical_cost = 0 //constant chemical drain hardcoded
dna_cost = 1
req_human = 1
// Fake Voice
/obj/effect/proc_holder/changeling/mimicvoice/sting_action(var/mob/user)
/datum/action/changeling/mimicvoice/sting_action(var/mob/user)
var/datum/changeling/changeling=user.mind.changeling
if(changeling.mimicing)
changeling.mimicing = ""
@@ -9,7 +9,7 @@
//Parent to shields and blades because muh copypasted code.
/obj/effect/proc_holder/changeling/weapon
/datum/action/changeling/weapon
name = "Organic Weapon"
desc = "Go tell a coder if you see this"
helptext = "Yell at coderbus"
@@ -21,7 +21,7 @@
var/weapon_type
var/weapon_name_simple
/obj/effect/proc_holder/changeling/weapon/try_to_sting(var/mob/user, var/mob/target)
/datum/action/changeling/weapon/try_to_sting(var/mob/user, var/mob/target)
if(istype(user.l_hand, weapon_type)) //Not the nicest way to do it, but eh
qdel(user.l_hand)
if(!silent)
@@ -36,7 +36,7 @@
return
..(user, target)
/obj/effect/proc_holder/changeling/weapon/sting_action(var/mob/user)
/datum/action/changeling/weapon/sting_action(var/mob/user)
if(!user.drop_item())
to_chat(user, "The [user.get_active_hand()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!")
return
@@ -45,7 +45,7 @@
return W
//Parent to space suits and armor.
/obj/effect/proc_holder/changeling/suit
/datum/action/changeling/suit
name = "Organic Suit"
desc = "Go tell a coder if you see this"
helptext = "Yell at coderbus"
@@ -60,7 +60,7 @@
var/recharge_slowdown = 0
var/blood_on_castoff = 0
/obj/effect/proc_holder/changeling/suit/try_to_sting(var/mob/user, var/mob/target)
/datum/action/changeling/suit/try_to_sting(var/mob/user, var/mob/target)
var/datum/changeling/changeling = user.mind.changeling
if(!ishuman(user) || !changeling)
return
@@ -84,7 +84,7 @@
return
..(H, target)
/obj/effect/proc_holder/changeling/suit/sting_action(var/mob/living/carbon/human/user)
/datum/action/changeling/suit/sting_action(var/mob/living/carbon/human/user)
if(!user.unEquip(user.wear_suit))
to_chat(user, "\the [user.wear_suit] is stuck to your body, you cannot grow a [suit_name_simple] over it!")
return
@@ -107,10 +107,11 @@
/***************************************\
|***************ARM BLADE***************|
\***************************************/
/obj/effect/proc_holder/changeling/weapon/arm_blade
/datum/action/changeling/weapon/arm_blade
name = "Arm Blade"
desc = "We reform one of our arms into a deadly blade."
helptext = "Cannot be used while in lesser form."
desc = "We reform one of our arms into a deadly blade. Costs 25 chemicals."
helptext = "We may retract our armblade in the same manner as we form it. Cannot be used while in lesser form."
button_icon_state = "armblade"
chemical_cost = 25
dna_cost = 2
genetic_damage = 10
@@ -168,12 +169,13 @@
|***********COMBAT TENTACLES*************|
\***************************************/
/obj/effect/proc_holder/changeling/weapon/tentacle
/datum/action/changeling/weapon/tentacle
name = "Tentacle"
desc = "We ready a tentacle to grab items or victims with."
desc = "We ready a tentacle to grab items or victims with. Costs 10 chemicals."
helptext = "We can use it once to retrieve a distant item. If used on living creatures, the effect depends on the intent: \
Help will simply drag them closer, Disarm will grab whatever they are holding instead of them, Grab will put the victim in our hold after catching it, \
and Harm will stun it, and stab it if we are also holding a sharp weapon. Cannot be used while in lesser form."
button_icon_state = "tentacle"
chemical_cost = 10
dna_cost = 2
genetic_damage = 5
@@ -341,10 +343,11 @@
/***************************************\
|****************SHIELD*****************|
\***************************************/
/obj/effect/proc_holder/changeling/weapon/shield
/datum/action/changeling/weapon/shield
name = "Organic Shield"
desc = "We reform one of our arms into a hard shield."
helptext = "Organic tissue cannot resist damage forever, the shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form."
desc = "We reform one of our arms into a hard shield. Costs 20 chemicals."
helptext = "Organic tissue cannot resist damage forever. The shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form."
button_icon_state = "organic_shield"
chemical_cost = 20
dna_cost = 1
genetic_damage = 12
@@ -354,7 +357,7 @@
weapon_type = /obj/item/shield/changeling
weapon_name_simple = "shield"
/obj/effect/proc_holder/changeling/weapon/shield/sting_action(var/mob/user)
/datum/action/changeling/weapon/shield/sting_action(var/mob/user)
var/datum/changeling/changeling = user.mind.changeling //So we can read the absorbedcount.
if(!changeling)
return
@@ -395,10 +398,11 @@
/***************************************\
|*********SPACE SUIT + HELMET***********|
\***************************************/
/obj/effect/proc_holder/changeling/suit/organic_space_suit
/datum/action/changeling/suit/organic_space_suit
name = "Organic Space Suit"
desc = "We grow an organic suit to protect ourselves from space exposure."
helptext = "We must constantly repair our form to make it space-proof, reducing chemical production while we are protected. Retreating the suit damages our genomes. Cannot be used in lesser form."
desc = "We grow an organic suit to protect ourselves from space exposure. Costs 20 chemicals."
helptext = "We must constantly repair our form to make it space proof, reducing chemical production while we are protected. Cannot be used in lesser form."
button_icon_state = "organic_suit"
chemical_cost = 20
dna_cost = 2
genetic_damage = 8
@@ -442,10 +446,11 @@
/***************************************\
|*****************ARMOR*****************|
\***************************************/
/obj/effect/proc_holder/changeling/suit/armor
/datum/action/changeling/suit/armor
name = "Chitinous Armor"
desc = "We turn our skin into tough chitin to protect us from damage."
helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Retreating the armor damages our genomes. Cannot be used in lesser form."
desc = "We turn our skin into tough chitin to protect us from damage. Costs 25 chemicals."
helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Cannot be used in lesser form."
button_icon_state = "chitinous_armor"
chemical_cost = 25
dna_cost = 2
genetic_damage = 11
@@ -1,13 +1,14 @@
/obj/effect/proc_holder/changeling/panacea
/datum/action/changeling/panacea
name = "Anatomic Panacea"
desc = "Expels impurifications from our form; curing diseases, removing parasites, sobering us, purging toxins and radiation, and resetting our genetic code completely."
desc = "Expels impurifications from our form, curing diseases, removing parasites, sobering us, purging toxins and radiation, and resetting our genetic code completely. Costs 20 chemicals."
helptext = "Can be used while unconscious."
button_icon_state = "panacea"
chemical_cost = 20
dna_cost = 1
req_stat = UNCONSCIOUS
//Heals the things that the other regenerative abilities don't.
/obj/effect/proc_holder/changeling/panacea/sting_action(var/mob/user)
/datum/action/changeling/panacea/sting_action(var/mob/user)
to_chat(user, "<span class='notice'>We cleanse impurities from our form.</span>")
@@ -1,11 +1,12 @@
/obj/effect/proc_holder/changeling/revive
/datum/action/changeling/revive
name = "Regenerate"
desc = "We regenerate, healing all damage from our form."
button_icon_state = "revive"
req_stat = DEAD
always_keep = 1
//Revive from regenerative stasis
/obj/effect/proc_holder/changeling/revive/sting_action(var/mob/living/carbon/user)
/datum/action/changeling/revive/sting_action(var/mob/living/carbon/user)
user.setToxLoss(0, FALSE)
user.setOxyLoss(0, FALSE)
user.setCloneLoss(0, FALSE)
@@ -62,7 +63,7 @@
user.regenerate_icons()
user.update_revive() //Handle waking up the changeling after the regenerative stasis has completed.
user.mind.changeling.purchasedpowers -= src
src.Remove(user)
user.med_hud_set_status()
user.med_hud_set_health()
feedback_add_details("changeling_powers","CR")
@@ -1,13 +1,14 @@
/obj/effect/proc_holder/changeling/resonant_shriek
/datum/action/changeling/resonant_shriek
name = "Resonant Shriek"
desc = "Our lungs and vocal chords shift, allowing us to briefly emit a noise that deafens and confuses the weak-minded."
helptext = "Emits a high-frequency sound that confuses and deafens humans, blows out nearby lights and overloads cyborg sensors."
desc = "Our lungs and vocal cords shift, allowing us to briefly emit a noise that deafens and confuses the weak minded. Costs 30 chemicals."
helptext = "Emits a high frequency sound that confuses and deafens humans, blows out nearby lights and overloads cyborg sensors."
button_icon_state = "resonant_shriek"
chemical_cost = 30
dna_cost = 1
req_human = 1
//A flashy ability, good for crowd control and sewing chaos.
/obj/effect/proc_holder/changeling/resonant_shriek/sting_action(var/mob/user)
//A flashy ability, good for crowd control and sowing chaos.
/datum/action/changeling/resonant_shriek/sting_action(var/mob/user)
for(var/mob/living/M in get_mobs_in_view(4, user))
if(iscarbon(M))
if(!M.mind || !M.mind.changeling)
@@ -28,14 +29,15 @@
feedback_add_details("changeling_powers","RS")
return 1
/obj/effect/proc_holder/changeling/dissonant_shriek
/datum/action/changeling/dissonant_shriek
name = "Dissonant Shriek"
desc = "We shift our vocal cords to release a high-frequency sound that overloads nearby electronics."
desc = "We shift our vocal cords to release a high frequency sound that overloads nearby electronics. Costs 30 chemicals."
button_icon_state = "dissonant_shriek"
chemical_cost = 30
dna_cost = 1
//A flashy ability, good for crowd control and sewing chaos.
/obj/effect/proc_holder/changeling/dissonant_shriek/sting_action(var/mob/user)
/datum/action/changeling/dissonant_shriek/sting_action(var/mob/user)
for(var/obj/machinery/light/L in range(5, usr))
L.on = 1
L.broken()
@@ -1,13 +1,14 @@
/obj/effect/proc_holder/changeling/spiders
/datum/action/changeling/spiders
name = "Spread Infestation"
desc = "Our form divides, creating arachnids which will grow into deadly beasts."
helptext = "The spiders are thoughtless creatures, and may attack their creators when fully grown. Requires at least 5 DNA absorptions."
button_icon_state = "spread_infestation"
chemical_cost = 45
dna_cost = 1
req_dna = 5
//Makes some spiderlings. Good for setting traps and causing general trouble.
/obj/effect/proc_holder/changeling/spiders/sting_action(var/mob/user)
/datum/action/changeling/spiders/sting_action(var/mob/user)
for(var/i=0, i<2, i++)
var/obj/structure/spider/spiderling/S = new(user.loc)
S.grow_as = /mob/living/simple_animal/hostile/poison/giant_spider/hunter
@@ -1,17 +1,18 @@
//Strained Muscles: Temporary speed boost at the cost of rapid damage
//Limited because of hardsuits and such; ideally, used for a quick getaway
/obj/effect/proc_holder/changeling/strained_muscles
/datum/action/changeling/strained_muscles
name = "Strained Muscles"
desc = "We evolve the ability to reduce the acid buildup in our muscles, allowing us to move much faster."
helptext = "The strain will make us tired, and we will rapidly become fatigued. Standard weight restrictions, like hardsuits, still apply. Cannot be used in lesser form."
button_icon_state = "strained_muscles"
chemical_cost = 0
dna_cost = 1
req_human = 1
var/stacks = 0 //Increments every 5 seconds; damage increases over time
var/enabled = 0 //Whether or not you are a hedgehog
/obj/effect/proc_holder/changeling/strained_muscles/sting_action(var/mob/living/carbon/user)
/datum/action/changeling/strained_muscles/sting_action(var/mob/living/carbon/user)
enabled = !enabled
if(enabled)
to_chat(user, "<span class='notice'>Our muscles tense and strengthen.</span>")
@@ -1,12 +1,13 @@
/obj/effect/proc_holder/changeling/swap_form
/datum/action/changeling/swap_form
name = "Swap Forms"
desc = "We force ourselves into the body of another form, pushing their consciousness into the form we left behind."
desc = "We force ourselves into the body of another form, pushing their consciousness into the form we left behind. Costs 40 chemicals."
helptext = "We will bring all our abilities with us, but we will lose our old form DNA in exchange for the new one. The process will seem suspicious to any observers."
button_icon_state = "mindswap"
chemical_cost = 40
dna_cost = 1
req_human = 1 //Monkeys can't grab
/obj/effect/proc_holder/changeling/swap_form/can_sting(var/mob/living/carbon/user)
/datum/action/changeling/swap_form/can_sting(var/mob/living/carbon/user)
if(!..())
return
var/obj/item/grab/G = user.get_active_hand()
@@ -22,8 +23,7 @@
return
return 1
/obj/effect/proc_holder/changeling/swap_form/sting_action(var/mob/living/carbon/user)
/datum/action/changeling/swap_form/sting_action(var/mob/living/carbon/user)
var/obj/item/grab/G = user.get_active_hand()
var/mob/living/carbon/human/target = G.affecting
var/datum/changeling/changeling = user.mind.changeling
@@ -38,6 +38,10 @@
to_chat(target, "<span class='userdanger'>[user] tightens [user.p_their()] grip as a painful sensation invades your body.</span>")
var/lingpowers = list()
for(var/power in changeling.purchasedpowers)
lingpowers += power
changeling.absorbed_dna -= changeling.find_dna(user.dna)
changeling.protected_dna -= changeling.find_dna(user.dna)
changeling.absorbedcount -= 1
@@ -55,6 +59,12 @@
user.Paralyse(2)
target.add_language("Changeling")
user.remove_language("Changeling")
user.regenerate_icons()
for(var/power in lingpowers)
var/datum/action/changeling/S = power
if(istype(S) && S.needs_button)
S.Grant(target)
to_chat(target, "<span class='warning'>Our genes cry out as we swap our [user] form for [target].</span>")
return 1
@@ -1,10 +1,10 @@
/obj/effect/proc_holder/changeling/sting
/datum/action/changeling/sting
name = "Tiny Prick"
desc = "Stabby stabby"
var/sting_icon = null
/obj/effect/proc_holder/changeling/sting/Click()
var/mob/user = usr
/datum/action/changeling/sting/Trigger()
var/mob/user = owner
if(!user || !user.mind || !user.mind.changeling)
return
if(!(user.mind.changeling.chosen_sting))
@@ -13,13 +13,13 @@
unset_sting(user)
return
/obj/effect/proc_holder/changeling/sting/proc/set_sting(var/mob/user)
/datum/action/changeling/sting/proc/set_sting(var/mob/user)
to_chat(user, "<span class='notice'>We prepare our sting, use alt+click or middle mouse button on target to sting them.</span>")
user.mind.changeling.chosen_sting = src
user.hud_used.lingstingdisplay.icon_state = sting_icon
user.hud_used.lingstingdisplay.invisibility = 0
/obj/effect/proc_holder/changeling/sting/proc/unset_sting(var/mob/user)
/datum/action/changeling/sting/proc/unset_sting(var/mob/user)
to_chat(user, "<span class='warning'>We retract our sting, we can't sting anyone for now.</span>")
user.mind.changeling.chosen_sting = null
user.hud_used.lingstingdisplay.icon_state = null
@@ -29,7 +29,7 @@
if(mind && mind.changeling && mind.changeling.chosen_sting)
mind.changeling.chosen_sting.unset_sting(src)
/obj/effect/proc_holder/changeling/sting/can_sting(var/mob/user, var/mob/target)
/datum/action/changeling/sting/can_sting(var/mob/user, var/mob/target)
if(!..())
return
if(!user.mind.changeling.chosen_sting)
@@ -51,7 +51,7 @@
return
return 1
/obj/effect/proc_holder/changeling/sting/sting_feedback(var/mob/user, var/mob/target)
/datum/action/changeling/sting/sting_feedback(var/mob/user, var/mob/target)
if(!target)
return
to_chat(user, "<span class='notice'>We stealthily sting [target.name].</span>")
@@ -60,18 +60,18 @@
add_attack_logs(user, target, "Unsuccessful sting (changeling)")
return 1
/obj/effect/proc_holder/changeling/sting/transformation
/datum/action/changeling/sting/transformation
name = "Transformation Sting"
desc = "We silently sting a human, injecting a retrovirus that forces them to transform."
desc = "We silently sting a human, injecting a retrovirus that forces them to transform. Costs 50 chemicals."
helptext = "The victim will transform much like a changeling would. The effects will be obvious to the victim, and the process will damage our genomes."
button_icon_state = "sting_transform"
sting_icon = "sting_transform"
chemical_cost = 50
dna_cost = 3
genetic_damage = 100
var/datum/dna/selected_dna = null
/obj/effect/proc_holder/changeling/sting/transformation/Click()
/datum/action/changeling/sting/transformation/Trigger()
var/mob/user = usr
var/datum/changeling/changeling = user.mind.changeling
if(changeling.chosen_sting)
@@ -85,7 +85,7 @@
return
..()
/obj/effect/proc_holder/changeling/sting/transformation/can_sting(var/mob/user, var/mob/target)
/datum/action/changeling/sting/transformation/can_sting(var/mob/user, var/mob/target)
if(!..())
return
if((HUSK in target.mutations) || (!ishuman(target)))
@@ -98,7 +98,7 @@
return FALSE
return TRUE
/obj/effect/proc_holder/changeling/sting/transformation/sting_action(var/mob/user, var/mob/target)
/datum/action/changeling/sting/transformation/sting_action(var/mob/user, var/mob/target)
add_attack_logs(user, target, "Transformation sting (changeling) (new identity is [selected_dna.real_name])")
if(issmall(target))
to_chat(user, "<span class='notice'>Our genes cry out as we sting [target.name]!</span>")
@@ -114,48 +114,51 @@
feedback_add_details("changeling_powers","TS")
return TRUE
obj/effect/proc_holder/changeling/sting/extract_dna
datum/action/changeling/sting/extract_dna
name = "Extract DNA Sting"
desc = "We stealthily sting a target and extract their DNA."
desc = "We stealthily sting a target and extract their DNA. Costs 25 chemicals."
helptext = "Will give you the DNA of your target, allowing you to transform into them."
button_icon_state = "sting_extract"
sting_icon = "sting_extract"
chemical_cost = 25
dna_cost = 0
/obj/effect/proc_holder/changeling/sting/extract_dna/can_sting(var/mob/user, var/mob/target)
/datum/action/changeling/sting/extract_dna/can_sting(var/mob/user, var/mob/target)
if(..())
return user.mind.changeling.can_absorb_dna(user, target)
/obj/effect/proc_holder/changeling/sting/extract_dna/sting_action(var/mob/user, var/mob/living/carbon/human/target)
/datum/action/changeling/sting/extract_dna/sting_action(var/mob/user, var/mob/living/carbon/human/target)
add_attack_logs(user, target, "Extraction sting (changeling)")
if(!(user.mind.changeling.has_dna(target.dna)))
user.mind.changeling.absorb_dna(target, user)
feedback_add_details("changeling_powers","ED")
return 1
obj/effect/proc_holder/changeling/sting/mute
datum/action/changeling/sting/mute
name = "Mute Sting"
desc = "We silently sting a human, completely silencing them for a short time."
desc = "We silently sting a human, completely silencing them for a short time. Costs 20 chemicals."
helptext = "Does not provide a warning to the victim that they have been stung, until they try to speak and cannot."
button_icon_state = "sting_mute"
sting_icon = "sting_mute"
chemical_cost = 20
dna_cost = 2
/obj/effect/proc_holder/changeling/sting/mute/sting_action(var/mob/user, var/mob/living/carbon/target)
/datum/action/changeling/sting/mute/sting_action(var/mob/user, var/mob/living/carbon/target)
add_attack_logs(user, target, "Mute sting (changeling)")
target.AdjustSilence(30)
feedback_add_details("changeling_powers","MS")
return 1
obj/effect/proc_holder/changeling/sting/blind
datum/action/changeling/sting/blind
name = "Blind Sting"
desc = "Temporarily blinds the target."
helptext = "This sting completely blinds a target for a short time."
desc = "We temporarily blind our victim. Costs 25 chemicals."
helptext = "This sting completely blinds a target for a short time, and leaves them with blurred vision for a long time."
button_icon_state = "sting_blind"
sting_icon = "sting_blind"
chemical_cost = 25
dna_cost = 1
/obj/effect/proc_holder/changeling/sting/blind/sting_action(var/mob/living/user, var/mob/living/target)
/datum/action/changeling/sting/blind/sting_action(var/mob/living/user, var/mob/living/target)
add_attack_logs(user, target, "Blind sting (changeling)")
to_chat(target, "<span class='danger'>Your eyes burn horrifically!</span>")
target.BecomeNearsighted()
@@ -164,15 +167,16 @@ obj/effect/proc_holder/changeling/sting/blind
feedback_add_details("changeling_powers","BS")
return 1
obj/effect/proc_holder/changeling/sting/LSD
datum/action/changeling/sting/LSD
name = "Hallucination Sting"
desc = "Causes terror in the target."
desc = "We cause mass terror to our victim. Costs 10 chemicals."
helptext = "We evolve the ability to sting a target with a powerful hallucinogenic chemical. The target does not notice they have been stung, and the effect occurs after 30 to 60 seconds."
button_icon_state = "sting_lsd"
sting_icon = "sting_lsd"
chemical_cost = 10
dna_cost = 1
/obj/effect/proc_holder/changeling/sting/LSD/sting_action(var/mob/user, var/mob/living/carbon/target)
/datum/action/changeling/sting/LSD/sting_action(var/mob/user, var/mob/living/carbon/target)
add_attack_logs(user, target, "LSD sting (changeling)")
spawn(rand(300,600))
if(target)
@@ -180,15 +184,16 @@ obj/effect/proc_holder/changeling/sting/LSD
feedback_add_details("changeling_powers","HS")
return 1
obj/effect/proc_holder/changeling/sting/cryo //Enable when mob cooling is fixed so that frostoil actually makes you cold, instead of mostly just hungry.
datum/action/changeling/sting/cryo //Enable when mob cooling is fixed so that frostoil actually makes you cold, instead of mostly just hungry.
name = "Cryogenic Sting"
desc = "We silently sting a human with a cocktail of chemicals that freeze them."
desc = "We silently sting our victim with a cocktail of chemicals that freezes them from the inside. Costs 15 chemicals."
helptext = "Does not provide a warning to the victim, though they will likely realize they are suddenly freezing."
button_icon_state = "sting_cryo"
sting_icon = "sting_cryo"
chemical_cost = 15
dna_cost = 2
/obj/effect/proc_holder/changeling/sting/cryo/sting_action(var/mob/user, var/mob/target)
/datum/action/changeling/sting/cryo/sting_action(var/mob/user, var/mob/target)
add_attack_logs(user, target, "Cryo sting (changeling)")
if(target.reagents)
target.reagents.add_reagent("frostoil", 30)
@@ -1,6 +1,7 @@
/obj/effect/proc_holder/changeling/transform
/datum/action/changeling/transform
name = "Transform"
desc = "We take on the appearance and voice of one we have absorbed."
desc = "We take on the appearance and voice of one we have absorbed. Costs 5 chemicals."
button_icon_state = "transform"
chemical_cost = 5
dna_cost = 0
req_dna = 1
@@ -8,7 +9,7 @@
max_genetic_damage = 3
//Change our DNA to that of somebody we've absorbed.
/obj/effect/proc_holder/changeling/transform/sting_action(var/mob/living/carbon/human/user)
/datum/action/changeling/transform/sting_action(var/mob/living/carbon/human/user)
var/datum/changeling/changeling = user.mind.changeling
var/datum/dna/chosen_dna = changeling.select_dna("Select the target DNA: ", "Target DNA")
@@ -156,6 +156,7 @@
user.SetWeakened(0)
user.SetStunned(0)
user.SetParalysis(0)
user.SetSleeping(0)
U.adjustStaminaLoss(-75)
to_chat(user, "<span class='notice'>You flush your system with clean blood and remove any incapacitating effects.</span>")
spawn(1)
+8
View File
@@ -595,3 +595,11 @@ Class Procs:
emp_act(EMP_LIGHT)
else
ex_act(EXPLODE_HEAVY)
/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8
var/md5 = md5(AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot.
for (var/i in 1 to 32)
. += hex2num(md5[i])
. = . % 9
AM.pixel_x = -8 + ((.%3)*8)
AM.pixel_y = -8 + (round( . / 3)*8)
@@ -14,7 +14,6 @@ var/global/list/image/splatter_cache = list()
icon = 'icons/effects/blood.dmi'
icon_state = "mfloor1"
random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7")
appearance_flags = NO_CLIENT_COLOR
blood_DNA = list()
var/base_icon = 'icons/effects/blood.dmi'
var/blood_state = BLOOD_STATE_HUMAN
@@ -155,7 +154,6 @@ var/global/list/image/splatter_cache = list()
layer = TURF_LAYER
random_icon_states = null
blood_DNA = list()
appearance_flags = NO_CLIENT_COLOR
var/list/existing_dirs = list()
/obj/effect/decal/cleanable/trail_holder/can_bloodcrawl_in()
+2
View File
@@ -4,6 +4,8 @@
gender = PLURAL
icon = 'icons/obj/items.dmi'
icon_state = "soap"
lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
w_class = WEIGHT_CLASS_TINY
throwforce = 0
throw_speed = 4
@@ -52,6 +52,7 @@
desc = "A backpack that opens into a localized pocket of Blue Space."
origin_tech = "bluespace=5;materials=4;engineering=4;plasmatech=5"
icon_state = "holdingpack"
item_state = "holdingpack"
max_w_class = WEIGHT_CLASS_HUGE
max_combined_w_class = 35
burn_state = FIRE_PROOF
@@ -62,6 +62,7 @@
/obj/item/storage/fancy/egg_box
icon_state = "eggbox"
icon_type = "egg"
item_state = "eggbox"
name = "egg box"
storage_slots = 12
can_hold = list(/obj/item/reagent_containers/food/snacks/egg)
+143
View File
@@ -88,7 +88,9 @@
//get message text, limit it's length.and clean/escape html
if(!msg)
set_typing(C, TRUE)
msg = input(src,"Message:", "Private message to [holder ? key_name(C, FALSE) : key_name_hidden(C, FALSE)]") as text|null
set_typing(C, FALSE)
if(!msg)
return
@@ -130,6 +132,9 @@
var/recieve_message = ""
pm_tracker.add_message(C, src, msg, mob)
C.pm_tracker.add_message(src, src, msg, C.mob)
if(holder && !C.holder)
recieve_message = "<span class='[recieve_span]' size='3'>-- Click the [recieve_pm_type]'s name to reply --</span>\n"
if(C.adminhelped)
@@ -233,3 +238,141 @@
continue
if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, X.mob))
to_chat(X, "<B><font color='blue'>PM: [key_name(src, TRUE, 0)]-&gt;IRC-Admins:</B> <span class='notice'>[msg]</span></font>")
/client/verb/open_pms_ui()
set name = "My PMs"
set category = "OOC"
pm_tracker.show_ui(usr)
/client/proc/set_typing(client/target, value)
if(!target)
return
var/datum/pm_convo/convo = target.pm_tracker.pms[key]
if(!convo)
return
convo.typing = value
if(target.pm_tracker.open && target.pm_tracker.current_title == key)
target.pm_tracker.show_ui(target.mob)
/datum/pm_tracker
var/current_title = ""
var/open = FALSE
var/list/pms = list()
var/show_archived = FALSE
var/window_id = "pms_window"
/datum/pm_convo
var/list/messages = list()
var/archived = FALSE
var/client/client
var/read = FALSE
var/typing = FALSE
/datum/pm_convo/New(client/C)
client = C
/datum/pm_convo/proc/add(client/sender, message)
messages.Add("[sender]: [message]")
archived = FALSE
read = FALSE
/datum/pm_tracker/proc/add_message(client/title, client/sender, message, mob/user)
if(!pms[title.key])
pms[title.key] = new /datum/pm_convo(title)
pms[title.key].add(sender, message)
if(!open)
// The next time the window's opened, it'll be open to the most recent message
current_title = title.key
return
// If it's already opened, it'll refresh
show_ui(user)
/datum/pm_tracker/proc/show_ui(mob/user)
var/dat = ""
dat += "<a href='?src=[UID()];refresh=1'>Refresh</a>"
dat += "<a href='?src=[UID()];showarchived=1'>[show_archived ? "Hide" : "Show"] Archived</a>"
dat += "<br>"
for(var/title in pms)
if(pms[title].archived && !show_archived)
continue
var/label = "[title]"
var/class = ""
if(title == current_title)
label = "<b>[label]</b>"
class = "linkOn"
else if(!pms[title].read)
label = "<i>*[label]</i>"
dat += "<a class='[class]' href='?src=[UID()];newtitle=[title]'>[label]</a>"
var/datum/pm_convo/convo = pms[current_title]
if(convo)
convo.read = TRUE
dat += "<h2>[check_rights(R_ADMIN, FALSE, user) ? fancy_title(current_title) : current_title]</h2>"
dat += "<h4>"
dat += "<table style='width:950px; border: 3px solid;'>"
for(var/message in convo.messages)
dat += "<tr><td>[message]</td></tr>"
dat += "</table>"
if(convo.typing)
dat += "<i><span class='typing'>[current_title] is typing</span></i>"
dat += "<br>"
dat += "</h4>"
dat += "<a href='?src=[UID()];reply=[current_title]'>Reply</a>"
dat += "<a href='?src=[UID()];archive=[current_title]'>[convo.archived ? "Unarchive" : "Archive"]</a>"
if(check_rights(R_ADMIN, FALSE, user))
dat += "<a href='?src=[UID()];ping=[current_title]'>Ping</a>"
var/datum/browser/popup = new(user, window_id, "Messages", 1000, 600, src)
popup.set_content(dat)
popup.open()
open = TRUE
/datum/pm_tracker/proc/fancy_title(title)
var/client/C = pms[title].client
if(!C)
return "[title] (Disconnected)"
return "[key_name(C, FALSE)] ([ADMIN_QUE(C.mob,"?")]) ([ADMIN_PP(C.mob,"PP")]) ([ADMIN_VV(C.mob,"VV")]) ([ADMIN_SM(C.mob,"SM")]) ([admin_jump_link(C.mob)]) (<A HREF='?_src_=holder;check_antagonist=1'>CA</A>)"
/datum/pm_tracker/Topic(href, href_list)
if(href_list["archive"])
pms[href_list["archive"]].archived = !pms[href_list["archive"]].archived
show_ui(usr)
return
if(href_list["refresh"])
show_ui(usr)
return
if(href_list["newtitle"])
current_title = href_list["newtitle"]
show_ui(usr)
return
if(href_list["ping"])
var/client/C = pms[href_list["ping"]].client
if(C)
C.pm_tracker.current_title = usr.key
window_flash(C)
C.pm_tracker.show_ui(C.mob)
to_chat(usr, "<span class='notice'>Forced open [C]'s messages window.</span>")
show_ui(usr)
return
if(href_list["reply"])
usr.client.cmd_admin_pm(ckey(href_list["reply"]), null)
show_ui(usr)
return
if(href_list["showarchived"])
show_archived = !show_archived
show_ui(usr)
return
if(href_list["close"])
open = FALSE
return
@@ -177,6 +177,11 @@ client/proc/one_click_antag()
H = pick(candidates)
SSticker.mode.add_cultist(H.mind)
candidates.Remove(H)
if(!summon_spots.len)
while(summon_spots.len < SUMMON_POSSIBILITIES)
var/area/summon = pick(return_sorted_areas() - summon_spots)
if(summon && is_station_level(summon.z) && summon.valid_territory)
summon_spots += summon
return 1
return 0
+1
View File
@@ -7,6 +7,7 @@
var/last_message = "" //contains the last message sent by this client - used to protect against copy-paste spamming.
var/last_message_count = 0 //contains a number of how many times a message identical to last_message was sent.
var/last_message_time = 0 //holds the last time (based on world.time) a message was sent
var/datum/pm_tracker/pm_tracker = new()
/////////
//OTHER//
+2 -2
View File
@@ -688,8 +688,8 @@
message += " (RESTRICTED)"
to_chat(world, "[message]")
/client/proc/colour_transition(var/list/colour_to = null, var/time = 10) //Call this with no parameters to reset to default.
animate(src, color=colour_to, time=time, easing=SINE_EASING)
/client/proc/colour_transition(list/colour_to = null, time = 10) //Call this with no parameters to reset to default.
animate(src, color = colour_to, time = time, easing = SINE_EASING)
/client/proc/on_varedit()
var_edited = TRUE
+4 -4
View File
@@ -256,16 +256,16 @@
desc = "Somehow these seem even more out-of-date than normal sunglasses."
actions_types = list(/datum/action/item_action/noir)
/obj/item/clothing/glasses/sunglasses/noir/attack_self()
toggle_noir()
/obj/item/clothing/glasses/sunglasses/noir/attack_self(mob/user)
toggle_noir(user)
/obj/item/clothing/glasses/sunglasses/noir/item_action_slot_check(slot)
if(slot == slot_glasses)
return 1
/obj/item/clothing/glasses/sunglasses/noir/proc/toggle_noir()
/obj/item/clothing/glasses/sunglasses/noir/proc/toggle_noir(mob/user)
color_view = color_view ? null : MATRIX_GREYSCALE //Toggles between null and grayscale, with null being the default option.
usr.update_client_colour()
user.update_client_colour()
/obj/item/clothing/glasses/sunglasses/yeah
name = "agreeable glasses"
+1
View File
@@ -213,6 +213,7 @@
name = "security gas mask"
desc = "A standard issue Security gas mask with integrated 'Compli-o-nator 3000' device, plays over a dozen pre-recorded compliance phrases designed to get scumbags to stand still whilst you taze them. Do not tamper with the device."
icon_state = "sechailer"
item_state = "sechailer"
var/phrase = 1
var/aggressiveness = 1
var/safety = 1
@@ -409,6 +409,7 @@
for(var/obj/O in contents)
if(O.name == K)
O.forceMove(loc)
adjust_item_drop_location(O)
update_icon()
i--
if(i <= 0)
+15 -8
View File
@@ -207,19 +207,26 @@
/datum/action/innate/minedrone/toggle_meson_vision
name = "Toggle Meson Vision"
button_icon_state = "meson"
var/sight_flags = SEE_TURFS
var/lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
/datum/action/innate/minedrone/toggle_meson_vision/Activate()
var/mob/living/simple_animal/hostile/mining_drone/user = owner
if(user.sight & SEE_TURFS)
user.sight &= ~SEE_TURFS
user.lighting_alpha = initial(user.lighting_alpha)
var/mob/living/user = owner
var/is_active = user.sight & SEE_TURFS
if(is_active)
UnregisterSignal(user, COMSIG_MOB_UPDATE_SIGHT)
user.update_sight()
else
user.sight |= SEE_TURFS
user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
RegisterSignal(user, COMSIG_MOB_UPDATE_SIGHT, .proc/update_user_sight)
user.update_sight()
user.sync_lighting_plane_alpha()
to_chat(user, "<span class='notice'>You toggle your meson vision [!is_active ? "on" : "off"].</span>")
to_chat(user, "<span class='notice'>You toggle your meson vision [(user.sight & SEE_TURFS) ? "on" : "off"].</span>")
/datum/action/innate/minedrone/toggle_meson_vision/proc/update_user_sight(mob/living/user)
user.sight |= sight_flags
if(!isnull(lighting_alpha))
user.lighting_alpha = min(user.lighting_alpha, lighting_alpha)
/datum/action/innate/minedrone/toggle_mode
name = "Toggle Mode"
@@ -619,12 +619,14 @@
/datum/pai_software/flashlight/toggle(mob/living/silicon/pai/user)
var/atom/movable/actual_location = istype(user.loc, /obj/item/paicard) ? user.loc : user
if(user.flashlight_on)
if(!user.flashlight_on)
actual_location.set_light(2)
user.card.set_light(2)
return
actual_location.set_light(2)
user.card.set_light(0)
else
actual_location.set_light(0)
user.card.set_light(0)
user.flashlight_on = !user.flashlight_on
/datum/pai_software/flashlight/is_active(mob/living/silicon/pai/user)
return user.flashlight_on
@@ -59,9 +59,6 @@
return
target.attack_animal(src)
/obj/item/organ/internal/body_egg/changeling_egg
name = "changeling egg"
desc = "Twitching and disgusting."
@@ -91,7 +88,12 @@
if(origin.changeling.can_absorb_dna(M, owner))
origin.changeling.absorb_dna(owner, M)
origin.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null)
var/datum/action/changeling/humanform/HF = new
HF.Grant(M)
for(var/power in origin.changeling.purchasedpowers)
var/datum/action/changeling/S = power
if(istype(S) && S.needs_button)
S.Grant(M)
M.key = origin.key
owner.gib()
-10
View File
@@ -956,9 +956,6 @@ var/list/slot_equipment_priority = list( \
statpanel("Status") // We only want alt-clicked turfs to come before Status
if(mind && mind.changeling)
add_stings_to_statpanel(mind.changeling.purchasedpowers)
if(mob_spell_list && mob_spell_list.len)
for(var/obj/effect/proc_holder/spell/S in mob_spell_list)
add_spell_to_statpanel(S)
@@ -1025,12 +1022,6 @@ var/list/slot_equipment_priority = list( \
statpanel_things += A
statpanel(listed_turf.name, null, statpanel_things)
/mob/proc/add_stings_to_statpanel(var/list/stings)
for(var/obj/effect/proc_holder/changeling/S in stings)
if(S.chemical_cost >=0 && S.can_be_used_by(src))
statpanel("[S.panel]",((S.chemical_cost > 0) ? "[S.chemical_cost]" : ""),S)
/mob/proc/add_spell_to_statpanel(var/obj/effect/proc_holder/spell/S)
switch(S.charge_type)
if("recharge")
@@ -1040,7 +1031,6 @@ var/list/slot_equipment_priority = list( \
if("holdervar")
statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S)
// facing verbs
/mob/proc/canface()
if(!canmove) return 0
+1 -11
View File
@@ -10,7 +10,6 @@
var/giftwrapped = 0
var/sortTag = 0
/obj/structure/bigDelivery/attack_hand(mob/user as mob)
playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1)
if(wrapped)
@@ -24,7 +23,6 @@
qdel(src)
/obj/structure/bigDelivery/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/destTagger))
var/obj/item/destTagger/O = W
@@ -67,17 +65,16 @@
else
to_chat(user, "<span class='notice'>You need more paper.</span>")
/obj/item/smallDelivery
name = "small parcel"
desc = "A small wrapped package."
icon = 'icons/obj/storage.dmi'
icon_state = "deliverycrateSmall"
item_state = "deliverypackage"
var/obj/item/wrapped = null
var/giftwrapped = 0
var/sortTag = 0
/obj/item/smallDelivery/attack_self(mob/user as mob)
if(wrapped && wrapped.loc) //sometimes items can disappear. For example, bombs. --rastaf0
wrapped.loc = user.loc
@@ -88,7 +85,6 @@
playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1)
qdel(src)
/obj/item/smallDelivery/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/destTagger))
var/obj/item/destTagger/O = W
@@ -128,8 +124,6 @@
else
to_chat(user, "<span class='notice'>You need more paper.</span>")
/obj/item/stack/packageWrap
name = "package wrapper"
icon = 'icons/obj/items.dmi'
@@ -140,7 +134,6 @@
max_amount = 25
burn_state = FLAMMABLE
/obj/item/stack/packageWrap/afterattack(var/obj/target as obj, mob/user as mob, proximity)
if(!proximity) return
if(!istype(target)) //this really shouldn't be necessary (but it is). -Pete
@@ -153,8 +146,6 @@
if(target in user)
return
if(istype(target, /obj/item) && !(istype(target, /obj/item/storage) && !istype(target,/obj/item/storage/box) && !istype(target, /obj/item/shippingPackage)))
var/obj/item/O = target
if(use(1))
@@ -364,7 +355,6 @@
to_chat(user, "You need more welding fuel to complete this task.")
return
/obj/item/shippingPackage
name = "Shipping package"
desc = "A pre-labeled package for shipping an item to coworkers."
+73 -88
View File
@@ -55,13 +55,9 @@ var/ert_request_answered = FALSE
to_chat(src, "<span class='boldnotice'>Upon using the antagHUD you forfeited the ability to join the round.</span>")
return 0
if(response_team_members.len > 6)
to_chat(src, "<span class='warning'>The emergency response team is already full!</span>")
return 0
return 1
/proc/trigger_armed_response_team(var/datum/response_team/response_team_type, commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots)
/proc/trigger_armed_response_team(datum/response_team/response_team_type, commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots)
response_team_members = list()
active_team = response_team_type
active_team.setSlots(commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots)
@@ -71,7 +67,7 @@ var/ert_request_answered = FALSE
if(!ert_candidates.len)
active_team.cannot_send_team()
send_emergency_team = FALSE
return 0
return
// Respawnable players get first dibs
for(var/mob/dead/observer/M in ert_candidates)
@@ -87,38 +83,58 @@ var/ert_request_answered = FALSE
if(!response_team_members.len)
active_team.cannot_send_team()
send_emergency_team = FALSE
return 0
return
var/index = 1
var/list/ert_gender_prefs = list()
for(var/mob/M in response_team_members)
if(index > emergencyresponseteamspawn.len)
index = 1
ert_gender_prefs.Add(input_async(M, "Please select a gender (10 seconds):", list("Male", "Female")))
addtimer(CALLBACK(GLOBAL_PROC, .proc/get_ert_role_prefs, response_team_members, ert_gender_prefs), 100)
/proc/get_ert_role_prefs(list/response_team_members, list/ert_gender_prefs)
var/list/ert_role_prefs = list()
for(var/datum/async_input/A in ert_gender_prefs)
A.close()
for(var/mob/M in response_team_members)
ert_role_prefs.Add(input_ranked_async(M, "Please order ERT roles from most to least preferred (15 seconds):", active_team.get_slot_list()))
addtimer(CALLBACK(GLOBAL_PROC, .proc/dispatch_response_team, response_team_members, ert_gender_prefs, ert_role_prefs), 150)
/proc/dispatch_response_team(list/response_team_members, list/ert_gender_prefs, list/ert_role_prefs)
var/spawn_index = 1
for(var/i = 1, i <= response_team_members.len, i++)
if(spawn_index > emergencyresponseteamspawn.len)
break
if(!active_team.get_slot_list().len)
break
var/gender_pref = ert_gender_prefs[i].result
var/role_pref = ert_role_prefs[i].close()
var/mob/M = response_team_members[i]
if(!M || !M.client)
continue
log_debug("Spawning as ERT: [M.ckey] ([M])")
var/client/C = M.client
var/mob/living/new_commando = C.create_response_team(emergencyresponseteamspawn[index])
if(!M || !new_commando)
if(!gender_pref || !role_pref)
// Player was afk and did not select
continue
new_commando.mind.key = M.key
new_commando.key = M.key
new_commando.update_icons()
index++
for(var/role in role_pref)
if(active_team.check_slot_available(role))
var/mob/living/new_commando = M.client.create_response_team(gender_pref, role, emergencyresponseteamspawn[spawn_index])
active_team.reduceSlots(role)
spawn_index++
if(!M || !new_commando)
break
new_commando.mind.key = M.key
new_commando.key = M.key
new_commando.update_icons()
break
send_emergency_team = FALSE
active_team.announce_team()
return 1
/client/proc/create_response_team(var/turf/spawn_location)
var/class = 0
while(!class)
class = input(src, "Which loadout would you like to choose?") in active_team.get_slot_list()
if(!active_team.check_slot_available(class)) // Because the prompt does not update automatically when a slot gets filled.
class = 0
if(active_team.count)
active_team.announce_team()
return
// Everyone who said yes was afk
active_team.cannot_send_team()
if(class == "Cyborg")
active_team.reduceCyborgSlots()
/client/proc/create_response_team(new_gender, role, turf/spawn_location)
if(role == "Cyborg")
var/cyborg_unlock = active_team.getCyborgUnlock()
var/mob/living/silicon/robot/ert/R = new /mob/living/silicon/robot/ert(spawn_location, cyborg_unlock)
return R
@@ -126,8 +142,6 @@ var/ert_request_answered = FALSE
var/mob/living/carbon/human/M = new(null)
var/obj/item/organ/external/head/head_organ = M.get_organ("head")
var/new_gender = alert(src, "Please select your gender.", "ERT Character Generation", "Male", "Female")
if(new_gender)
if(new_gender == "Male")
M.change_gender(MALE)
@@ -169,21 +183,24 @@ var/ert_request_answered = FALSE
SSticker.mode.ert += M.mind
M.forceMove(spawn_location)
SSjobs.CreateMoneyAccount(M, class, null)
SSjobs.CreateMoneyAccount(M, role, null)
active_team.equip_officer(class, M)
active_team.equip_officer(role, M)
return M
/datum/response_team
var/command_slots = 1
var/engineer_slots = 3
var/medical_slots = 3
var/security_slots = 3
var/janitor_slots = 0
var/paranormal_slots = 0
var/cyborg_slots = 0
var/list/slots = list(
Commander = 0,
Security = 0,
Engineer = 0,
Medic = 0,
Janitor = 0,
Paranormal = 0,
Cyborg = 0
)
var/count = 0
var/command_outfit
var/engineering_outfit
@@ -193,88 +210,56 @@ var/ert_request_answered = FALSE
var/paranormal_outfit
var/cyborg_unlock = 0
/datum/response_team/proc/setSlots(com, sec, med, eng, jan, par, cyb)
command_slots = com == null ? command_slots : com
security_slots = sec == null ? security_slots : sec
medical_slots = med == null ? medical_slots : med
engineer_slots = eng == null ? engineer_slots : eng
janitor_slots = jan == null ? janitor_slots : jan
paranormal_slots = par == null ? paranormal_slots : par
cyborg_slots = cyb == null ? cyborg_slots : cyb
/datum/response_team/proc/setSlots(com=1, sec=3, med=3, eng=3, jan=0, par=0, cyb=0)
slots["Commander"] = com
slots["Security"] = sec
slots["Medic"] = med
slots["Engineer"] = eng
slots["Janitor"] = jan
slots["Paranormal"] = par
slots["Cyborg"] = cyb
/datum/response_team/proc/reduceCyborgSlots()
cyborg_slots--
/datum/response_team/proc/reduceSlots(role)
slots[role]--
count++
/datum/response_team/proc/getCyborgUnlock()
return cyborg_unlock
/datum/response_team/proc/get_slot_list()
var/list/slots_available = list()
if(command_slots)
slots_available |= "Commander"
if(security_slots)
slots_available |= "Security"
if(engineer_slots)
slots_available |= "Engineer"
if(medical_slots)
slots_available |= "Medic"
if(janitor_slots)
slots_available |= "Janitor"
if(paranormal_slots)
slots_available |= "Paranormal"
if(cyborg_slots)
slots_available |= "Cyborg"
for(var/role in slots)
if(slots[role])
slots_available.Add(role)
return slots_available
/datum/response_team/proc/check_slot_available(var/slot)
switch(slot)
if("Commander")
return command_slots
if("Security")
return security_slots
if("Engineer")
return engineer_slots
if("Medic")
return medical_slots
if("Janitor")
return janitor_slots
if("Paranormal")
return paranormal_slots
if("Cyborg")
return cyborg_slots
return 0
/datum/response_team/proc/check_slot_available(role)
return slots[role]
/datum/response_team/proc/equip_officer(var/officer_type, var/mob/living/carbon/human/M)
switch(officer_type)
if("Engineer")
engineer_slots -= 1
M.equipOutfit(engineering_outfit)
M.job = "ERT Engineering"
if("Security")
security_slots -= 1
M.equipOutfit(security_outfit)
M.job = "ERT Security"
if("Medic")
medical_slots -= 1
M.equipOutfit(medical_outfit)
M.job = "ERT Medical"
if("Janitor")
janitor_slots -= 1
M.equipOutfit(janitor_outfit)
M.job = "ERT Janitor"
if("Paranormal")
paranormal_slots -= 1
M.equipOutfit(paranormal_outfit)
M.job = "ERT Paranormal"
M.mind.isholy = TRUE
if("Commander")
command_slots = 0
// Override name and age for the commander
M.rename_character(null, "[pick("Lieutenant", "Captain", "Major")] [pick(GLOB.last_names)]")
M.age = rand(35,45)
+19 -1
View File
@@ -345,4 +345,22 @@ div.notice
-ms-interpolation-mode: nearest-neighbor;
width: 64px;
height:64px;
}
}
.typing:after
{
overflow: hidden;
display: inline-block;
vertical-align: bottom;
animation: ellipsis steps(4,end) 900ms infinite;
content: "\2026";
width: 0px;
}
@keyframes ellipsis
{
to
{
width: 1.25em;
}
}
@@ -0,0 +1,4 @@
author: "EmanTheAlmighty"
delete-after: True
changes:
- tweak: "Admin made cultists can now properly summon their Gods if the gamemode wasn't initially Cult."
@@ -0,0 +1,6 @@
author: "Arkatos"
delete-after: True
changes:
- rscadd: "Changeling verbs replaced with action buttons"
- tweak: "Changeling ability descriptions updated"
- imageadd: "Added custom icons for changeling action buttons"
@@ -0,0 +1,4 @@
author: "Arkatos"
delete-after: True
changes:
- imageadd: "Added movement animation for mice, chickens and killer tomatoes"
@@ -0,0 +1,5 @@
author: "Couls"
delete-after: True
changes:
- rscadd: "Only names from the manifest will be used for syndicate code phrases"
- rscdel: "randomly generated people names from syndicate code phrases"
@@ -0,0 +1,8 @@
author: "Arkatos"
delete-after: True
changes:
- imageadd: "Added inhand sprite for eggbox"
- imageadd: "Added inhand sprites for all types of soaps"
- imageadd: "Added inhand sprite for small parcel"
- imageadd: "Added inhand sprite for sechailer"
- imageadd: "Added inhand sprite for bag of holding"
@@ -0,0 +1,4 @@
author: "Arkatos"
delete-after: True
changes:
- tweak: "Added new system for outputting contents of smartfridges"
@@ -0,0 +1,5 @@
author: "TDSSS"
delete-after: True
changes:
- tweak: "Vampire rejuv wakes you up if you're asleep now"
- tweak: "Cling epinephrine wakes you up if you're asleep now"
@@ -0,0 +1,4 @@
author: "Tayyyyyyy"
delete-after: True
changes:
- rscadd: "Messages window (My PMs in OOC tab)"
@@ -0,0 +1,4 @@
author: "Tayyyyyyy"
delete-after: True
changes:
- tweak: "You no longer have to wait on others for ERT spawning"
@@ -0,0 +1,5 @@
author: "Markolie"
delete-after: True
changes:
- bugfix: "Lighting now respects color blindness again."
- bugfix: "pAI flashlights now work properly."
Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 KiB

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 146 KiB

+1
View File
@@ -339,6 +339,7 @@
#include "code\datums\helper_datums\global_iterator.dm"
#include "code\datums\helper_datums\hotkey_modes.dm"
#include "code\datums\helper_datums\icon_snapshot.dm"
#include "code\datums\helper_datums\input.dm"
#include "code\datums\helper_datums\map_template.dm"
#include "code\datums\helper_datums\teleport.dm"
#include "code\datums\helper_datums\topic_input.dm"