Merge remote-tracking branch 'refs/remotes/Citadel-Station-13/master' into IHAVENOIDEAWHATTHEFUCKIMDOING
This commit is contained in:
@@ -29,13 +29,13 @@
|
||||
dat += "<I>Using this contract, you may summon an apprentice to aid you on your mission.</I><BR>"
|
||||
dat += "<I>If you are unable to establish contact with your apprentice, you can feed the contract back to the spellbook to refund your points.</I><BR>"
|
||||
dat += "<B>Which school of magic is your apprentice studying?:</B><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];school=[APPRENTICE_DESTRUCTION]'>Destruction</A><BR>"
|
||||
dat += "<A href='byond://?src=[REF(src)];school=[APPRENTICE_DESTRUCTION]'>Destruction</A><BR>"
|
||||
dat += "<I>Your apprentice is skilled in offensive magic. They know Magic Missile and Fireball.</I><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];school=[APPRENTICE_BLUESPACE]'>Bluespace Manipulation</A><BR>"
|
||||
dat += "<A href='byond://?src=[REF(src)];school=[APPRENTICE_BLUESPACE]'>Bluespace Manipulation</A><BR>"
|
||||
dat += "<I>Your apprentice is able to defy physics, melting through solid objects and travelling great distances in the blink of an eye. They know Teleport and Ethereal Jaunt.</I><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];school=[APPRENTICE_HEALING]'>Healing</A><BR>"
|
||||
dat += "<A href='byond://?src=[REF(src)];school=[APPRENTICE_HEALING]'>Healing</A><BR>"
|
||||
dat += "<I>Your apprentice is training to cast spells that will aid your survival. They know Forcewall and Charge and come with a Staff of Healing.</I><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];school=[APPRENTICE_ROBELESS]'>Robeless</A><BR>"
|
||||
dat += "<A href='byond://?src=[REF(src)];school=[APPRENTICE_ROBELESS]'>Robeless</A><BR>"
|
||||
dat += "<I>Your apprentice is training to cast spells without their robes. They know Knock and Mindswap.</I><BR>"
|
||||
user << browse(dat, "window=radio")
|
||||
onclose(user, "radio")
|
||||
|
||||
@@ -6,56 +6,47 @@
|
||||
var/door = 0
|
||||
var/grille = 0
|
||||
var/mach = 0
|
||||
var/num_territories = 1//Number of total valid territories for gang mode
|
||||
|
||||
/datum/station_state/proc/count()
|
||||
for(var/Z in GLOB.station_z_levels)
|
||||
for(var/turf/T in block(locate(1,1,Z), locate(world.maxx,world.maxy,Z)))
|
||||
// don't count shuttles since they may have just left
|
||||
if(istype(T.loc, /area/shuttle))
|
||||
continue
|
||||
|
||||
if(isfloorturf(T))
|
||||
var/turf/open/floor/TF = T
|
||||
if(!(TF.burnt))
|
||||
floor += 12
|
||||
else
|
||||
floor += 1
|
||||
|
||||
if(iswallturf(T))
|
||||
var/turf/closed/wall/TW = T
|
||||
if(TW.intact)
|
||||
wall += 2
|
||||
else
|
||||
wall += 1
|
||||
|
||||
if(istype(T, /turf/closed/wall/r_wall))
|
||||
var/turf/closed/wall/r_wall/TRW = T
|
||||
if(TRW.intact)
|
||||
r_wall += 2
|
||||
else
|
||||
r_wall += 1
|
||||
|
||||
|
||||
/datum/station_state/proc/count(count_territories)
|
||||
for(var/turf/T in block(locate(1,1,1), locate(world.maxx,world.maxy,1)))
|
||||
|
||||
if(isfloorturf(T))
|
||||
var/turf/open/floor/TF = T
|
||||
if(!(TF.burnt))
|
||||
src.floor += 12
|
||||
else
|
||||
src.floor += 1
|
||||
|
||||
if(iswallturf(T))
|
||||
var/turf/closed/wall/TW = T
|
||||
if(TW.intact)
|
||||
src.wall += 2
|
||||
else
|
||||
src.wall += 1
|
||||
|
||||
if(istype(T, /turf/closed/wall/r_wall))
|
||||
var/turf/closed/wall/r_wall/TRW = T
|
||||
if(TRW.intact)
|
||||
src.r_wall += 2
|
||||
else
|
||||
src.r_wall += 1
|
||||
|
||||
|
||||
for(var/obj/O in T.contents)
|
||||
if(istype(O, /obj/structure/window))
|
||||
src.window += 1
|
||||
else if(istype(O, /obj/structure/grille))
|
||||
var/obj/structure/grille/GR = O
|
||||
if(!GR.broken)
|
||||
src.grille += 1
|
||||
else if(istype(O, /obj/machinery/door))
|
||||
src.door += 1
|
||||
else if(ismachinery(O))
|
||||
src.mach += 1
|
||||
|
||||
if(count_territories)
|
||||
var/list/valid_territories = list()
|
||||
for(var/area/A in world) //First, collect all area types on the station zlevel
|
||||
if(A.z in GLOB.station_z_levels)
|
||||
if(!(A.type in valid_territories) && A.valid_territory)
|
||||
valid_territories |= A.type
|
||||
if(valid_territories.len)
|
||||
num_territories = valid_territories.len //Add them all up to make the total number of area types
|
||||
else
|
||||
to_chat(world, "ERROR: NO VALID TERRITORIES")
|
||||
for(var/obj/O in T.contents)
|
||||
if(istype(O, /obj/structure/window))
|
||||
window += 1
|
||||
else if(istype(O, /obj/structure/grille))
|
||||
var/obj/structure/grille/GR = O
|
||||
if(!GR.broken)
|
||||
grille += 1
|
||||
else if(istype(O, /obj/machinery/door))
|
||||
door += 1
|
||||
else if(ismachinery(O))
|
||||
mach += 1
|
||||
|
||||
/datum/station_state/proc/score(datum/station_state/result)
|
||||
if(!result)
|
||||
|
||||
@@ -226,6 +226,8 @@
|
||||
. = ..()
|
||||
if(!independent) //no pulling people deep into the blob
|
||||
verbs -= /mob/living/verb/pulled
|
||||
else
|
||||
pass_flags &= ~PASSBLOB
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobbernaut/Life()
|
||||
if(..())
|
||||
|
||||
@@ -79,12 +79,13 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
/mob/camera/blob/proc/victory()
|
||||
sound_to_playing_players('sound/machines/alarm.ogg')
|
||||
sleep(100)
|
||||
for(var/mob/living/L in GLOB.mob_list)
|
||||
for(var/i in GLOB.mob_living_list)
|
||||
var/mob/living/L = i
|
||||
var/turf/T = get_turf(L)
|
||||
if(!T || !(T.z in GLOB.station_z_levels))
|
||||
continue
|
||||
|
||||
if(L in GLOB.overminds || L.checkpass(PASSBLOB))
|
||||
if(L in GLOB.overminds || (L.pass_flags & PASSBLOB))
|
||||
continue
|
||||
|
||||
var/area/Ablob = get_area(T)
|
||||
@@ -92,9 +93,12 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
if(!Ablob.blob_allowed)
|
||||
continue
|
||||
|
||||
playsound(L, 'sound/effects/splat.ogg', 50, 1)
|
||||
L.death()
|
||||
new/mob/living/simple_animal/hostile/blob/blobspore(T)
|
||||
if(!("blob" in L.faction))
|
||||
playsound(L, 'sound/effects/splat.ogg', 50, 1)
|
||||
L.death()
|
||||
new/mob/living/simple_animal/hostile/blob/blobspore(T)
|
||||
else
|
||||
L.fully_heal()
|
||||
|
||||
for(var/V in GLOB.sortedAreas)
|
||||
var/area/A = V
|
||||
|
||||
@@ -154,33 +154,34 @@
|
||||
return
|
||||
if(!can_buy(40))
|
||||
return
|
||||
B.max_integrity = initial(B.max_integrity) * 0.25 //factories that produced a blobbernaut have much lower health
|
||||
B.obj_integrity = min(B.obj_integrity, B.max_integrity)
|
||||
B.update_icon()
|
||||
B.visible_message("<span class='warning'><b>The blobbernaut [pick("rips", "tears", "shreds")] its way out of the factory blob!</b></span>")
|
||||
playsound(B.loc, 'sound/effects/splat.ogg', 50, 1)
|
||||
var/mob/living/simple_animal/hostile/blob/blobbernaut/blobber = new /mob/living/simple_animal/hostile/blob/blobbernaut(get_turf(B))
|
||||
flick("blobbernaut_produce", blobber)
|
||||
B.naut = blobber
|
||||
blobber.factory = B
|
||||
blobber.overmind = src
|
||||
blobber.update_icons()
|
||||
blobber.notransform = 1 //stop the naut from moving around
|
||||
blobber.adjustHealth(blobber.maxHealth * 0.5)
|
||||
blob_mobs += blobber
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [blob_reagent_datum.name] blobbernaut?", ROLE_BLOB, null, ROLE_BLOB, 50, blobber) //players must answer rapidly
|
||||
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [blob_reagent_datum.name] blobbernaut?", ROLE_BLOB, null, ROLE_BLOB, 50) //players must answer rapidly
|
||||
if(candidates.len) //if we got at least one candidate, they're a blobbernaut now.
|
||||
B.max_integrity = initial(B.max_integrity) * 0.25 //factories that produced a blobbernaut have much lower health
|
||||
B.obj_integrity = min(B.obj_integrity, B.max_integrity)
|
||||
B.update_icon()
|
||||
B.visible_message("<span class='warning'><b>The blobbernaut [pick("rips", "tears", "shreds")] its way out of the factory blob!</b></span>")
|
||||
playsound(B.loc, 'sound/effects/splat.ogg', 50, 1)
|
||||
var/mob/living/simple_animal/hostile/blob/blobbernaut/blobber = new /mob/living/simple_animal/hostile/blob/blobbernaut(get_turf(B))
|
||||
flick("blobbernaut_produce", blobber)
|
||||
B.naut = blobber
|
||||
blobber.factory = B
|
||||
blobber.overmind = src
|
||||
blobber.update_icons()
|
||||
blobber.adjustHealth(blobber.maxHealth * 0.5)
|
||||
blob_mobs += blobber
|
||||
var/client/C = pick(candidates)
|
||||
blobber.key = C.key
|
||||
SEND_SOUND(blobber, sound('sound/effects/blobattack.ogg'))
|
||||
SEND_SOUND(blobber, sound('sound/effects/attackblob.ogg'))
|
||||
to_chat(blobber, "<b>You are a blobbernaut!</b>")
|
||||
to_chat(blobber, "You are powerful, hard to kill, and slowly regenerate near nodes and cores, but will slowly die if not near the blob or if the factory that made you is killed.")
|
||||
to_chat(blobber, "You are powerful, hard to kill, and slowly regenerate near nodes and cores, <span class='cultlarge'>but will slowly die if not near the blob</span> or if the factory that made you is killed.")
|
||||
to_chat(blobber, "You can communicate with other blobbernauts and overminds via <b>:b</b>")
|
||||
to_chat(blobber, "Your overmind's blob reagent is: <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font>!")
|
||||
to_chat(blobber, "The <b><font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</b></font> reagent [blob_reagent_datum.shortdesc ? "[blob_reagent_datum.shortdesc]" : "[blob_reagent_datum.description]"]")
|
||||
if(blobber)
|
||||
blobber.notransform = 0
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You could not conjure a sentience for your blobbernaut. Your points have been refunded. Try again later.</span>")
|
||||
add_points(40)
|
||||
|
||||
/mob/camera/blob/verb/relocate_core()
|
||||
set category = "Blob"
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
return atmosblock
|
||||
|
||||
/obj/structure/blob/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover) && mover.checkpass(PASSBLOB))
|
||||
if(istype(mover) && (mover.pass_flags & PASSBLOB))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
. = 0
|
||||
if(ismovableatom(caller))
|
||||
var/atom/movable/mover = caller
|
||||
. = . || mover.checkpass(PASSBLOB)
|
||||
. = . || (mover.pass_flags & PASSBLOB)
|
||||
|
||||
/obj/structure/blob/update_icon() //Updates color based on overmind color if we have an overmind.
|
||||
if(overmind)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
/datum/cellular_emporium
|
||||
var/name = "cellular emporium"
|
||||
var/datum/changeling/changeling
|
||||
var/datum/antagonist/changeling/changeling
|
||||
|
||||
/datum/cellular_emporium/New(my_changeling)
|
||||
. = ..()
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
var/list/abilities = list()
|
||||
|
||||
for(var/path in subtypesof(/obj/effect/proc_holder/changeling))
|
||||
for(var/path in changeling.all_powers)
|
||||
var/obj/effect/proc_holder/changeling/ability = path
|
||||
|
||||
var/dna_cost = initial(ability.dna_cost)
|
||||
@@ -61,10 +61,10 @@
|
||||
switch(action)
|
||||
if("readapt")
|
||||
if(changeling.canrespec)
|
||||
changeling.lingRespec(usr)
|
||||
changeling.readapt()
|
||||
if("evolve")
|
||||
var/sting_name = params["name"]
|
||||
changeling.purchasePower(usr, sting_name)
|
||||
changeling.purchase_power(sting_name)
|
||||
|
||||
/datum/action/innate/cellular_emporium
|
||||
name = "Cellular Emporium"
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
#define LING_FAKEDEATH_TIME 400 //40 seconds
|
||||
#define LING_DEAD_GENETICDAMAGE_HEAL_CAP 50 //The lowest value of geneticdamage handle_changeling() can take it to while dead.
|
||||
#define LING_ABSORB_RECENT_SPEECH 8 //The amount of recent spoken lines to gain on absorbing a mob
|
||||
|
||||
GLOBAL_LIST_INIT(possible_changeling_IDs, list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega"))
|
||||
GLOBAL_LIST_INIT(slots, list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store"))
|
||||
GLOBAL_LIST_INIT(slot2slot, list("head" = slot_head, "wear_mask" = slot_wear_mask, "neck" = slot_neck, "back" = slot_back, "wear_suit" = slot_wear_suit, "w_uniform" = slot_w_uniform, "shoes" = slot_shoes, "belt" = slot_belt, "gloves" = slot_gloves, "glasses" = slot_glasses, "ears" = slot_ears, "wear_id" = slot_wear_id, "s_store" = slot_s_store))
|
||||
GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "wear_mask" = /obj/item/clothing/mask/changeling, "back" = /obj/item/changeling, "wear_suit" = /obj/item/clothing/suit/changeling, "w_uniform" = /obj/item/clothing/under/changeling, "shoes" = /obj/item/clothing/shoes/changeling, "belt" = /obj/item/changeling, "gloves" = /obj/item/clothing/gloves/changeling, "glasses" = /obj/item/clothing/glasses/changeling, "ears" = /obj/item/changeling, "wear_id" = /obj/item/changeling, "s_store" = /obj/item/changeling))
|
||||
|
||||
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/changelings = list()
|
||||
GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our this objective to all lings
|
||||
|
||||
|
||||
/datum/game_mode/changeling
|
||||
@@ -29,26 +22,8 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
|
||||
<span class='green'>Changelings</span>: Accomplish the objectives assigned to you.\n\
|
||||
<span class='notice'>Crew</span>: Root out and eliminate the changeling menace."
|
||||
|
||||
var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time
|
||||
var/const/prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target
|
||||
var/const/prob_right_murder_target_h = 50 // upper bound on probability of naimg the right assassination target
|
||||
|
||||
var/const/prob_int_item = 50 // intercept names the theft target half the time
|
||||
var/const/prob_right_item_l = 25 // lower bound on probability of naming right theft target
|
||||
var/const/prob_right_item_h = 50 // upper bound on probability of naming the right theft target
|
||||
|
||||
var/const/prob_int_sab_target = 50 // intercept names the sabotage target half the time
|
||||
var/const/prob_right_sab_target_l = 25 // lower bound on probability of naming right sabotage target
|
||||
var/const/prob_right_sab_target_h = 50 // upper bound on probability of naming right sabotage target
|
||||
|
||||
var/const/prob_right_killer_l = 25 //lower bound on probability of naming the right operative
|
||||
var/const/prob_right_killer_h = 50 //upper bound on probability of naming the right operative
|
||||
var/const/prob_right_objective_l = 25 //lower bound on probability of determining the objective correctly
|
||||
var/const/prob_right_objective_h = 50 //upper bound on probability of determining the objective correctly
|
||||
|
||||
var/const/changeling_amount = 4 //hard limit on changelings if scaling is turned off
|
||||
|
||||
var/changeling_team_objective_type = null //If this is not null, we hand our this objective to all lings
|
||||
var/list/changelings = list()
|
||||
|
||||
/datum/game_mode/changeling/pre_setup()
|
||||
|
||||
@@ -80,7 +55,6 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
|
||||
return 0
|
||||
|
||||
/datum/game_mode/changeling/post_setup()
|
||||
|
||||
//Decide if it's ok for the lings to have a team objective
|
||||
//And then set it up to be handed out in forge_changeling_objectives
|
||||
var/list/team_objectives = subtypesof(/datum/objective/changeling_team_objective)
|
||||
@@ -92,116 +66,27 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
|
||||
possible_team_objectives += T
|
||||
|
||||
if(possible_team_objectives.len && prob(20*changelings.len))
|
||||
changeling_team_objective_type = pick(possible_team_objectives)
|
||||
GLOB.changeling_team_objective_type = pick(possible_team_objectives)
|
||||
|
||||
for(var/datum/mind/changeling in changelings)
|
||||
log_game("[changeling.key] (ckey) has been selected as a changeling")
|
||||
changeling.current.make_changeling()
|
||||
forge_changeling_objectives(changeling)
|
||||
greet_changeling(changeling)
|
||||
SSticker.mode.update_changeling_icons_added(changeling)
|
||||
var/datum/antagonist/changeling/new_antag = new(changeling)
|
||||
new_antag.team_mode = TRUE
|
||||
changeling.add_antag_datum(new_antag)
|
||||
..()
|
||||
|
||||
/datum/game_mode/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
var/changelingcap = min(round(GLOB.joined_player_list.len / (csc * 2)) + 2, round(GLOB.joined_player_list.len / csc))
|
||||
if(SSticker.mode.changelings.len >= changelingcap) //Caps number of latejoin antagonists
|
||||
if(changelings.len >= changelingcap) //Caps number of latejoin antagonists
|
||||
return
|
||||
if(SSticker.mode.changelings.len <= (changelingcap - 2) || prob(100 - (csc * 2)))
|
||||
if(changelings.len <= (changelingcap - 2) || prob(100 - (csc * 2)))
|
||||
if(ROLE_CHANGELING in character.client.prefs.be_special)
|
||||
if(!jobban_isbanned(character, ROLE_CHANGELING) && !jobban_isbanned(character, "Syndicate"))
|
||||
if(age_check(character.client))
|
||||
if(!(character.job in restricted_jobs))
|
||||
character.mind.make_Changling()
|
||||
|
||||
/datum/game_mode/proc/forge_changeling_objectives(datum/mind/changeling, var/team_mode = 0)
|
||||
//OBJECTIVES - random traitor objectives. Unique objectives "steal brain" and "identity theft".
|
||||
//No escape alone because changelings aren't suited for it and it'd probably just lead to rampant robusting
|
||||
//If it seems like they'd be able to do it in play, add a 10% chance to have to escape alone
|
||||
|
||||
var/escape_objective_possible = TRUE
|
||||
|
||||
//if there's a team objective, check if it's compatible with escape objectives
|
||||
for(var/datum/objective/changeling_team_objective/CTO in changeling.objectives)
|
||||
if(!CTO.escape_objective_compatible)
|
||||
escape_objective_possible = FALSE
|
||||
break
|
||||
|
||||
var/datum/objective/absorb/absorb_objective = new
|
||||
absorb_objective.owner = changeling
|
||||
absorb_objective.gen_amount_goal(6, 8)
|
||||
changeling.objectives += absorb_objective
|
||||
|
||||
if(prob(60))
|
||||
if(prob(85))
|
||||
var/datum/objective/steal/steal_objective = new
|
||||
steal_objective.owner = changeling
|
||||
steal_objective.find_target()
|
||||
changeling.objectives += steal_objective
|
||||
else
|
||||
var/datum/objective/download/download_objective = new
|
||||
download_objective.owner = changeling
|
||||
download_objective.gen_amount_goal()
|
||||
changeling.objectives += download_objective
|
||||
|
||||
var/list/active_ais = active_ais()
|
||||
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
|
||||
var/datum/objective/destroy/destroy_objective = new
|
||||
destroy_objective.owner = changeling
|
||||
destroy_objective.find_target()
|
||||
changeling.objectives += destroy_objective
|
||||
else
|
||||
if(prob(70))
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
kill_objective.owner = changeling
|
||||
if(team_mode) //No backstabbing while in a team
|
||||
kill_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
|
||||
else
|
||||
kill_objective.find_target()
|
||||
changeling.objectives += kill_objective
|
||||
else
|
||||
var/datum/objective/maroon/maroon_objective = new
|
||||
maroon_objective.owner = changeling
|
||||
if(team_mode)
|
||||
maroon_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
|
||||
else
|
||||
maroon_objective.find_target()
|
||||
changeling.objectives += maroon_objective
|
||||
|
||||
if (!(locate(/datum/objective/escape) in changeling.objectives) && escape_objective_possible)
|
||||
var/datum/objective/escape/escape_with_identity/identity_theft = new
|
||||
identity_theft.owner = changeling
|
||||
identity_theft.target = maroon_objective.target
|
||||
identity_theft.update_explanation_text()
|
||||
changeling.objectives += identity_theft
|
||||
escape_objective_possible = FALSE
|
||||
|
||||
if (!(locate(/datum/objective/escape) in changeling.objectives) && escape_objective_possible)
|
||||
if(prob(50))
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = changeling
|
||||
changeling.objectives += escape_objective
|
||||
else
|
||||
var/datum/objective/escape/escape_with_identity/identity_theft = new
|
||||
identity_theft.owner = changeling
|
||||
if(team_mode)
|
||||
identity_theft.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
|
||||
else
|
||||
identity_theft.find_target()
|
||||
changeling.objectives += identity_theft
|
||||
escape_objective_possible = FALSE
|
||||
|
||||
|
||||
|
||||
/datum/game_mode/changeling/forge_changeling_objectives(datum/mind/changeling)
|
||||
if(changeling_team_objective_type)
|
||||
var/datum/objective/changeling_team_objective/team_objective = new changeling_team_objective_type
|
||||
team_objective.owner = changeling
|
||||
changeling.objectives += team_objective
|
||||
|
||||
..(changeling,1)
|
||||
else
|
||||
..(changeling,0)
|
||||
changelings += character.mind
|
||||
|
||||
/datum/game_mode/changeling/generate_report()
|
||||
return "The Gorlex Marauders have announced the successful raid and destruction of Central Command containment ship #S-[rand(1111, 9999)]. This ship housed only a single prisoner - \
|
||||
@@ -209,29 +94,12 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
|
||||
of the Thing being sent to a station in this sector is highly likely. It may be in the guise of any crew member. Trust nobody - suspect everybody. Do not announce this to the crew, \
|
||||
as paranoia may spread and inhibit workplace efficiency."
|
||||
|
||||
/datum/game_mode/proc/greet_changeling(datum/mind/changeling, you_are=1)
|
||||
if (you_are)
|
||||
to_chat(changeling.current, "<span class='boldannounce'>You are [changeling.changeling.changelingID], a changeling! You have absorbed and taken the form of a human.</span>")
|
||||
to_chat(changeling.current, "<span class='boldannounce'>Use say \":g message\" to communicate with your fellow changelings.</span>")
|
||||
to_chat(changeling.current, "<b>You must complete the following tasks:</b>")
|
||||
changeling.current.playsound_local(get_turf(changeling.current), 'sound/ambience/antag/ling_aler.ogg', 100, FALSE, pressure_affected = FALSE)
|
||||
|
||||
if (changeling.current.mind)
|
||||
var/mob/living/carbon/human/H = changeling.current
|
||||
if(H.mind.assigned_role == "Clown")
|
||||
to_chat(H, "You have evolved beyond your clownish nature, allowing you to wield weapons without harming yourself.")
|
||||
H.dna.remove_mutation(CLOWNMUT)
|
||||
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/objective in changeling.objectives)
|
||||
to_chat(changeling.current, "<b>Objective #[obj_count]</b>: [objective.explanation_text]")
|
||||
obj_count++
|
||||
return
|
||||
|
||||
/datum/game_mode/proc/auto_declare_completion_changeling()
|
||||
var/list/changelings = get_antagonists(/datum/antagonist/changeling,TRUE) //Only real lings get a mention
|
||||
if(changelings.len)
|
||||
var/text = "<br><font size=3><b>The changelings were:</b></font>"
|
||||
for(var/datum/mind/changeling in changelings)
|
||||
var/datum/antagonist/changeling/ling = changeling.has_antag_datum(/datum/antagonist/changeling)
|
||||
var/changelingwin = 1
|
||||
if(!changeling.current)
|
||||
changelingwin = 0
|
||||
@@ -239,8 +107,8 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
|
||||
text += printplayer(changeling)
|
||||
|
||||
//Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed.
|
||||
text += "<br><b>Changeling ID:</b> [changeling.changeling.changelingID]."
|
||||
text += "<br><b>Genomes Extracted:</b> [changeling.changeling.absorbedcount]"
|
||||
text += "<br><b>Changeling ID:</b> [ling.changelingID]."
|
||||
text += "<br><b>Genomes Extracted:</b> [ling.absorbedcount]"
|
||||
|
||||
if(changeling.objectives.len)
|
||||
var/count = 1
|
||||
@@ -265,176 +133,8 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
|
||||
|
||||
to_chat(world, text)
|
||||
|
||||
|
||||
return 1
|
||||
|
||||
/datum/changeling //stores changeling powers, changeling recharge thingie, changeling absorbed DNA and changeling ID (for changeling hivemind)
|
||||
var/list/stored_profiles = list() //list of datum/changelingprofile
|
||||
var/datum/changelingprofile/first_prof = null
|
||||
//var/list/absorbed_dna = list()
|
||||
//var/list/protected_dna = list() //dna that is not lost when capacity is otherwise full
|
||||
var/dna_max = 6 //How many extra DNA strands the changeling can store for transformation.
|
||||
var/absorbedcount = 0
|
||||
var/chem_charges = 20
|
||||
var/chem_storage = 75
|
||||
var/chem_recharge_rate = 1
|
||||
var/chem_recharge_slowdown = 0
|
||||
var/sting_range = 2
|
||||
var/changelingID = "Changeling"
|
||||
var/geneticdamage = 0
|
||||
var/isabsorbing = 0
|
||||
var/islinking = 0
|
||||
var/geneticpoints = 10
|
||||
var/purchasedpowers = list()
|
||||
var/mimicing = ""
|
||||
var/canrespec = 0
|
||||
var/changeling_speak = 0
|
||||
var/datum/dna/chosen_dna
|
||||
var/obj/effect/proc_holder/changeling/sting/chosen_sting
|
||||
var/datum/cellular_emporium/cellular_emporium
|
||||
var/datum/action/innate/cellular_emporium/emporium_action
|
||||
|
||||
/datum/changeling/New(var/gender=FEMALE)
|
||||
..()
|
||||
var/honorific
|
||||
if(gender == FEMALE)
|
||||
honorific = "Ms."
|
||||
else
|
||||
honorific = "Mr."
|
||||
if(GLOB.possible_changeling_IDs.len)
|
||||
changelingID = pick(GLOB.possible_changeling_IDs)
|
||||
GLOB.possible_changeling_IDs -= changelingID
|
||||
changelingID = "[honorific] [changelingID]"
|
||||
else
|
||||
changelingID = "[honorific] [rand(1,999)]"
|
||||
|
||||
cellular_emporium = new(src)
|
||||
emporium_action = new(cellular_emporium)
|
||||
|
||||
/datum/changeling/Destroy()
|
||||
qdel(cellular_emporium)
|
||||
cellular_emporium = null
|
||||
qdel(emporium_action)
|
||||
emporium_action = null
|
||||
. = ..()
|
||||
|
||||
/datum/changeling/proc/regenerate(var/mob/living/carbon/the_ling)
|
||||
if(istype(the_ling))
|
||||
emporium_action.Grant(the_ling)
|
||||
if(the_ling.stat == DEAD)
|
||||
chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), (chem_storage*0.5))
|
||||
geneticdamage = max(LING_DEAD_GENETICDAMAGE_HEAL_CAP,geneticdamage-1)
|
||||
else //not dead? no chem/geneticdamage caps.
|
||||
chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), chem_storage)
|
||||
geneticdamage = max(0, geneticdamage-1)
|
||||
|
||||
|
||||
/datum/changeling/proc/get_dna(dna_owner)
|
||||
for(var/datum/changelingprofile/prof in stored_profiles)
|
||||
if(dna_owner == prof.name)
|
||||
return prof
|
||||
|
||||
/datum/changeling/proc/has_dna(datum/dna/tDNA)
|
||||
for(var/datum/changelingprofile/prof in stored_profiles)
|
||||
if(tDNA.is_same_as(prof.dna))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/changeling/proc/can_absorb_dna(mob/living/carbon/user, mob/living/carbon/human/target, var/verbose=1)
|
||||
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)
|
||||
if(verbose)
|
||||
to_chat(user, "<span class='warning'>[target] is not compatible with our biology.</span>")
|
||||
return
|
||||
if((target.disabilities & NOCLONE) || (target.disabilities & HUSK))
|
||||
if(verbose)
|
||||
to_chat(user, "<span class='warning'>DNA of [target] is ruined beyond usability!</span>")
|
||||
return
|
||||
if(!ishuman(target))//Absorbing monkeys is entirely possible, but it can cause issues with transforming. That's what lesser form is for anyway!
|
||||
if(verbose)
|
||||
to_chat(user, "<span class='warning'>We could gain no benefit from absorbing a lesser creature.</span>")
|
||||
return
|
||||
if(has_dna(target.dna))
|
||||
if(verbose)
|
||||
to_chat(user, "<span class='warning'>We already have this DNA in storage!</span>")
|
||||
return
|
||||
if(!target.has_dna())
|
||||
if(verbose)
|
||||
to_chat(user, "<span class='warning'>[target] is not compatible with our biology.</span>")
|
||||
return
|
||||
return 1
|
||||
|
||||
/datum/changeling/proc/create_profile(mob/living/carbon/human/H, mob/living/carbon/human/user, protect = 0)
|
||||
var/datum/changelingprofile/prof = new
|
||||
|
||||
H.dna.real_name = H.real_name //Set this again, just to be sure that it's properly set.
|
||||
var/datum/dna/new_dna = new H.dna.type
|
||||
H.dna.copy_dna(new_dna)
|
||||
prof.dna = new_dna
|
||||
prof.name = H.real_name
|
||||
prof.protected = protect
|
||||
|
||||
prof.underwear = H.underwear
|
||||
prof.undershirt = H.undershirt
|
||||
prof.socks = H.socks
|
||||
|
||||
var/list/slots = list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store")
|
||||
for(var/slot in slots)
|
||||
if(slot in H.vars)
|
||||
var/obj/item/I = H.vars[slot]
|
||||
if(!I)
|
||||
continue
|
||||
prof.name_list[slot] = I.name
|
||||
prof.appearance_list[slot] = I.appearance
|
||||
prof.flags_cover_list[slot] = I.flags_cover
|
||||
prof.item_color_list[slot] = I.item_color
|
||||
prof.item_state_list[slot] = I.item_state
|
||||
prof.exists_list[slot] = 1
|
||||
else
|
||||
continue
|
||||
|
||||
return prof
|
||||
|
||||
/datum/changeling/proc/add_profile(datum/changelingprofile/prof)
|
||||
if(stored_profiles.len > dna_max)
|
||||
if(!push_out_profile())
|
||||
return
|
||||
|
||||
stored_profiles += prof
|
||||
absorbedcount++
|
||||
|
||||
/datum/changeling/proc/add_new_profile(mob/living/carbon/human/H, mob/living/carbon/human/user, protect = 0)
|
||||
var/datum/changelingprofile/prof = create_profile(H, protect)
|
||||
add_profile(prof)
|
||||
return prof
|
||||
|
||||
/datum/changeling/proc/remove_profile(mob/living/carbon/human/H, force = 0)
|
||||
for(var/datum/changelingprofile/prof in stored_profiles)
|
||||
if(H.real_name == prof.name)
|
||||
if(prof.protected && !force)
|
||||
continue
|
||||
stored_profiles -= prof
|
||||
qdel(prof)
|
||||
|
||||
/datum/changeling/proc/get_profile_to_remove()
|
||||
for(var/datum/changelingprofile/prof in stored_profiles)
|
||||
if(!prof.protected)
|
||||
return prof
|
||||
|
||||
/datum/changeling/proc/push_out_profile()
|
||||
var/datum/changelingprofile/removeprofile = get_profile_to_remove()
|
||||
if(removeprofile)
|
||||
stored_profiles -= removeprofile
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/changeling_transform(mob/living/carbon/human/user, datum/changelingprofile/chosen_prof)
|
||||
var/datum/dna/chosen_dna = chosen_prof.dna
|
||||
user.real_name = chosen_prof.name
|
||||
@@ -474,50 +174,4 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
|
||||
if(equip)
|
||||
user.equip_to_slot_or_del(C, GLOB.slot2slot[slot])
|
||||
|
||||
user.regenerate_icons()
|
||||
|
||||
/datum/changelingprofile
|
||||
var/name = "a bug"
|
||||
|
||||
var/protected = 0
|
||||
|
||||
var/datum/dna/dna = null
|
||||
var/list/name_list = list() //associative list of slotname = itemname
|
||||
var/list/appearance_list = list()
|
||||
var/list/flags_cover_list = list()
|
||||
var/list/exists_list = list()
|
||||
var/list/item_color_list = list()
|
||||
var/list/item_state_list = list()
|
||||
|
||||
var/underwear
|
||||
var/undershirt
|
||||
var/socks
|
||||
|
||||
/datum/changelingprofile/Destroy()
|
||||
qdel(dna)
|
||||
. = ..()
|
||||
|
||||
/datum/changelingprofile/proc/copy_profile(datum/changelingprofile/newprofile)
|
||||
newprofile.name = name
|
||||
newprofile.protected = protected
|
||||
newprofile.dna = new dna.type
|
||||
dna.copy_dna(newprofile.dna)
|
||||
newprofile.name_list = name_list.Copy()
|
||||
newprofile.appearance_list = appearance_list.Copy()
|
||||
newprofile.flags_cover_list = flags_cover_list.Copy()
|
||||
newprofile.exists_list = exists_list.Copy()
|
||||
newprofile.item_color_list = item_color_list.Copy()
|
||||
newprofile.item_state_list = item_state_list.Copy()
|
||||
newprofile.underwear = underwear
|
||||
newprofile.undershirt = undershirt
|
||||
newprofile.socks = socks
|
||||
|
||||
/datum/game_mode/proc/update_changeling_icons_added(datum/mind/changling_mind)
|
||||
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_CHANGELING]
|
||||
hud.join_hud(changling_mind.current)
|
||||
set_antag_hud(changling_mind.current, "changling")
|
||||
|
||||
/datum/game_mode/proc/update_changeling_icons_removed(datum/mind/changling_mind)
|
||||
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_CHANGELING]
|
||||
hud.leave_hud(changling_mind.current)
|
||||
set_antag_hud(changling_mind.current, null)
|
||||
user.regenerate_icons()
|
||||
@@ -26,14 +26,14 @@
|
||||
|
||||
/obj/effect/proc_holder/changeling/Click()
|
||||
var/mob/user = usr
|
||||
if(!user || !user.mind || !user.mind.changeling)
|
||||
if(!user || !user.mind || !user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
return
|
||||
try_to_sting(user)
|
||||
|
||||
/obj/effect/proc_holder/changeling/proc/try_to_sting(mob/user, mob/target)
|
||||
if(!can_sting(user, target))
|
||||
return
|
||||
var/datum/changeling/c = user.mind.changeling
|
||||
var/datum/antagonist/changeling/c = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(sting_action(user, target))
|
||||
SSblackbox.add_details("changeling_powers",name)
|
||||
sting_feedback(user, target)
|
||||
@@ -52,7 +52,7 @@
|
||||
if(req_human && !ishuman(user))
|
||||
to_chat(user, "<span class='warning'>We cannot do that in this form!</span>")
|
||||
return 0
|
||||
var/datum/changeling/c = user.mind.changeling
|
||||
var/datum/antagonist/changeling/c = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(c.chem_charges < chemical_cost)
|
||||
to_chat(user, "<span class='warning'>We require at least [chemical_cost] unit\s of chemicals to do that!</span>")
|
||||
return 0
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/datum/changeling/proc/purchasePower(mob/living/carbon/user, sting_name)
|
||||
|
||||
var/obj/effect/proc_holder/changeling/thepower = null
|
||||
|
||||
for(var/path in subtypesof(/obj/effect/proc_holder/changeling))
|
||||
var/obj/effect/proc_holder/changeling/S = path
|
||||
if(initial(S.name) == sting_name)
|
||||
thepower = new path()
|
||||
break
|
||||
|
||||
if(!thepower)
|
||||
to_chat(user, "This is awkward. Changeling power purchase failed, please report this bug to a coder!")
|
||||
return
|
||||
|
||||
if(absorbedcount < thepower.req_dna)
|
||||
to_chat(user, "We lack the energy to evolve this ability!")
|
||||
return
|
||||
|
||||
if(has_sting(thepower))
|
||||
to_chat(user, "We have already evolved this ability!")
|
||||
return
|
||||
|
||||
if(thepower.dna_cost < 0)
|
||||
to_chat(user, "We cannot evolve this ability.")
|
||||
return
|
||||
|
||||
if(geneticpoints < thepower.dna_cost)
|
||||
to_chat(user, "We have reached our capacity for abilities.")
|
||||
return
|
||||
|
||||
if(user.status_flags & FAKEDEATH)//To avoid potential exploits by buying new powers while in stasis, which clears your verblist.
|
||||
to_chat(user, "We lack the energy to evolve new abilities right now.")
|
||||
return
|
||||
|
||||
geneticpoints -= thepower.dna_cost
|
||||
purchasedpowers += thepower
|
||||
thepower.on_purchase(user)
|
||||
|
||||
//Reselect powers
|
||||
/datum/changeling/proc/lingRespec(mob/user)
|
||||
if(!ishuman(user))
|
||||
to_chat(user, "<span class='danger'>We can't remove our evolutions in this form!</span>")
|
||||
return
|
||||
if(canrespec)
|
||||
to_chat(user, "<span class='notice'>We have removed our evolutions from this form, and are now ready to readapt.</span>")
|
||||
user.remove_changeling_powers(1)
|
||||
canrespec = 0
|
||||
user.make_changeling(TRUE)
|
||||
return 1
|
||||
else
|
||||
to_chat(user, "<span class='danger'>You lack the power to readapt your evolutions!</span>")
|
||||
return 0
|
||||
|
||||
/mob/proc/make_changeling(is_respec)
|
||||
if(!mind)
|
||||
return
|
||||
if(!ishuman(src) && !ismonkey(src))
|
||||
return
|
||||
if(!mind.changeling)
|
||||
mind.changeling = new /datum/changeling(gender)
|
||||
if(mind.changeling.purchasedpowers)
|
||||
remove_changeling_powers(1)
|
||||
// purchase free powers.
|
||||
for(var/path in subtypesof(/obj/effect/proc_holder/changeling))
|
||||
var/obj/effect/proc_holder/changeling/S = new path()
|
||||
if(!S.dna_cost)
|
||||
if(!mind.changeling.has_sting(S))
|
||||
mind.changeling.purchasedpowers+=S
|
||||
S.on_purchase(src, is_respec)
|
||||
if(is_respec)
|
||||
SSblackbox.add_details("changeling_power_purchase","Readapt")
|
||||
|
||||
var/mob/living/carbon/C = src //only carbons have dna now, so we have to typecaste
|
||||
if(ishuman(C))
|
||||
var/datum/changelingprofile/prof = mind.changeling.add_new_profile(C, src)
|
||||
mind.changeling.first_prof = prof
|
||||
|
||||
var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN)
|
||||
if(B)
|
||||
B.vital = FALSE
|
||||
B.decoy_override = TRUE
|
||||
return 1
|
||||
|
||||
/datum/changeling/proc/reset()
|
||||
chosen_sting = null
|
||||
geneticpoints = initial(geneticpoints)
|
||||
sting_range = initial(sting_range)
|
||||
chem_storage = initial(chem_storage)
|
||||
chem_recharge_rate = initial(chem_recharge_rate)
|
||||
chem_charges = min(chem_charges, chem_storage)
|
||||
chem_recharge_slowdown = initial(chem_recharge_slowdown)
|
||||
mimicing = ""
|
||||
|
||||
/mob/proc/remove_changeling_powers(keep_free_powers=0)
|
||||
if(ishuman(src) || ismonkey(src))
|
||||
if(mind && mind.changeling)
|
||||
mind.changeling.changeling_speak = 0
|
||||
mind.changeling.reset()
|
||||
for(var/obj/effect/proc_holder/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)
|
||||
if(hud_used)
|
||||
hud_used.lingstingdisplay.icon_state = null
|
||||
hud_used.lingstingdisplay.invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
/datum/changeling/proc/has_sting(obj/effect/proc_holder/changeling/power)
|
||||
for(var/obj/effect/proc_holder/changeling/P in purchasedpowers)
|
||||
if(initial(power.name) == P.name)
|
||||
return 1
|
||||
return 0
|
||||
@@ -9,7 +9,7 @@
|
||||
if(!..())
|
||||
return
|
||||
|
||||
var/datum/changeling/changeling = user.mind.changeling
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(changeling.isabsorbing)
|
||||
to_chat(user, "<span class='warning'>We are already absorbing!</span>")
|
||||
return
|
||||
@@ -22,12 +22,12 @@
|
||||
return
|
||||
|
||||
var/mob/living/carbon/target = user.pulling
|
||||
return changeling.can_absorb_dna(user,target)
|
||||
return changeling.can_absorb_dna(target)
|
||||
|
||||
|
||||
|
||||
/obj/effect/proc_holder/changeling/absorbDNA/sting_action(mob/user)
|
||||
var/datum/changeling/changeling = user.mind.changeling
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
var/mob/living/carbon/human/target = user.pulling
|
||||
changeling.isabsorbing = 1
|
||||
for(var/i in 1 to 3)
|
||||
@@ -52,7 +52,7 @@
|
||||
to_chat(target, "<span class='userdanger'>You are absorbed by the changeling!</span>")
|
||||
|
||||
if(!changeling.has_dna(target.dna))
|
||||
changeling.add_new_profile(target, user)
|
||||
changeling.add_new_profile(target)
|
||||
|
||||
if(user.nutrition < NUTRITION_LEVEL_WELL_FED)
|
||||
user.nutrition = min((user.nutrition + target.nutrition), NUTRITION_LEVEL_WELL_FED)
|
||||
@@ -84,12 +84,14 @@
|
||||
user.mind.store_memory("<B>We have no more knowledge of [target]'s speech patterns.</B>")
|
||||
to_chat(user, "<span class='boldnotice'>We have no more knowledge of [target]'s speech patterns.</span>")
|
||||
|
||||
if(target.mind.changeling)//If the target was a changeling, suck out their extra juice and objective points!
|
||||
changeling.chem_charges += min(target.mind.changeling.chem_charges, changeling.chem_storage)
|
||||
changeling.absorbedcount += (target.mind.changeling.absorbedcount)
|
||||
|
||||
target.mind.changeling.stored_profiles.len = 1
|
||||
target.mind.changeling.absorbedcount = 0
|
||||
var/datum/antagonist/changeling/target_ling = target.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(target_ling)//If the target was a changeling, suck out their extra juice and objective points!
|
||||
changeling.chem_charges += min(target_ling.chem_charges, changeling.chem_storage)
|
||||
changeling.absorbedcount += (target_ling.absorbedcount)
|
||||
|
||||
target_ling.stored_profiles.len = 1
|
||||
target_ling.absorbedcount = 0
|
||||
|
||||
|
||||
changeling.chem_charges=min(changeling.chem_charges+10, changeling.chem_storage)
|
||||
|
||||
@@ -1,35 +1,37 @@
|
||||
/obj/effect/proc_holder/changeling/fakedeath
|
||||
name = "Reviving Stasis"
|
||||
desc = "We fall into a stasis, allowing us to regenerate and trick our enemies."
|
||||
chemical_cost = 15
|
||||
dna_cost = 0
|
||||
req_dna = 1
|
||||
req_stat = DEAD
|
||||
|
||||
//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(mob/living/user)
|
||||
to_chat(user, "<span class='notice'>We begin our stasis, preparing energy to arise once more.</span>")
|
||||
if(user.stat != DEAD)
|
||||
user.emote("deathgasp")
|
||||
user.tod = worldtime2text()
|
||||
user.status_flags |= FAKEDEATH //play dead
|
||||
user.update_stat()
|
||||
user.update_canmove()
|
||||
|
||||
addtimer(CALLBACK(src, .proc/ready_to_regenerate, user), LING_FAKEDEATH_TIME, TIMER_UNIQUE)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/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 revive.</span>")
|
||||
user.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/revive(null)
|
||||
|
||||
/obj/effect/proc_holder/changeling/fakedeath/can_sting(mob/user)
|
||||
if(user.status_flags & FAKEDEATH)
|
||||
to_chat(user, "<span class='warning'>We are already reviving.</span>")
|
||||
return
|
||||
if(!user.stat) //Confirmation for living changelings if they want to fake their death
|
||||
switch(alert("Are we sure we wish to fake our own death?",,"Yes", "No"))
|
||||
if("No")
|
||||
return
|
||||
return ..()
|
||||
/obj/effect/proc_holder/changeling/fakedeath
|
||||
name = "Reviving Stasis"
|
||||
desc = "We fall into a stasis, allowing us to regenerate and trick our enemies."
|
||||
chemical_cost = 15
|
||||
dna_cost = 0
|
||||
req_dna = 1
|
||||
req_stat = DEAD
|
||||
|
||||
//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(mob/living/user)
|
||||
to_chat(user, "<span class='notice'>We begin our stasis, preparing energy to arise once more.</span>")
|
||||
if(user.stat != DEAD)
|
||||
user.emote("deathgasp")
|
||||
user.tod = worldtime2text()
|
||||
user.status_flags |= FAKEDEATH //play dead
|
||||
user.update_stat()
|
||||
user.update_canmove()
|
||||
|
||||
addtimer(CALLBACK(src, .proc/ready_to_regenerate, user), LING_FAKEDEATH_TIME, TIMER_UNIQUE)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/changeling/fakedeath/proc/ready_to_regenerate(mob/user)
|
||||
if(user && user.mind)
|
||||
var/datum/antagonist/changeling/C = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(C && C.purchasedpowers)
|
||||
to_chat(user, "<span class='notice'>We are ready to revive.</span>")
|
||||
C.purchasedpowers += new /obj/effect/proc_holder/changeling/revive(null)
|
||||
|
||||
/obj/effect/proc_holder/changeling/fakedeath/can_sting(mob/user)
|
||||
if(user.status_flags & FAKEDEATH)
|
||||
to_chat(user, "<span class='warning'>We are already reviving.</span>")
|
||||
return
|
||||
if(!user.stat) //Confirmation for living changelings if they want to fake their death
|
||||
switch(alert("Are we sure we wish to fake our own death?",,"Yes", "No"))
|
||||
if("No")
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -1,93 +1,93 @@
|
||||
//HIVEMIND COMMUNICATION (:g)
|
||||
/obj/effect/proc_holder/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
|
||||
|
||||
/obj/effect/proc_holder/changeling/hivemind_comms/on_purchase(mob/user, is_respec)
|
||||
..()
|
||||
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
|
||||
if(!changeling.has_sting(S1))
|
||||
changeling.purchasedpowers+=S1
|
||||
var/obj/effect/proc_holder/changeling/hivemind_download/S2 = new
|
||||
if(!changeling.has_sting(S2))
|
||||
changeling.purchasedpowers+=S2
|
||||
|
||||
// HIVE MIND UPLOAD/DOWNLOAD DNA
|
||||
GLOBAL_LIST_EMPTY(hivemind_bank)
|
||||
|
||||
/obj/effect/proc_holder/changeling/hivemind_upload
|
||||
name = "Hive Channel DNA"
|
||||
desc = "Allows us to channel DNA in the airwaves to allow other changelings to absorb it."
|
||||
chemical_cost = 10
|
||||
dna_cost = -1
|
||||
|
||||
/obj/effect/proc_holder/changeling/hivemind_upload/sting_action(var/mob/user)
|
||||
var/datum/changeling/changeling = user.mind.changeling
|
||||
var/list/names = list()
|
||||
for(var/datum/changelingprofile/prof in changeling.stored_profiles)
|
||||
if(!(prof in GLOB.hivemind_bank))
|
||||
names += prof.name
|
||||
|
||||
if(names.len <= 0)
|
||||
to_chat(user, "<span class='notice'>The airwaves already have all of our DNA.</span>")
|
||||
return
|
||||
|
||||
var/chosen_name = input("Select a DNA to channel: ", "Channel DNA", null) as null|anything in names
|
||||
if(!chosen_name)
|
||||
return
|
||||
|
||||
var/datum/changelingprofile/chosen_dna = changeling.get_dna(chosen_name)
|
||||
if(!chosen_dna)
|
||||
return
|
||||
|
||||
var/datum/changelingprofile/uploaded_dna = new chosen_dna.type
|
||||
chosen_dna.copy_profile(uploaded_dna)
|
||||
GLOB.hivemind_bank += uploaded_dna
|
||||
to_chat(user, "<span class='notice'>We channel the DNA of [chosen_name] to the air.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/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."
|
||||
chemical_cost = 10
|
||||
dna_cost = -1
|
||||
|
||||
/obj/effect/proc_holder/changeling/hivemind_download/can_sting(mob/living/carbon/user)
|
||||
if(!..())
|
||||
return
|
||||
var/datum/changeling/changeling = user.mind.changeling
|
||||
var/datum/changelingprofile/first_prof = changeling.stored_profiles[1]
|
||||
if(first_prof.name == user.real_name)//If our current DNA is the stalest, we gotta ditch it.
|
||||
to_chat(user, "<span class='warning'>We have reached our capacity to store genetic information! We must transform before absorbing more.</span>")
|
||||
return
|
||||
return 1
|
||||
|
||||
/obj/effect/proc_holder/changeling/hivemind_download/sting_action(mob/user)
|
||||
var/datum/changeling/changeling = user.mind.changeling
|
||||
var/list/names = list()
|
||||
for(var/datum/changelingprofile/prof in GLOB.hivemind_bank)
|
||||
if(!(prof in changeling.stored_profiles))
|
||||
names[prof.name] = prof
|
||||
|
||||
if(names.len <= 0)
|
||||
to_chat(user, "<span class='notice'>There's no new DNA to absorb from the air.</span>")
|
||||
return
|
||||
|
||||
var/S = input("Select a DNA absorb from the air: ", "Absorb DNA", null) as null|anything in names
|
||||
if(!S)
|
||||
return
|
||||
var/datum/changelingprofile/chosen_prof = names[S]
|
||||
if(!chosen_prof)
|
||||
return
|
||||
|
||||
var/datum/changelingprofile/downloaded_prof = new chosen_prof.type
|
||||
chosen_prof.copy_profile(downloaded_prof)
|
||||
changeling.add_profile(downloaded_prof)
|
||||
to_chat(user, "<span class='notice'>We absorb the DNA of [S] from the air.</span>")
|
||||
return TRUE
|
||||
//HIVEMIND COMMUNICATION (:g)
|
||||
/obj/effect/proc_holder/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
|
||||
|
||||
/obj/effect/proc_holder/changeling/hivemind_comms/on_purchase(mob/user, is_respec)
|
||||
..()
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/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
|
||||
if(!changeling.has_sting(S1))
|
||||
changeling.purchasedpowers+=S1
|
||||
var/obj/effect/proc_holder/changeling/hivemind_download/S2 = new
|
||||
if(!changeling.has_sting(S2))
|
||||
changeling.purchasedpowers+=S2
|
||||
|
||||
// HIVE MIND UPLOAD/DOWNLOAD DNA
|
||||
GLOBAL_LIST_EMPTY(hivemind_bank)
|
||||
|
||||
/obj/effect/proc_holder/changeling/hivemind_upload
|
||||
name = "Hive Channel DNA"
|
||||
desc = "Allows us to channel DNA in the airwaves to allow other changelings to absorb it."
|
||||
chemical_cost = 10
|
||||
dna_cost = -1
|
||||
|
||||
/obj/effect/proc_holder/changeling/hivemind_upload/sting_action(var/mob/user)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
var/list/names = list()
|
||||
for(var/datum/changelingprofile/prof in changeling.stored_profiles)
|
||||
if(!(prof in GLOB.hivemind_bank))
|
||||
names += prof.name
|
||||
|
||||
if(names.len <= 0)
|
||||
to_chat(user, "<span class='notice'>The airwaves already have all of our DNA.</span>")
|
||||
return
|
||||
|
||||
var/chosen_name = input("Select a DNA to channel: ", "Channel DNA", null) as null|anything in names
|
||||
if(!chosen_name)
|
||||
return
|
||||
|
||||
var/datum/changelingprofile/chosen_dna = changeling.get_dna(chosen_name)
|
||||
if(!chosen_dna)
|
||||
return
|
||||
|
||||
var/datum/changelingprofile/uploaded_dna = new chosen_dna.type
|
||||
chosen_dna.copy_profile(uploaded_dna)
|
||||
GLOB.hivemind_bank += uploaded_dna
|
||||
to_chat(user, "<span class='notice'>We channel the DNA of [chosen_name] to the air.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/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."
|
||||
chemical_cost = 10
|
||||
dna_cost = -1
|
||||
|
||||
/obj/effect/proc_holder/changeling/hivemind_download/can_sting(mob/living/carbon/user)
|
||||
if(!..())
|
||||
return
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
var/datum/changelingprofile/first_prof = changeling.stored_profiles[1]
|
||||
if(first_prof.name == user.real_name)//If our current DNA is the stalest, we gotta ditch it.
|
||||
to_chat(user, "<span class='warning'>We have reached our capacity to store genetic information! We must transform before absorbing more.</span>")
|
||||
return
|
||||
return 1
|
||||
|
||||
/obj/effect/proc_holder/changeling/hivemind_download/sting_action(mob/user)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
var/list/names = list()
|
||||
for(var/datum/changelingprofile/prof in GLOB.hivemind_bank)
|
||||
if(!(prof in changeling.stored_profiles))
|
||||
names[prof.name] = prof
|
||||
|
||||
if(names.len <= 0)
|
||||
to_chat(user, "<span class='notice'>There's no new DNA to absorb from the air.</span>")
|
||||
return
|
||||
|
||||
var/S = input("Select a DNA absorb from the air: ", "Absorb DNA", null) as null|anything in names
|
||||
if(!S)
|
||||
return
|
||||
var/datum/changelingprofile/chosen_prof = names[S]
|
||||
if(!chosen_prof)
|
||||
return
|
||||
|
||||
var/datum/changelingprofile/downloaded_prof = new chosen_prof.type
|
||||
chosen_prof.copy_profile(downloaded_prof)
|
||||
changeling.add_profile(downloaded_prof)
|
||||
to_chat(user, "<span class='notice'>We absorb the DNA of [S] from the air.</span>")
|
||||
return TRUE
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
/obj/effect/proc_holder/changeling/humanform
|
||||
name = "Human Form"
|
||||
desc = "We change into a human."
|
||||
chemical_cost = 5
|
||||
req_dna = 1
|
||||
|
||||
//Transform into a human.
|
||||
/obj/effect/proc_holder/changeling/humanform/sting_action(mob/living/carbon/user)
|
||||
var/datum/changeling/changeling = user.mind.changeling
|
||||
var/list/names = list()
|
||||
for(var/datum/changelingprofile/prof in changeling.stored_profiles)
|
||||
names += "[prof.name]"
|
||||
|
||||
var/chosen_name = input("Select the target DNA: ", "Target DNA", null) as null|anything in names
|
||||
if(!chosen_name)
|
||||
return
|
||||
|
||||
var/datum/changelingprofile/chosen_prof = changeling.get_dna(chosen_name)
|
||||
if(!chosen_prof)
|
||||
return
|
||||
if(!user || user.notransform)
|
||||
return 0
|
||||
to_chat(user, "<span class='notice'>We transform our appearance.</span>")
|
||||
|
||||
changeling.purchasedpowers -= src
|
||||
|
||||
var/newmob = user.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS)
|
||||
|
||||
changeling_transform(newmob, chosen_prof)
|
||||
return TRUE
|
||||
/obj/effect/proc_holder/changeling/humanform
|
||||
name = "Human Form"
|
||||
desc = "We change into a human."
|
||||
chemical_cost = 5
|
||||
req_dna = 1
|
||||
|
||||
//Transform into a human.
|
||||
/obj/effect/proc_holder/changeling/humanform/sting_action(mob/living/carbon/user)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
var/list/names = list()
|
||||
for(var/datum/changelingprofile/prof in changeling.stored_profiles)
|
||||
names += "[prof.name]"
|
||||
|
||||
var/chosen_name = input("Select the target DNA: ", "Target DNA", null) as null|anything in names
|
||||
if(!chosen_name)
|
||||
return
|
||||
|
||||
var/datum/changelingprofile/chosen_prof = changeling.get_dna(chosen_name)
|
||||
if(!chosen_prof)
|
||||
return
|
||||
if(!user || user.notransform)
|
||||
return 0
|
||||
to_chat(user, "<span class='notice'>We transform our appearance.</span>")
|
||||
|
||||
changeling.purchasedpowers -= src
|
||||
|
||||
var/newmob = user.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS)
|
||||
|
||||
changeling_transform(newmob, chosen_prof)
|
||||
return TRUE
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/obj/effect/proc_holder/changeling/linglink/can_sting(mob/living/carbon/user)
|
||||
if(!..())
|
||||
return
|
||||
var/datum/changeling/changeling = user.mind.changeling
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(changeling.islinking)
|
||||
to_chat(user, "<span class='warning'>We have already formed a link with the victim!</span>")
|
||||
return
|
||||
@@ -19,22 +19,23 @@
|
||||
to_chat(user, "<span class='warning'>We cannot link with this creature!</span>")
|
||||
return
|
||||
var/mob/living/carbon/target = user.pulling
|
||||
|
||||
if(!target.mind)
|
||||
to_chat(user, "<span class='warning'>The victim has no mind to link to!</span>")
|
||||
return
|
||||
if(target.stat == DEAD)
|
||||
to_chat(user, "<span class='warning'>The victim is dead, you cannot link to a dead mind!</span>")
|
||||
return
|
||||
if(target.mind.changeling)
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='warning'>The victim is already a part of the hivemind!</span>")
|
||||
return
|
||||
if(user.grab_state <= GRAB_AGGRESSIVE)
|
||||
to_chat(user, "<span class='warning'>We must have a tighter grip to link with this creature!</span>")
|
||||
return
|
||||
return changeling.can_absorb_dna(user,target)
|
||||
return changeling.can_absorb_dna(target)
|
||||
|
||||
/obj/effect/proc_holder/changeling/linglink/sting_action(mob/user)
|
||||
var/datum/changeling/changeling = user.mind.changeling
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
var/mob/living/carbon/human/target = user.pulling
|
||||
changeling.islinking = 1
|
||||
for(var/i in 1 to 3)
|
||||
@@ -47,7 +48,8 @@
|
||||
if(3)
|
||||
to_chat(user, "<span class='notice'>We mold the [target]'s mind like clay, granting [target.p_them()] the ability to speak in the hivemind!</span>")
|
||||
to_chat(target, "<span class='userdanger'>A migraine throbs behind your eyes, you hear yourself screaming - but your mouth has not opened!</span>")
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
for(var/mi in GLOB.mob_list)
|
||||
var/mob/M = mi
|
||||
if(M.lingcheck() == 2)
|
||||
to_chat(M, "<i><font color=#800080>We can sense a foreign presence in the hivemind...</font></i>")
|
||||
target.mind.linglink = 1
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/obj/effect/proc_holder/changeling/mimicvoice
|
||||
name = "Mimic Voice"
|
||||
desc = "We shape our vocal glands to sound like a desired voice."
|
||||
helptext = "Will turn your voice into the name that you enter. We must constantly expend chemicals to maintain our form like this."
|
||||
chemical_cost = 0 //constant chemical drain hardcoded
|
||||
dna_cost = 1
|
||||
req_human = 1
|
||||
|
||||
|
||||
// Fake Voice
|
||||
/obj/effect/proc_holder/changeling/mimicvoice/sting_action(mob/user)
|
||||
var/datum/changeling/changeling=user.mind.changeling
|
||||
if(changeling.mimicing)
|
||||
changeling.mimicing = ""
|
||||
changeling.chem_recharge_slowdown -= 0.5
|
||||
to_chat(user, "<span class='notice'>We return our vocal glands to their original position.</span>")
|
||||
return
|
||||
|
||||
var/mimic_voice = stripped_input(user, "Enter a name to mimic.", "Mimic Voice", null, MAX_NAME_LEN)
|
||||
if(!mimic_voice)
|
||||
return
|
||||
|
||||
changeling.mimicing = mimic_voice
|
||||
changeling.chem_recharge_slowdown += 0.5
|
||||
to_chat(user, "<span class='notice'>We shape our glands to take the voice of <b>[mimic_voice]</b>, this will slow down regenerating chemicals while active.</span>")
|
||||
to_chat(user, "<span class='notice'>Use this power again to return to our original voice and return chemical production to normal levels.</span>")
|
||||
return TRUE
|
||||
/obj/effect/proc_holder/changeling/mimicvoice
|
||||
name = "Mimic Voice"
|
||||
desc = "We shape our vocal glands to sound like a desired voice."
|
||||
helptext = "Will turn your voice into the name that you enter. We must constantly expend chemicals to maintain our form like this."
|
||||
chemical_cost = 0 //constant chemical drain hardcoded
|
||||
dna_cost = 1
|
||||
req_human = 1
|
||||
|
||||
|
||||
// Fake Voice
|
||||
/obj/effect/proc_holder/changeling/mimicvoice/sting_action(mob/user)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(changeling.mimicing)
|
||||
changeling.mimicing = ""
|
||||
changeling.chem_recharge_slowdown -= 0.5
|
||||
to_chat(user, "<span class='notice'>We return our vocal glands to their original position.</span>")
|
||||
return
|
||||
|
||||
var/mimic_voice = stripped_input(user, "Enter a name to mimic.", "Mimic Voice", null, MAX_NAME_LEN)
|
||||
if(!mimic_voice)
|
||||
return
|
||||
|
||||
changeling.mimicing = mimic_voice
|
||||
changeling.chem_recharge_slowdown += 0.5
|
||||
to_chat(user, "<span class='notice'>We shape our glands to take the voice of <b>[mimic_voice]</b>, this will slow down regenerating chemicals while active.</span>")
|
||||
to_chat(user, "<span class='notice'>Use this power again to return to our original voice and return chemical production to normal levels.</span>")
|
||||
return TRUE
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
|
||||
//checks if we already have an organic suit and casts it off.
|
||||
/obj/effect/proc_holder/changeling/suit/proc/check_suit(mob/user)
|
||||
var/datum/changeling/changeling = user.mind.changeling
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(!ishuman(user) || !changeling)
|
||||
return 1
|
||||
var/mob/living/carbon/human/H = user
|
||||
@@ -122,7 +122,7 @@
|
||||
user.equip_to_slot_if_possible(new suit_type(user), slot_wear_suit, 1, 1, 1)
|
||||
user.equip_to_slot_if_possible(new helmet_type(user), slot_head, 1, 1, 1)
|
||||
|
||||
var/datum/changeling/changeling = user.mind.changeling
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
changeling.chem_recharge_slowdown += recharge_slowdown
|
||||
return TRUE
|
||||
|
||||
@@ -385,7 +385,7 @@
|
||||
weapon_name_simple = "shield"
|
||||
|
||||
/obj/effect/proc_holder/changeling/weapon/shield/sting_action(mob/user)
|
||||
var/datum/changeling/changeling = user.mind.changeling //So we can read the absorbedcount.
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling) //So we can read the absorbedcount.
|
||||
if(!changeling)
|
||||
return
|
||||
|
||||
|
||||
@@ -1,35 +1,37 @@
|
||||
/obj/effect/proc_holder/changeling/revive
|
||||
name = "Revive"
|
||||
desc = "We regenerate, healing all damage from our form."
|
||||
helptext = "Does not regrow lost organs or a missing head."
|
||||
req_stat = DEAD
|
||||
always_keep = TRUE
|
||||
ignores_fakedeath = TRUE
|
||||
|
||||
//Revive from revival stasis
|
||||
/obj/effect/proc_holder/changeling/revive/sting_action(mob/living/carbon/user)
|
||||
user.status_flags &= ~(FAKEDEATH)
|
||||
user.tod = null
|
||||
user.revive(full_heal = 1)
|
||||
var/list/missing = user.get_missing_limbs()
|
||||
missing -= "head" // headless changelings are funny
|
||||
if(missing.len)
|
||||
playsound(user, 'sound/magic/demon_consume.ogg', 50, 1)
|
||||
user.visible_message("<span class='warning'>[user]'s missing limbs \
|
||||
reform, making a loud, grotesque sound!</span>",
|
||||
"<span class='userdanger'>Your limbs regrow, making a \
|
||||
loud, crunchy sound and giving you great pain!</span>",
|
||||
"<span class='italics'>You hear organic matter ripping \
|
||||
and tearing!</span>")
|
||||
user.emote("scream")
|
||||
user.regenerate_limbs(0, list("head"))
|
||||
/obj/effect/proc_holder/changeling/revive
|
||||
name = "Revive"
|
||||
desc = "We regenerate, healing all damage from our form."
|
||||
helptext = "Does not regrow lost organs or a missing head."
|
||||
req_stat = DEAD
|
||||
always_keep = TRUE
|
||||
ignores_fakedeath = TRUE
|
||||
|
||||
//Revive from revival stasis
|
||||
/obj/effect/proc_holder/changeling/revive/sting_action(mob/living/carbon/user)
|
||||
user.status_flags &= ~(FAKEDEATH)
|
||||
user.tod = null
|
||||
user.revive(full_heal = 1)
|
||||
var/list/missing = user.get_missing_limbs()
|
||||
missing -= "head" // headless changelings are funny
|
||||
if(missing.len)
|
||||
playsound(user, 'sound/magic/demon_consume.ogg', 50, 1)
|
||||
user.visible_message("<span class='warning'>[user]'s missing limbs \
|
||||
reform, making a loud, grotesque sound!</span>",
|
||||
"<span class='userdanger'>Your limbs regrow, making a \
|
||||
loud, crunchy sound and giving you great pain!</span>",
|
||||
"<span class='italics'>You hear organic matter ripping \
|
||||
and tearing!</span>")
|
||||
user.emote("scream")
|
||||
user.regenerate_limbs(0, list("head"))
|
||||
user.regenerate_organs()
|
||||
to_chat(user, "<span class='notice'>We have revived ourselves.</span>")
|
||||
user.mind.changeling.purchasedpowers -= src
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/changeling/revive/can_be_used_by(mob/user)
|
||||
if((user.stat != DEAD) && !(user.status_flags & FAKEDEATH))
|
||||
user.mind.changeling.purchasedpowers -= src
|
||||
return 0
|
||||
. = ..()
|
||||
to_chat(user, "<span class='notice'>We have revived ourselves.</span>")
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
changeling.purchasedpowers -= src
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/changeling/revive/can_be_used_by(mob/user)
|
||||
if((user.stat != DEAD) && !(user.status_flags & FAKEDEATH))
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
changeling.purchasedpowers -= src
|
||||
return 0
|
||||
. = ..()
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
for(var/mob/living/M in get_hearers_in_view(4, user))
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/C = M
|
||||
if(!C.mind || !C.mind.changeling)
|
||||
if(!C.mind || !C.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
C.adjustEarDamage(0, 30)
|
||||
C.confused += 25
|
||||
C.Jitter(50)
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/Click()
|
||||
var/mob/user = usr
|
||||
if(!user || !user.mind || !user.mind.changeling)
|
||||
if(!user || !user.mind)
|
||||
return
|
||||
if(!(user.mind.changeling.chosen_sting))
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(!changeling)
|
||||
return
|
||||
if(!changeling.chosen_sting)
|
||||
set_sting(user)
|
||||
else
|
||||
unset_sting(user)
|
||||
@@ -15,41 +18,48 @@
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/proc/set_sting(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
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
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(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
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
changeling.chosen_sting = null
|
||||
|
||||
user.hud_used.lingstingdisplay.icon_state = null
|
||||
user.hud_used.lingstingdisplay.invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
/mob/living/carbon/proc/unset_sting()
|
||||
if(mind && mind.changeling && mind.changeling.chosen_sting)
|
||||
src.mind.changeling.chosen_sting.unset_sting(src)
|
||||
if(mind)
|
||||
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(changeling && changeling.chosen_sting)
|
||||
changeling.chosen_sting.unset_sting(src)
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/can_sting(mob/user, mob/target)
|
||||
if(!..())
|
||||
return
|
||||
if(!user.mind.changeling.chosen_sting)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(!changeling.chosen_sting)
|
||||
to_chat(user, "We haven't prepared our sting yet!")
|
||||
if(!iscarbon(target))
|
||||
return
|
||||
if(!isturf(user.loc))
|
||||
return
|
||||
if(!AStar(user, target.loc, /turf/proc/Distance, user.mind.changeling.sting_range, simulated_only = 0))
|
||||
if(!AStar(user, target.loc, /turf/proc/Distance, changeling.sting_range, simulated_only = 0))
|
||||
return
|
||||
if(target.mind && target.mind.changeling)
|
||||
if(target.mind && target.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
sting_feedback(user, target)
|
||||
user.mind.changeling.chem_charges -= chemical_cost
|
||||
changeling.chem_charges -= chemical_cost //??
|
||||
return 1
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/sting_feedback(mob/user, mob/target)
|
||||
if(!target)
|
||||
return
|
||||
to_chat(user, "<span class='notice'>We stealthily sting [target.name].</span>")
|
||||
if(target.mind && target.mind.changeling)
|
||||
if(target.mind && target.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(target, "<span class='warning'>You feel a tiny prick.</span>")
|
||||
return 1
|
||||
|
||||
@@ -65,7 +75,7 @@
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/transformation/Click()
|
||||
var/mob/user = usr
|
||||
var/datum/changeling/changeling = user.mind.changeling
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(changeling.chosen_sting)
|
||||
unset_sting(user)
|
||||
return
|
||||
@@ -163,12 +173,14 @@
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/extract_dna/can_sting(mob/user, mob/target)
|
||||
if(..())
|
||||
return user.mind.changeling.can_absorb_dna(user, target)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
return changeling.can_absorb_dna(target)
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/extract_dna/sting_action(mob/user, mob/living/carbon/human/target)
|
||||
add_logs(user, target, "stung", "extraction sting")
|
||||
if(!(user.mind.changeling.has_dna(target.dna)))
|
||||
user.mind.changeling.add_new_profile(target, user)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(!(changeling.has_dna(target.dna)))
|
||||
changeling.add_new_profile(target)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/mute
|
||||
|
||||
@@ -1,126 +1,129 @@
|
||||
/obj/effect/proc_holder/changeling/transform
|
||||
name = "Transform"
|
||||
desc = "We take on the appearance and voice of one we have absorbed."
|
||||
chemical_cost = 5
|
||||
dna_cost = 0
|
||||
req_dna = 1
|
||||
req_human = 1
|
||||
|
||||
/obj/item/clothing/glasses/changeling
|
||||
name = "flesh"
|
||||
/obj/effect/proc_holder/changeling/transform
|
||||
name = "Transform"
|
||||
desc = "We take on the appearance and voice of one we have absorbed."
|
||||
chemical_cost = 5
|
||||
dna_cost = 0
|
||||
req_dna = 1
|
||||
req_human = 1
|
||||
|
||||
/obj/item/clothing/glasses/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
|
||||
/obj/item/clothing/glasses/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.changeling)
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/under/changeling
|
||||
name = "flesh"
|
||||
|
||||
/obj/item/clothing/glasses/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/under/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
|
||||
/obj/item/clothing/under/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.changeling)
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/suit/changeling
|
||||
name = "flesh"
|
||||
|
||||
/obj/item/clothing/under/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/suit/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
allowed = list(/obj/item/changeling)
|
||||
|
||||
/obj/item/clothing/suit/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.changeling)
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/head/changeling
|
||||
name = "flesh"
|
||||
allowed = list(/obj/item/changeling)
|
||||
|
||||
/obj/item/clothing/suit/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/head/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
|
||||
/obj/item/clothing/head/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.changeling)
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/shoes/changeling
|
||||
name = "flesh"
|
||||
|
||||
/obj/item/clothing/head/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/shoes/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
|
||||
/obj/item/clothing/shoes/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.changeling)
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/gloves/changeling
|
||||
name = "flesh"
|
||||
|
||||
/obj/item/clothing/shoes/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/gloves/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
|
||||
/obj/item/clothing/gloves/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.changeling)
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/mask/changeling
|
||||
name = "flesh"
|
||||
|
||||
/obj/item/clothing/gloves/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/mask/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
|
||||
/obj/item/clothing/mask/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.changeling)
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/changeling
|
||||
name = "flesh"
|
||||
|
||||
/obj/item/clothing/mask/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
slot_flags = ALL
|
||||
allowed = list(/obj/item/changeling)
|
||||
|
||||
/obj/item/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.changeling)
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
//Change our DNA to that of somebody we've absorbed.
|
||||
/obj/effect/proc_holder/changeling/transform/sting_action(mob/living/carbon/human/user)
|
||||
var/datum/changeling/changeling = user.mind.changeling
|
||||
var/datum/changelingprofile/chosen_prof = changeling.select_dna("Select the target DNA: ", "Target DNA", user)
|
||||
|
||||
if(!chosen_prof)
|
||||
return
|
||||
|
||||
changeling_transform(user, chosen_prof)
|
||||
return TRUE
|
||||
|
||||
/datum/changeling/proc/select_dna(var/prompt, var/title, var/mob/living/carbon/user)
|
||||
var/list/names = list("Drop Flesh Disguise")
|
||||
for(var/datum/changelingprofile/prof in stored_profiles)
|
||||
names += "[prof.name]"
|
||||
|
||||
var/chosen_name = input(prompt, title, null) as null|anything in names
|
||||
if(!chosen_name)
|
||||
return
|
||||
|
||||
if(chosen_name == "Drop Flesh Disguise")
|
||||
for(var/slot in GLOB.slots)
|
||||
if(istype(user.vars[slot], GLOB.slot2type[slot]))
|
||||
qdel(user.vars[slot])
|
||||
|
||||
var/datum/changelingprofile/prof = get_dna(chosen_name)
|
||||
return prof
|
||||
slot_flags = ALL
|
||||
allowed = list(/obj/item/changeling)
|
||||
|
||||
/obj/item/changeling/attack_hand(mob/user)
|
||||
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
to_chat(user, "<span class='notice'>You reabsorb [src] into your body.</span>")
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
//Change our DNA to that of somebody we've absorbed.
|
||||
/obj/effect/proc_holder/changeling/transform/sting_action(mob/living/carbon/human/user)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
var/datum/changelingprofile/chosen_prof = changeling.select_dna("Select the target DNA: ", "Target DNA")
|
||||
|
||||
if(!chosen_prof)
|
||||
return
|
||||
|
||||
changeling_transform(user, chosen_prof)
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/changeling/proc/select_dna(var/prompt, var/title)
|
||||
var/mob/living/carbon/user = owner.current
|
||||
if(!istype(user))
|
||||
return
|
||||
var/list/names = list("Drop Flesh Disguise")
|
||||
for(var/datum/changelingprofile/prof in stored_profiles)
|
||||
names += "[prof.name]"
|
||||
|
||||
var/chosen_name = input(prompt, title, null) as null|anything in names
|
||||
if(!chosen_name)
|
||||
return
|
||||
|
||||
if(chosen_name == "Drop Flesh Disguise")
|
||||
for(var/slot in GLOB.slots)
|
||||
if(istype(user.vars[slot], GLOB.slot2type[slot]))
|
||||
qdel(user.vars[slot])
|
||||
|
||||
var/datum/changelingprofile/prof = get_dna(chosen_name)
|
||||
return prof
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
reroll_friendly = 1
|
||||
|
||||
var/list/possible_changelings = list()
|
||||
var/list/changelings = list()
|
||||
var/const/changeling_amount = 1 //hard limit on changelings if scaling is turned off
|
||||
|
||||
/datum/game_mode/traitor/changeling/announce()
|
||||
@@ -57,25 +58,22 @@
|
||||
|
||||
/datum/game_mode/traitor/changeling/post_setup()
|
||||
for(var/datum/mind/changeling in changelings)
|
||||
changeling.current.make_changeling()
|
||||
forge_changeling_objectives(changeling)
|
||||
greet_changeling(changeling)
|
||||
SSticker.mode.update_changeling_icons_added(changeling)
|
||||
..()
|
||||
return
|
||||
changeling.add_antag_datum(/datum/antagonist/changeling)
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/traitor/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners
|
||||
var/csc = CONFIG_GET(number/changeling_scaling_coeff)
|
||||
var/changelingcap = min( round(GLOB.joined_player_list.len / (csc * 4)) + 2, round(GLOB.joined_player_list.len / (csc * 2)))
|
||||
if(SSticker.mode.changelings.len >= changelingcap) //Caps number of latejoin antagonists
|
||||
if(changelings.len >= changelingcap) //Caps number of latejoin antagonists
|
||||
..()
|
||||
return
|
||||
if(SSticker.mode.changelings.len <= (changelingcap - 2) || prob(100 / (csc * 4)))
|
||||
if(changelings.len <= (changelingcap - 2) || prob(100 / (csc * 4)))
|
||||
if(ROLE_CHANGELING in character.client.prefs.be_special)
|
||||
if(!jobban_isbanned(character, ROLE_CHANGELING) && !jobban_isbanned(character, "Syndicate"))
|
||||
if(age_check(character.client))
|
||||
if(!(character.job in restricted_jobs))
|
||||
character.mind.make_Changling()
|
||||
changelings += character.mind
|
||||
..()
|
||||
|
||||
/datum/game_mode/traitor/changeling/generate_report()
|
||||
|
||||
@@ -273,6 +273,7 @@ Credit where due:
|
||||
if(plasmaman && !visualsOnly) //If we need to breathe from the plasma tank, we should probably start doing that
|
||||
H.internal = H.get_item_for_held_index(2)
|
||||
H.update_internals_hud_icon(1)
|
||||
H.sec_hud_set_ID()
|
||||
|
||||
/obj/item/paper/servant_primer
|
||||
name = "The Ark And You: A Primer On Servitude"
|
||||
|
||||
@@ -38,8 +38,11 @@
|
||||
beckon(AM)
|
||||
|
||||
/obj/effect/clockwork/city_of_cogs_rift/proc/beckon(atom/movable/AM)
|
||||
var/turf/T = get_turf(pick(GLOB.city_of_cogs_spawns))
|
||||
if(is_servant_of_ratvar(AM))
|
||||
T = GLOB.ark_of_the_clockwork_justiciar ? get_step(GLOB.ark_of_the_clockwork_justiciar, SOUTH) : get_turf(pick(GLOB.servant_spawns))
|
||||
AM.visible_message("<span class='danger'>[AM] passes through [src]!</span>", ignored_mob = AM)
|
||||
AM.forceMove(pick(!is_servant_of_ratvar(AM) ? GLOB.city_of_cogs_spawns : GLOB.servant_spawns))
|
||||
AM.forceMove(T)
|
||||
AM.visible_message("<span class='danger'>[AM] materializes from the air!</span>", \
|
||||
"<span class='boldannounce'>You pass through [src] and appear [is_servant_of_ratvar(AM) ? "back at the City of Cogs" : "somewhere unfamiliar. Looks like it was a one-way trip.."].</span>")
|
||||
do_sparks(5, TRUE, src)
|
||||
|
||||
@@ -162,7 +162,7 @@
|
||||
var/locname = initial(A.name)
|
||||
possible_targets[avoid_assoc_duplicate_keys("[locname] [O.name]", teleportnames)] = O
|
||||
|
||||
for(var/mob/living/L in GLOB.living_mob_list)
|
||||
for(var/mob/living/L in GLOB.alive_mob_list)
|
||||
if(!L.stat && is_servant_of_ratvar(L) && !L.Adjacent(invoker) && (L.z <= ZLEVEL_SPACEMAX)) //People right next to the invoker can't be portaled to, for obvious reasons
|
||||
possible_targets[avoid_assoc_duplicate_keys("[L.name] ([L.real_name])", teleportnames)] = L
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ List of nuances:
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
if(!whisper)
|
||||
L.say(message, "clock", spans, language=/datum/language/common)
|
||||
L.say(message, "clock", spans, language=/datum/language/common, ignore_spam = TRUE)
|
||||
else
|
||||
L.whisper(message, "clock", spans, language=/datum/language/common)
|
||||
else
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/obj/item/clockwork/slab //Clockwork slab: The most important tool in Ratvar's arsenal. Allows scripture recital, tutorials, and generates components.
|
||||
name = "clockwork slab"
|
||||
desc = "A strange metal tablet. A clock in the center turns around and around."
|
||||
clockwork_desc = "A link between you and the Celestial Derelict. It contains information, recites scripture, and is your most vital tool as a Servant.\n\
|
||||
Hitting a slab, a Servant with a slab, or a cache will <b>transfer</b> this slab's components into the target, the target's slab, or the global cache, respectively."
|
||||
clockwork_desc = "A link between you and the Celestial Derelict. It contains information, recites scripture, and is your most vital tool as a Servant."
|
||||
icon_state = "dread_ipad"
|
||||
lefthand_file = 'icons/mob/inhands/antag/clockwork_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/antag/clockwork_righthand.dmi'
|
||||
@@ -231,7 +230,7 @@
|
||||
this will cause you to whisper your message aloud, so doing so in a public place is very suspicious and you should try to restrict it to private use.<br><br>"
|
||||
dat += "If you aren't willing or don't have the time to read through every section, you can still help your teammates! Ask if they've set up a base. If they have, head there \
|
||||
and ask however you can help; chances are there's always something. If not, it's your job as a Servant to get one up and running! Try to find a secluded, low-traffic area, \
|
||||
like the auxilary base or somewhere deep in maintenance. You'll want to go into the Drivers section of the slab and look for <i>Tinkerer's Cache.</i> Find a nice spot and \
|
||||
like the auxiliary base or somewhere deep in maintenance. You'll want to go into the Drivers section of the slab and look for <i>Tinkerer's Cache.</i> Find a nice spot and \
|
||||
create one. This serves as a storage for <i>components,</i> the cult's primary resource. (Your slab's probably produced a few by now.) By attacking that cache with this \
|
||||
slab, you'll offload all your components into it, and all Servants will be able to use those components from any distance - all Tinkerer's Caches are linked!<br><br>"
|
||||
dat += "Once you have a base up and running, contact your fellows and let them know. You should come back here often to drop off the slab's components, and your fellows \
|
||||
@@ -250,7 +249,7 @@
|
||||
teamwork is an instrumental component of your success.<br><br>" //get it? component? ha!
|
||||
dat += "As a Servant of Ratvar, the tools you are given focus around building and maintaining bases and outposts. A great deal of your power comes from stationary \
|
||||
structures, and without constructing a base somewhere, it's essentially impossible to succeed. Finding a good spot to build a base can be difficult, and it's recommended \
|
||||
that you choose an area in low-traffic part of the station (such as the auxilary base). Make sure to disconnect any cameras in the area beforehand.<br><br>"
|
||||
that you choose an area in low-traffic part of the station (such as the auxiliary base). Make sure to disconnect any cameras in the area beforehand.<br><br>"
|
||||
dat += "Because of how complex being a Servant is, it isn't possible to fit much information into this section. It's highly recommended that you read the <b>Components</b> \
|
||||
and <b>Scripture</b> sections next. Not knowing how these two systems work will cripple both you and your fellows, and lead to a frustrating experience for everyone.<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>-=-=-=-=-=-</font>"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
weather_immunities = list("lava")
|
||||
movement_type = FLYING
|
||||
a_intent = INTENT_HARM
|
||||
loot = list(/obj/item/clockwork/component/geis_capacitor/fallen_armor)
|
||||
light_range = 2
|
||||
light_power = 1.1
|
||||
@@ -24,7 +25,6 @@
|
||||
unique abilities, you're a fearsome fighter in one-on-one combat, and your shield protects from projectiles!<br><br>Obey the Servants and do as they \
|
||||
tell you. Your primary goal is to defend the Ark from destruction; they are your allies in this, and should be protected from harm.</b>"
|
||||
empower_string = "<span class='neovgre'>The Anima Bulwark's power flows through you! Your weapon will strike harder, your armor is sturdier, and your shield is more durable.</span>"
|
||||
var/deflect_chance = 40 //Chance to deflect any given projectile (non-damaging energy projectiles are always deflected)
|
||||
var/max_shield_health = 3
|
||||
var/shield_health = 3 //Amount of projectiles that can be deflected within
|
||||
var/shield_health_regen = 0 //When world.time equals this, shield health will regenerate
|
||||
@@ -55,8 +55,6 @@
|
||||
obj_damage = 100
|
||||
max_shield_health = INFINITY
|
||||
else if(GLOB.ratvar_approaches) //Hefty health bonus and slight attack damage increase
|
||||
health = 200
|
||||
maxHealth = 200
|
||||
melee_damage_upper = 15
|
||||
melee_damage_lower = 15
|
||||
attacktext = "carves"
|
||||
|
||||
@@ -53,6 +53,7 @@ Applications: 8 servants, 3 caches, and 100 CV
|
||||
if(slab.busy)
|
||||
to_chat(invoker, "<span class='warning'>[slab] refuses to work, displaying the message: \"[slab.busy]!\"</span>")
|
||||
return FALSE
|
||||
pre_recital()
|
||||
slab.busy = "Invocation ([name]) in progress"
|
||||
if(GLOB.ratvar_awakens)
|
||||
channel_time *= 0.5 //if ratvar has awoken, half channel time and no cost
|
||||
@@ -176,6 +177,9 @@ Applications: 8 servants, 3 caches, and 100 CV
|
||||
/datum/clockwork_scripture/proc/scripture_fail() //Called if the scripture fails to invoke.
|
||||
|
||||
|
||||
/datum/clockwork_scripture/proc/pre_recital() //Called before the scripture is recited
|
||||
|
||||
|
||||
/datum/clockwork_scripture/proc/post_recital() //Called after the scripture is recited
|
||||
|
||||
//Channeled scripture begins instantly but runs constantly
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
/datum/clockwork_scripture/create_object/construct/clockwork_marauder
|
||||
descname = "Well-Rounded Combat Construct"
|
||||
name = "Clockwork Marauder"
|
||||
desc = "Creates a shell for a clockwork marauder, a balanced frontline construct."
|
||||
desc = "Creates a shell for a clockwork marauder, a balanced frontline construct that can deflect projectiles with its shield."
|
||||
invocations = list("Arise, avatar of Arbiter!", "Defend the Ark with vengeful zeal.")
|
||||
channel_time = 50
|
||||
power_cost = 1000
|
||||
creator_message = "<span class='brass'>Your slab disgorges several chunks of replicant alloy that form into a suit of thrumming armor.</span>"
|
||||
usage_tip = "The marauder's shield can effectively deflect energy-based projectiles."
|
||||
usage_tip = "Reciting this scripture multiple times in a short period will cause it to take longer!"
|
||||
tier = SCRIPTURE_APPLICATION
|
||||
one_per_tile = TRUE
|
||||
primary_component = BELLIGERENT_EYE
|
||||
@@ -22,6 +22,9 @@
|
||||
object_path = /obj/item/clockwork/construct_chassis/clockwork_marauder
|
||||
construct_type = /mob/living/simple_animal/hostile/clockwork/marauder
|
||||
combat_construct = TRUE
|
||||
var/static/recent_marauders = 0
|
||||
var/static/time_since_last_marauder = 0
|
||||
var/static/scaled_recital_time = 0
|
||||
|
||||
/datum/clockwork_scripture/create_object/construct/clockwork_marauder/update_construct_limit()
|
||||
var/human_servants = 0
|
||||
@@ -32,15 +35,30 @@
|
||||
construct_limit = human_servants / 4 //1 per 4 human servants, and a maximum of 3 marauders
|
||||
construct_limit = Clamp(construct_limit, 1, 3)
|
||||
|
||||
/datum/clockwork_scripture/create_object/prolonging_prism/check_special_requirements()
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_DOCKED || SSshuttle.emergency.mode == SHUTTLE_IGNITING || SSshuttle.emergency.mode == SHUTTLE_STRANDED || SSshuttle.emergency.mode == SHUTTLE_ESCAPE)
|
||||
to_chat(invoker, "<span class='inathneq'>\"It is too late to construct one of these, champion.\"</span>")
|
||||
return FALSE
|
||||
var/turf/T = get_turf(invoker)
|
||||
if(!T || !(T.z in GLOB.station_z_levels))
|
||||
to_chat(invoker, "<span class='inathneq'>\"You must be on the station to construct one of these, champion.\"</span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
/datum/clockwork_scripture/create_object/construct/clockwork_marauder/pre_recital()
|
||||
channel_time = initial(channel_time)
|
||||
calculate_scaling()
|
||||
if(scaled_recital_time)
|
||||
to_chat(invoker, "<span class='warning'>The Hierophant Network is under strain from repeated summoning, making this scripture [scaled_recital_time / 10] seconds slower!</span>")
|
||||
channel_time += scaled_recital_time
|
||||
return TRUE
|
||||
|
||||
/datum/clockwork_scripture/create_object/construct/clockwork_marauder/scripture_effects()
|
||||
. = ..()
|
||||
time_since_last_marauder = world.time
|
||||
recent_marauders++
|
||||
calculate_scaling()
|
||||
|
||||
/datum/clockwork_scripture/create_object/construct/clockwork_marauder/proc/calculate_scaling()
|
||||
var/WT = world.time
|
||||
var/MT = time_since_last_marauder //Cast it for quicker reference
|
||||
var/marauders_to_exclude = 0
|
||||
if(world.time >= time_since_last_marauder + MARAUDER_SCRIPTURE_SCALING_THRESHOLD)
|
||||
marauders_to_exclude = round(WT - MT) / MARAUDER_SCRIPTURE_SCALING_THRESHOLD //If at least 20 seconds have passed, lose one marauder for each 20 seconds
|
||||
//i.e. world.time = 10000, last marauder = 9000, so we lose 5 marauders from the recent count since 10k - 9k = 1k, 1k / 200 = 5
|
||||
time_since_last_marauder = world.time //So that it can't be spammed to make the marauder exclusion plummet; this emulates "ticking"
|
||||
recent_marauders = max(0, recent_marauders - marauders_to_exclude)
|
||||
scaled_recital_time = min(recent_marauders * MARAUDER_SCRIPTURE_SCALING_TIME, MARAUDER_SCRIPTURE_SCALING_MAX)
|
||||
|
||||
|
||||
//Mania Motor: Creates a malevolent transmitter that will broadcast the whispers of Sevtug into the minds of nearby nonservants, causing a variety of mental effects at a power cost.
|
||||
|
||||
@@ -129,7 +129,11 @@
|
||||
|
||||
/datum/clockwork_scripture/abscond/scripture_effects()
|
||||
var/take_pulling = invoker.pulling && isliving(invoker.pulling) && get_clockwork_power(ABSCOND_ABDUCTION_COST)
|
||||
var/turf/T = get_turf(pick(GLOB.servant_spawns))
|
||||
var/turf/T
|
||||
if(GLOB.ark_of_the_clockwork_justiciar)
|
||||
T = get_step(GLOB.ark_of_the_clockwork_justiciar, SOUTH)
|
||||
else
|
||||
T = get_turf(pick(GLOB.servant_spawns))
|
||||
invoker.visible_message("<span class='warning'>[invoker] flickers and phases out of existence!</span>", \
|
||||
"<span class='bold sevtug_small'>You feel a dizzying sense of vertigo as you're yanked back to Reebe!</span>")
|
||||
T.visible_message("<span class='warning'>[invoker] flickers and phases into existence!</span>")
|
||||
|
||||
@@ -322,7 +322,7 @@
|
||||
to_chat(invoker, "<span class='warning'>You must not be inside an object to use this scripture!</span>")
|
||||
return FALSE
|
||||
var/other_servants = 0
|
||||
for(var/mob/living/L in GLOB.living_mob_list)
|
||||
for(var/mob/living/L in GLOB.alive_mob_list)
|
||||
if(is_servant_of_ratvar(L) && !L.stat && L != invoker)
|
||||
other_servants++
|
||||
for(var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/O in GLOB.all_clockwork_objects)
|
||||
|
||||
@@ -134,11 +134,21 @@
|
||||
var/damage = max((obj_integrity * 0.7) / severity, 100) //requires multiple bombs to take down
|
||||
take_damage(damage, BRUTE, "bomb", 0)
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/get_arrival_time(var/deciseconds = TRUE)
|
||||
if(seconds_until_activation)
|
||||
. = seconds_until_activation
|
||||
else if(grace_period)
|
||||
. = grace_period
|
||||
else if(GATEWAY_RATVAR_ARRIVAL - progress_in_seconds > 0)
|
||||
. = round(max((GATEWAY_RATVAR_ARRIVAL - progress_in_seconds) / (GATEWAY_SUMMON_RATE), 0), 1)
|
||||
if(deciseconds)
|
||||
. *= 10
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/get_arrival_text(s_on_time)
|
||||
if(seconds_until_activation)
|
||||
return "[seconds_until_activation][s_on_time ? "S" : ""]"
|
||||
return "[get_arrival_time()][s_on_time ? "S" : ""]"
|
||||
if(grace_period)
|
||||
return "[grace_period][s_on_time ? "S" : ""]"
|
||||
return "[get_arrival_time()][s_on_time ? "S" : ""]"
|
||||
. = "IMMINENT"
|
||||
if(!obj_integrity)
|
||||
. = "DETONATING"
|
||||
@@ -151,12 +161,12 @@
|
||||
icon_state = initial(icon_state)
|
||||
if(is_servant_of_ratvar(user) || isobserver(user))
|
||||
if(!active)
|
||||
to_chat(user, "<span class='big'><b>Seconds until the Ark's activation:</b> [get_arrival_text(TRUE)]</span>")
|
||||
to_chat(user, "<span class='big'><b>Time until the Ark's activation:</b> [DisplayTimeText(get_arrival_time())]</span>")
|
||||
else
|
||||
if(grace_period)
|
||||
to_chat(user, "<span class='big'><b>Crew grace period time remaining:</b> [get_arrival_text(TRUE)]</span>")
|
||||
to_chat(user, "<span class='big'><b>Crew grace period time remaining:</b> [DisplayTimeText(get_arrival_time())]</span>")
|
||||
else
|
||||
to_chat(user, "<span class='big'><b>Seconds until Ratvar's arrival:</b> [get_arrival_text(TRUE)]</span>")
|
||||
to_chat(user, "<span class='big'><b>Time until Ratvar's arrival:</b> [DisplayTimeText(get_arrival_time())]</span>")
|
||||
switch(progress_in_seconds)
|
||||
if(-INFINITY to GATEWAY_REEBE_FOUND)
|
||||
to_chat(user, "<span class='heavy_brass'>The Ark is feeding power into the bluespace field.</span>")
|
||||
@@ -266,15 +276,16 @@
|
||||
CHECK_TICK
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/celestial_gateway/attack_ghost(mob/user)
|
||||
if(!user.client || !user.client.holder)
|
||||
return
|
||||
if(!IsAdminGhost(user))
|
||||
return ..()
|
||||
if(GLOB.servants_active)
|
||||
to_chat(user, "<span class='danger'>The Ark is already counting down.</span>")
|
||||
return
|
||||
return ..()
|
||||
if(alert(user, "Activate the Ark's countdown?", name, "Yes", "No") == "Yes")
|
||||
if(alert(user, "REALLY activate the Ark's countdown?", name, "Yes", "No") == "Yes")
|
||||
if(alert(user, "You're REALLY SURE? This cannot be undone.", name, "Yes - Activate the Ark", "No") == "Yes - Activate the Ark")
|
||||
message_admins("<span class='danger'>Admin [key_name_admin(user)] started the Ark's countdown!</span>")
|
||||
log_admin("Admin [key_name(user)] started the Ark's countdown on a non-clockcult mode!")
|
||||
to_chat(user, "<span class='userdanger'>The gamemode is now being treated as clockwork cult, and the Ark is counting down from 30 \
|
||||
minutes. You will need to create servant players yourself.</span>")
|
||||
final_countdown(35)
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
continue
|
||||
C.update_values()
|
||||
to_chat(C, C.empower_string)
|
||||
for(var/mob/living/carbon/human/H in GLOB.living_mob_list)
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
if(is_servant_of_ratvar(H))
|
||||
to_chat(H, "<span class='bold alloy'>The beacon's power warps your body into a clockwork form! You are now immune to many hazards, and your body is more robust against damage!</span>")
|
||||
H.set_species(/datum/species/golem/clockwork/no_scrap)
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
T.ratvar_act(TRUE)
|
||||
var/dir_to_step_in = pick(GLOB.cardinals)
|
||||
var/list/meals = list()
|
||||
for(var/mob/living/L in GLOB.living_mob_list) //we want to know who's alive so we don't lose and retarget a single person
|
||||
for(var/mob/living/L in GLOB.alive_mob_list) //we want to know who's alive so we don't lose and retarget a single person
|
||||
if(L.z == z && !is_servant_of_ratvar(L) && L.mind)
|
||||
meals += L
|
||||
if(GLOB.cult_narsie && GLOB.cult_narsie.z == z)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define CULT_SCALING_COEFFICIENT 9.3 //Roughly one new cultist at roundstart per this many players
|
||||
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/cult = list()
|
||||
var/list/cult_objectives = list()
|
||||
@@ -64,7 +66,10 @@
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
//cult scaling goes here
|
||||
recommended_enemies = 3 + round(num_players()/15)
|
||||
recommended_enemies = 1 + round(num_players()/CULT_SCALING_COEFFICIENT)
|
||||
var/remaining = (num_players() % CULT_SCALING_COEFFICIENT) * 10 //Basically the % of how close the population is toward adding another cultis
|
||||
if(prob(remaining))
|
||||
recommended_enemies++
|
||||
|
||||
|
||||
for(var/cultists_number = 1 to recommended_enemies)
|
||||
@@ -256,6 +261,10 @@
|
||||
SSticker.news_report = CULT_FAILURE
|
||||
|
||||
text += "<br><B>Objective #[obj_count]</B>: [explanation]"
|
||||
if(cult.len)
|
||||
text += "<br><b>The cultists were:</b>"
|
||||
for(var/datum/mind/M in cult)
|
||||
text += printplayer(M)
|
||||
to_chat(world, text)
|
||||
..()
|
||||
return 1
|
||||
@@ -303,3 +312,5 @@
|
||||
SSticker.news_report = CULT_FAILURE
|
||||
text += "<br><B>Objective #[obj_count]</B>: [explanation]"
|
||||
to_chat(world, text)
|
||||
|
||||
#undef CULT_SCALING_COEFFICIENT
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
else if(!ishuman(user))
|
||||
title = "Construct"
|
||||
my_message = "<span class='[span]'><b>[title] [findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]:</b> [message]</span>"
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
for(var/i in GLOB.player_list)
|
||||
var/mob/M = i
|
||||
if(iscultist(M))
|
||||
to_chat(M, my_message)
|
||||
else if(M in GLOB.dead_mob_list)
|
||||
|
||||
@@ -324,7 +324,7 @@
|
||||
icon_state = "cult_armor"
|
||||
item_state = "cult_armor"
|
||||
desc = "A heavily-armored exosuit worn by warriors of the Nar-Sien cult. It can withstand hard vacuum."
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
allowed = list(/obj/item/tome, /obj/item/melee/cultblade, /obj/item/tank/internals/)
|
||||
armor = list(melee = 70, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30, fire = 40, acid = 75)
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/cult
|
||||
|
||||
@@ -137,7 +137,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
for(var/M in invokers)
|
||||
var/mob/living/L = M
|
||||
if(invocation)
|
||||
L.say(invocation, language = /datum/language/common)
|
||||
L.say(invocation, language = /datum/language/common, ignore_spam = TRUE)
|
||||
if(invoke_damage)
|
||||
L.apply_damage(invoke_damage, BRUTE)
|
||||
to_chat(L, "<span class='cultitalic'>[src] saps your strength!</span>")
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
dat += "<HR>"
|
||||
for(var/s in possible_summons)
|
||||
var/datum/cult_supply/S = s
|
||||
dat += "<a href='?src=\ref[src];id=[initial(S.id)]'>[initial(S.invocation)]</a> - [initial(S.desc)]<br>"
|
||||
dat += "<a href='?src=[REF(src)];id=[initial(S.id)]'>[initial(S.invocation)]</a> - [initial(S.desc)]<br>"
|
||||
var/datum/browser/popup = new(user, "talisman", "", 400, 400)
|
||||
popup.set_content(dat.Join(""))
|
||||
popup.open()
|
||||
|
||||
@@ -225,8 +225,8 @@
|
||||
|
||||
/obj/item/paper/talisman/horror/afterattack(mob/living/target, mob/living/user)
|
||||
if(iscultist(user) && (get_dist(user, target) < 7))
|
||||
to_chat(user, "<span class='cultitalic'>You disturb [target] with visions of madness!</span>")
|
||||
if(iscarbon(target))
|
||||
to_chat(user, "<span class='cultitalic'>You disturb [target] with visions of madness!</span>")
|
||||
var/mob/living/carbon/H = target
|
||||
H.reagents.add_reagent("mindbreaker", 12)
|
||||
if(is_servant_of_ratvar(target))
|
||||
@@ -234,8 +234,7 @@
|
||||
target.emote("scream")
|
||||
target.confused = max(0, target.confused + 3)
|
||||
target.flash_act()
|
||||
qdel(src)
|
||||
|
||||
qdel(src)
|
||||
|
||||
//Talisman of Fabrication: Creates a construct shell out of 25 metal sheets, or converts plasteel into runed metal up to 25 times
|
||||
/obj/item/paper/talisman/construction
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
var/ascended = FALSE
|
||||
sight = (SEE_TURFS | SEE_OBJS)
|
||||
status_flags = CANPUSH
|
||||
spacewalk = TRUE
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
var/mob/living/oldform
|
||||
var/list/devil_overlays[DEVIL_TOTAL_LAYERS]
|
||||
@@ -135,9 +136,6 @@
|
||||
"<span class='userdanger'>[attack_message]</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/true_devil/Process_Spacemove(movement_dir = 0)
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/true_devil/singularity_act()
|
||||
if(ascended)
|
||||
return 0
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
replacementmode.restricted_jobs += "Assistant"
|
||||
|
||||
message_admins("The roundtype will be converted. If you have other plans for the station or feel the station is too messed up to inhabit <A HREF='?_src_=holder;[HrefToken()];toggle_midround_antag=\ref[usr]'>stop the creation of antags</A> or <A HREF='?_src_=holder;[HrefToken()];end_round=\ref[usr]'>end the round now</A>.")
|
||||
message_admins("The roundtype will be converted. If you have other plans for the station or feel the station is too messed up to inhabit <A HREF='?_src_=holder;[HrefToken()];toggle_midround_antag=[REF(usr)]'>stop the creation of antags</A> or <A HREF='?_src_=holder;[HrefToken()];end_round=[REF(usr)]'>end the round now</A>.")
|
||||
|
||||
. = 1
|
||||
sleep(rand(600,1800))
|
||||
@@ -217,7 +217,7 @@
|
||||
if(living_antag_player && living_antag_player.mind && isliving(living_antag_player) && living_antag_player.stat != DEAD && !isnewplayer(living_antag_player) &&!isbrain(living_antag_player))
|
||||
return 0 //A resource saver: once we find someone who has to die for all antags to be dead, we can just keep checking them, cycling over everyone only when we lose our mark.
|
||||
|
||||
for(var/mob/Player in GLOB.living_mob_list)
|
||||
for(var/mob/Player in GLOB.alive_mob_list)
|
||||
if(Player.mind && Player.stat != DEAD && !isnewplayer(Player) &&!isbrain(Player) && Player.client)
|
||||
if(Player.mind.special_role || LAZYLEN(Player.mind.antag_datums)) //Someone's still antaging!
|
||||
living_antag_player = Player
|
||||
@@ -407,16 +407,11 @@
|
||||
//////////////////////////
|
||||
/proc/display_roundstart_logout_report()
|
||||
var/msg = "<span class='boldnotice'>Roundstart logout report\n\n</span>"
|
||||
for(var/mob/living/L in GLOB.mob_list)
|
||||
for(var/i in GLOB.mob_living_list)
|
||||
var/mob/living/L = i
|
||||
|
||||
if(L.ckey)
|
||||
var/found = 0
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(C.ckey == L.ckey)
|
||||
found = 1
|
||||
break
|
||||
if(!found)
|
||||
msg += "<b>[L.name]</b> ([L.ckey]), the [L.job] (<font color='#ffcc00'><b>Disconnected</b></font>)\n"
|
||||
if(L.ckey && !GLOB.directory[L.ckey])
|
||||
msg += "<b>[L.name]</b> ([L.ckey]), the [L.job] (<font color='#ffcc00'><b>Disconnected</b></font>)\n"
|
||||
|
||||
|
||||
if(L.ckey && L.client)
|
||||
@@ -452,10 +447,8 @@
|
||||
continue //Ghosted while alive
|
||||
|
||||
|
||||
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
if(M.client && M.client.holder)
|
||||
to_chat(M, msg)
|
||||
for (var/C in GLOB.admins)
|
||||
to_chat(C, msg)
|
||||
|
||||
/datum/game_mode/proc/printplayer(datum/mind/ply, fleecheck)
|
||||
var/text = "<br><b>[ply.key]</b> was <b>[ply.name]</b> the <b>[ply.assigned_role]</b> and"
|
||||
@@ -464,8 +457,10 @@
|
||||
text += " <span class='boldannounce'>died</span>"
|
||||
else
|
||||
text += " <span class='greenannounce'>survived</span>"
|
||||
if(fleecheck && (!(ply.current.z in GLOB.station_z_levels)))
|
||||
text += " while <span class='boldannounce'>fleeing the station</span>"
|
||||
if(fleecheck)
|
||||
var/turf/T = get_turf(ply.current)
|
||||
if(!T || !(T.z in GLOB.station_z_levels))
|
||||
text += " while <span class='boldannounce'>fleeing the station</span>"
|
||||
if(ply.current.real_name != ply.name)
|
||||
text += " as <b>[ply.current.real_name]</b>"
|
||||
else
|
||||
@@ -533,4 +528,4 @@
|
||||
//By default nuke just ends the round
|
||||
/datum/game_mode/proc/OnNukeExplosion(off_station)
|
||||
if(off_station < 2)
|
||||
station_was_nuked = TRUE //Will end the round on next check.
|
||||
station_was_nuked = TRUE //Will end the round on next check.
|
||||
|
||||
@@ -133,9 +133,9 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
dat += "<B>Install Module:</B><BR>"
|
||||
dat += "<I>The number afterwards is the amount of processing time it consumes.</I><BR>"
|
||||
for(var/datum/AI_Module/large/module in possible_modules)
|
||||
dat += "<A href='byond://?src=\ref[src];[module.mod_pick_name]=1'>[module.module_name]</A><A href='byond://?src=\ref[src];showdesc=[module.mod_pick_name]'>\[?\]</A> ([module.cost])<BR>"
|
||||
dat += "<A href='byond://?src=[REF(src)];[module.mod_pick_name]=1'>[module.module_name]</A><A href='byond://?src=[REF(src)];showdesc=[module.mod_pick_name]'>\[?\]</A> ([module.cost])<BR>"
|
||||
for(var/datum/AI_Module/small/module in possible_modules)
|
||||
dat += "<A href='byond://?src=\ref[src];[module.mod_pick_name]=1'>[module.module_name]</A><A href='byond://?src=\ref[src];showdesc=[module.mod_pick_name]'>\[?\]</A> ([module.cost])<BR>"
|
||||
dat += "<A href='byond://?src=[REF(src)];[module.mod_pick_name]=1'>[module.module_name]</A><A href='byond://?src=[REF(src)];showdesc=[module.mod_pick_name]'>\[?\]</A> ([module.cost])<BR>"
|
||||
dat += "<HR>"
|
||||
if(temp)
|
||||
dat += "[temp]"
|
||||
@@ -375,7 +375,8 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
/obj/machinery/doomsday_device/proc/detonate(z_level = ZLEVEL_STATION_PRIMARY)
|
||||
sound_to_playing_players('sound/machines/alarm.ogg')
|
||||
sleep(100)
|
||||
for(var/mob/living/L in GLOB.mob_list)
|
||||
for(var/i in GLOB.mob_living_list)
|
||||
var/mob/living/L = i
|
||||
var/turf/T = get_turf(L)
|
||||
if(!T || !(T.z in GLOB.station_z_levels))
|
||||
continue
|
||||
@@ -679,7 +680,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
C.images -= I
|
||||
|
||||
/mob/living/silicon/ai/proc/can_place_transformer(datum/action/innate/ai/place_transformer/action)
|
||||
if(!eyeobj || !isturf(loc) || !canUseTopic() || !action)
|
||||
if(!eyeobj || !isturf(loc) || incapacitated() || !action)
|
||||
return
|
||||
var/turf/middle = get_turf(eyeobj)
|
||||
var/list/turfs = list(middle, locate(middle.x - 1, middle.y, middle.z), locate(middle.x + 1, middle.y, middle.z))
|
||||
|
||||
@@ -477,7 +477,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
species = "<span class='notice'>[H.dna.species.name]</span>"
|
||||
if(L.mind && L.mind.changeling)
|
||||
if(L.mind && L.mind.has_antag_datum(/datum/antagonist/changeling))
|
||||
species = "<span class='warning'>Changeling lifeform</span>"
|
||||
var/obj/item/organ/heart/gland/temp = locate() in H.internal_organs
|
||||
if(temp)
|
||||
|
||||
@@ -43,20 +43,20 @@
|
||||
dat += "Collected Samples : [points] <br>"
|
||||
dat += "Gear Credits: [credits] <br>"
|
||||
dat += "<b>Transfer data in exchange for supplies:</b><br>"
|
||||
dat += "<a href='?src=\ref[src];dispense=baton'>Advanced Baton</A><br>"
|
||||
dat += "<a href='?src=\ref[src];dispense=helmet'>Agent Helmet</A><br>"
|
||||
dat += "<a href='?src=\ref[src];dispense=vest'>Agent Vest</A><br>"
|
||||
dat += "<a href='?src=\ref[src];dispense=silencer'>Radio Silencer</A><br>"
|
||||
dat += "<a href='?src=\ref[src];dispense=tool'>Science Tool</A><br>"
|
||||
dat += "<a href='?src=[REF(src)];dispense=baton'>Advanced Baton</A><br>"
|
||||
dat += "<a href='?src=[REF(src)];dispense=helmet'>Agent Helmet</A><br>"
|
||||
dat += "<a href='?src=[REF(src)];dispense=vest'>Agent Vest</A><br>"
|
||||
dat += "<a href='?src=[REF(src)];dispense=silencer'>Radio Silencer</A><br>"
|
||||
dat += "<a href='?src=[REF(src)];dispense=tool'>Science Tool</A><br>"
|
||||
else
|
||||
dat += "<span class='bad'>NO EXPERIMENT MACHINE DETECTED</span> <br>"
|
||||
|
||||
if(pad)
|
||||
dat += "<span class='bad'>Emergency Teleporter System.</span>"
|
||||
dat += "<span class='bad'>Consider using primary observation console first.</span>"
|
||||
dat += "<a href='?src=\ref[src];teleporter_send=1'>Activate Teleporter</A><br>"
|
||||
dat += "<a href='?src=[REF(src)];teleporter_send=1'>Activate Teleporter</A><br>"
|
||||
if(gizmo && gizmo.marked)
|
||||
dat += "<a href='?src=\ref[src];teleporter_retrieve=1'>Retrieve Mark</A><br>"
|
||||
dat += "<a href='?src=[REF(src)];teleporter_retrieve=1'>Retrieve Mark</A><br>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Retrieve Mark</span><br>"
|
||||
else
|
||||
@@ -66,15 +66,15 @@
|
||||
dat += "<h4> Agent Vest Mode </h4><br>"
|
||||
var/mode = vest.mode
|
||||
if(mode == VEST_STEALTH)
|
||||
dat += "<a href='?src=\ref[src];flip_vest=1'>Combat</A>"
|
||||
dat += "<a href='?src=[REF(src)];flip_vest=1'>Combat</A>"
|
||||
dat += "<span class='linkOff'>Stealth</span>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Combat</span>"
|
||||
dat += "<a href='?src=\ref[src];flip_vest=1'>Stealth</A>"
|
||||
dat += "<a href='?src=[REF(src)];flip_vest=1'>Stealth</A>"
|
||||
|
||||
dat+="<br>"
|
||||
dat += "<a href='?src=\ref[src];select_disguise=1'>Select Agent Vest Disguise</a><br>"
|
||||
dat += "<a href='?src=\ref[src];toggle_vest=1'>[vest.flags_1 & NODROP_1 ? "Unlock" : "Lock"] Vest</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];select_disguise=1'>Select Agent Vest Disguise</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];toggle_vest=1'>[vest.flags_1 & NODROP_1 ? "Unlock" : "Lock"] Vest</a><br>"
|
||||
else
|
||||
dat += "<span class='bad'>NO AGENT VEST DETECTED</span>"
|
||||
var/datum/browser/popup = new(user, "computer", "Abductor Console", 400, 500)
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
item_count++
|
||||
var/g_color = gland_colors[i]
|
||||
var/amount = amounts[i]
|
||||
dat += "<a class='box gland' style='background-color:[g_color]' href='?src=\ref[src];dispense=[i]'>[amount]</a>"
|
||||
dat += "<a class='box gland' style='background-color:[g_color]' href='?src=[REF(src)];dispense=[i]'>[amount]</a>"
|
||||
if(item_count == 4) // Four boxes per line
|
||||
dat +="</br></br>"
|
||||
item_count = 0
|
||||
|
||||
@@ -104,9 +104,9 @@
|
||||
dat += "<table><tr><td>"
|
||||
dat += "<img src=dissection_img height=80 width=80>" //Avert your eyes
|
||||
dat += "</td><td>"
|
||||
dat += "<a href='?src=\ref[src];experiment=1'>Probe</a><br>"
|
||||
dat += "<a href='?src=\ref[src];experiment=2'>Dissect</a><br>"
|
||||
dat += "<a href='?src=\ref[src];experiment=3'>Analyze</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];experiment=1'>Probe</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];experiment=2'>Dissect</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];experiment=3'>Analyze</a><br>"
|
||||
dat += "</td></tr></table>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Experiment </span>"
|
||||
@@ -127,8 +127,8 @@
|
||||
dat += "<br>"
|
||||
dat += "[flash]"
|
||||
dat += "<br>"
|
||||
dat += "<a href='?src=\ref[src];refresh=1'>Scan</a>"
|
||||
dat += "<a href='?src=\ref[src];[state_open ? "close=1'>Close</a>" : "open=1'>Open</a>"]"
|
||||
dat += "<a href='?src=[REF(src)];refresh=1'>Scan</a>"
|
||||
dat += "<a href='?src=[REF(src)];[state_open ? "close=1'>Close</a>" : "open=1'>Open</a>"]"
|
||||
var/datum/browser/popup = new(user, "experiment", "Probing Console", 300, 300)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.set_content(dat)
|
||||
|
||||
@@ -654,7 +654,8 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/swarmer/proc/swarmer_chat(msg)
|
||||
var/rendered = "<B>Swarm communication - [src]</b> [say_quote(msg, get_spans())]"
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
for(var/i in GLOB.mob_list)
|
||||
var/mob/M = i
|
||||
if(isswarmer(M))
|
||||
to_chat(M, rendered)
|
||||
if(isobserver(M))
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
print_command_report(swarmer_report, announce=TRUE)
|
||||
|
||||
/datum/round_event/spawn_swarmer/proc/find_swarmer()
|
||||
for(var/mob/living/M in GLOB.mob_list)
|
||||
if(istype(M, /mob/living/simple_animal/hostile/swarmer) && M.client) //If there is a swarmer with an active client, we've found our swarmer
|
||||
for(var/i in GLOB.mob_living_list)
|
||||
var/mob/living/L = i
|
||||
if(istype(L, /mob/living/simple_animal/hostile/swarmer) && L.client) //If there is a swarmer with an active client, we've found our swarmer
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
return 0
|
||||
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever() //ugly but unfortunately needed
|
||||
for(var/mob/living/carbon/human/H in GLOB.living_mob_list)
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
if(H.mind && H.stat != DEAD)
|
||||
if(H.HasDisease(D))
|
||||
return 0
|
||||
@@ -87,7 +87,7 @@
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_ENDGAME)
|
||||
return 0
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever()
|
||||
for(var/mob/living/carbon/monkey/M in GLOB.living_mob_list)
|
||||
for(var/mob/living/carbon/monkey/M in GLOB.alive_mob_list)
|
||||
if (M.HasDisease(D))
|
||||
if(M.onCentCom() || M.onSyndieBase())
|
||||
escaped_monkeys++
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
maxHealth = INFINITY
|
||||
layer = GHOST_LAYER
|
||||
healable = FALSE
|
||||
spacewalk = TRUE
|
||||
sight = SEE_SELF
|
||||
|
||||
see_in_dark = 8
|
||||
@@ -153,8 +154,6 @@
|
||||
|
||||
|
||||
//Immunities
|
||||
/mob/living/simple_animal/revenant/Process_Spacemove(movement_dir = 0)
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/revenant/ex_act(severity, target)
|
||||
return 1 //Immune to the effects of explosions.
|
||||
|
||||
@@ -91,9 +91,11 @@
|
||||
var/obj/item/device/nuclear_challenge/challenge = new /obj/item/device/nuclear_challenge
|
||||
synd_mind.current.put_in_hands(challenge, TRUE)
|
||||
|
||||
var/list/foundIDs = synd_mind.current.search_contents_for(/obj/item/card/id)
|
||||
var/static/id_cache = typecacheof(/obj/item/card/id)
|
||||
var/list/foundIDs = typecache_filter_list(synd_mind.current.GetAllContents(), id_cache)
|
||||
if(foundIDs.len)
|
||||
for(var/obj/item/card/id/ID in foundIDs)
|
||||
for(var/i in 1 to foundIDs.len)
|
||||
var/obj/item/card/id/ID = foundIDs[i]
|
||||
ID.name = "lead agent card"
|
||||
ID.access += ACCESS_SYNDICATE_LEADER
|
||||
else
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
icon = 'icons/obj/machines/nuke_terminal.dmi'
|
||||
icon_state = "nuclearbomb_base"
|
||||
anchored = TRUE //stops it being moved
|
||||
use_tag = TRUE
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate
|
||||
//ui_style = "syndicate" // actually the nuke op bomb is a stole nt bomb
|
||||
@@ -121,15 +122,7 @@
|
||||
to_chat(user, "<span class='notice'>You remove the screws from [src]'s front panel.</span>")
|
||||
update_icon()
|
||||
return
|
||||
if(NUKESTATE_UNSCREWED)
|
||||
if(istype(I, /obj/item/crowbar))
|
||||
to_chat(user, "<span class='notice'>You start removing [src]'s front panel...</span>")
|
||||
playsound(loc, I.usesound, 100, 1)
|
||||
if(do_after(user,30*I.toolspeed,target=src))
|
||||
to_chat(user, "<span class='notice'>You remove [src]'s front panel.</span>")
|
||||
deconstruction_state = NUKESTATE_PANEL_REMOVED
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(NUKESTATE_PANEL_REMOVED)
|
||||
if(istype(I, /obj/item/weldingtool))
|
||||
var/obj/item/weldingtool/welder = I
|
||||
@@ -141,16 +134,6 @@
|
||||
deconstruction_state = NUKESTATE_WELDED
|
||||
update_icon()
|
||||
return
|
||||
if(NUKESTATE_WELDED)
|
||||
if(istype(I, /obj/item/crowbar))
|
||||
to_chat(user, "<span class='notice'>You start prying off [src]'s inner plate...</span>")
|
||||
playsound(loc, I.usesound, 100, 1)
|
||||
if(do_after(user,50*I.toolspeed,target=src))
|
||||
to_chat(user, "<span class='notice'>You pry off [src]'s inner plate. You can see the core's green glow!</span>")
|
||||
deconstruction_state = NUKESTATE_CORE_EXPOSED
|
||||
update_icon()
|
||||
START_PROCESSING(SSobj, core)
|
||||
return
|
||||
if(NUKESTATE_CORE_EXPOSED)
|
||||
if(istype(I, /obj/item/nuke_core_container))
|
||||
var/obj/item/nuke_core_container/core_box = I
|
||||
@@ -181,6 +164,27 @@
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/nuclearbomb/crowbar_act(mob/user, obj/item/tool)
|
||||
. = FALSE
|
||||
switch(deconstruction_state)
|
||||
if(NUKESTATE_UNSCREWED)
|
||||
to_chat(user, "<span class='notice'>You start removing [src]'s front panel...</span>")
|
||||
playsound(loc, tool.usesound, 100, 1)
|
||||
if(do_after(user, 30 * tool.toolspeed, target = src))
|
||||
to_chat(user, "<span class='notice'>You remove [src]'s front panel.</span>")
|
||||
deconstruction_state = NUKESTATE_PANEL_REMOVED
|
||||
update_icon()
|
||||
return TRUE
|
||||
if(NUKESTATE_WELDED)
|
||||
to_chat(user, "<span class='notice'>You start prying off [src]'s inner plate...</span>")
|
||||
playsound(loc, tool.usesound, 100, 1)
|
||||
if(do_after(user, 50 * tool.toolspeed, target = src))
|
||||
to_chat(user, "<span class='notice'>You pry off [src]'s inner plate. You can see the core's green glow!</span>")
|
||||
deconstruction_state = NUKESTATE_CORE_EXPOSED
|
||||
update_icon()
|
||||
START_PROCESSING(SSobj, core)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/get_nuke_state()
|
||||
if(exploding)
|
||||
return NUKE_ON_EXPLODING
|
||||
|
||||
@@ -586,7 +586,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
n_p ++
|
||||
else if (SSticker.IsRoundInProgress())
|
||||
for(var/mob/living/carbon/human/P in GLOB.player_list)
|
||||
if(P.client && !(P.mind in SSticker.mode.changelings) && !(P.mind in owners))
|
||||
if(P.client && !(P.mind.has_antag_datum(/datum/antagonist/changeling)) && !(P.mind in owners))
|
||||
n_p ++
|
||||
target_amount = min(target_amount, n_p)
|
||||
|
||||
@@ -597,9 +597,12 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
var/list/datum/mind/owners = get_owners()
|
||||
var/absorbedcount = 0
|
||||
for(var/datum/mind/M in owners)
|
||||
if(!owner || !owner.changeling || !owner.changeling.stored_profiles)
|
||||
if(!M)
|
||||
continue
|
||||
absorbedcount += M.changeling.absorbedcount
|
||||
var/datum/antagonist/changeling/changeling = M.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(!changeling || !changeling.stored_profiles)
|
||||
continue
|
||||
absorbedcount += changeling.absorbedcount
|
||||
return absorbedcount >= target_amount
|
||||
|
||||
|
||||
@@ -696,10 +699,11 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
if("Chief Medical Officer")
|
||||
department_string = "medical"
|
||||
|
||||
var/ling_count = SSticker.mode.changelings
|
||||
var/list/lings = get_antagonists(/datum/antagonist/changeling,TRUE)
|
||||
var/ling_count = lings.len
|
||||
|
||||
for(var/datum/mind/M in SSticker.minds)
|
||||
if(M in SSticker.mode.changelings)
|
||||
if(M in lings)
|
||||
continue
|
||||
if(department_head in get_department_heads(M.assigned_role))
|
||||
if(ling_count)
|
||||
@@ -723,13 +727,13 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
//Needed heads is between min_lings and the maximum possible amount of command roles
|
||||
//So at the time of writing, rand(3,6), it's also capped by the amount of lings there are
|
||||
//Because you can't fill 6 head roles with 3 lings
|
||||
|
||||
var/list/lings = get_antagonists(/datum/antagonist/changeling,TRUE)
|
||||
var/needed_heads = rand(min_lings,GLOB.command_positions.len)
|
||||
needed_heads = min(SSticker.mode.changelings.len,needed_heads)
|
||||
needed_heads = min(lings.len,needed_heads)
|
||||
|
||||
var/list/heads = SSjob.get_living_heads()
|
||||
for(var/datum/mind/head in heads)
|
||||
if(head in SSticker.mode.changelings) //Looking at you HoP.
|
||||
if(head in lings) //Looking at you HoP.
|
||||
continue
|
||||
if(needed_heads)
|
||||
department_minds += head
|
||||
@@ -789,7 +793,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
|
||||
//Check each department member's mind to see if any of them made it to centcom alive, if they did it's an automatic fail
|
||||
for(var/datum/mind/M in department_minds)
|
||||
if(M in SSticker.mode.changelings) //Lings aren't picked for this, but let's be safe
|
||||
if(M.has_antag_datum(/datum/antagonist/changeling)) //Lings aren't picked for this, but let's be safe
|
||||
continue
|
||||
|
||||
if(M.current)
|
||||
@@ -800,7 +804,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
//Check each staff member has been replaced, by cross referencing changeling minds, changeling current dna, the staff minds and their original DNA names
|
||||
var/success = 0
|
||||
changelings:
|
||||
for(var/datum/mind/changeling in SSticker.mode.changelings)
|
||||
for(var/datum/mind/changeling in get_antagonists(/datum/antagonist/changeling,TRUE))
|
||||
if(success >= department_minds.len) //We did it, stop here!
|
||||
return 1
|
||||
if(ishuman(changeling.current))
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
if(headrevs.len)
|
||||
var/num_revs = 0
|
||||
var/num_survivors = 0
|
||||
for(var/mob/living/carbon/survivor in GLOB.living_mob_list)
|
||||
for(var/mob/living/carbon/survivor in GLOB.alive_mob_list)
|
||||
if(survivor.ckey)
|
||||
num_survivors++
|
||||
if(survivor.mind)
|
||||
|
||||
@@ -1,139 +1,139 @@
|
||||
/*
|
||||
This is for the sandbox for now,
|
||||
maybe useful later for an actual thing?
|
||||
-Sayu
|
||||
*/
|
||||
|
||||
/obj/structure/door_assembly
|
||||
var/datum/airlock_maker/maker = null
|
||||
|
||||
/obj/structure/door_assembly/attack_hand()
|
||||
..()
|
||||
if(maker)
|
||||
maker.interact()
|
||||
|
||||
/datum/airlock_maker
|
||||
var/obj/structure/door_assembly/linked = null
|
||||
|
||||
var/list/access_used = null
|
||||
var/require_all = 1
|
||||
|
||||
var/paintjob = "none"
|
||||
var/glassdoor = 0
|
||||
|
||||
var/doorname = "airlock"
|
||||
|
||||
/datum/airlock_maker/New(var/atom/target_loc)
|
||||
linked = new(target_loc)
|
||||
linked.maker = src
|
||||
linked.anchored = FALSE
|
||||
access_used = list()
|
||||
|
||||
interact()
|
||||
|
||||
/datum/airlock_maker/proc/linkpretty(href,desc,active)
|
||||
if(!desc)
|
||||
var/static/list/defaults = list("No","Yes")
|
||||
desc = defaults[active+1]
|
||||
if(active)
|
||||
return "<a href='?src=\ref[src];[href]'><b>[desc]</b></a>"
|
||||
return "<a href='?src=\ref[src];[href]'><i>[desc]</i></a>"
|
||||
|
||||
/datum/airlock_maker/proc/interact()
|
||||
var/list/leftcolumn = list()
|
||||
var/list/rightcolumn = list()
|
||||
leftcolumn += "<u><b>Required Access</b></u>"
|
||||
for(var/access in get_all_accesses())
|
||||
leftcolumn += linkpretty("access=[access]",get_access_desc(access),access in access_used)
|
||||
leftcolumn += "Require all listed accesses: [linkpretty("reqall",null,require_all)]"
|
||||
|
||||
rightcolumn += "<u><b>Paintjob</b></u>"
|
||||
for(var/option in list("none","engineering","atmos","security","command","medical","research","mining","maintenance","external","highsecurity"))
|
||||
rightcolumn += linkpretty("paint=[option]",option,option == paintjob)
|
||||
rightcolumn += "Glass door: " + linkpretty("glass",null,glassdoor) + "<br><br>"
|
||||
var/length = max(leftcolumn.len,rightcolumn.len)
|
||||
|
||||
var/dat = "You may move the model airlock around. A new airlock will be built in its space when you click done, below.<hr><br>"
|
||||
dat += "<a href='?src=\ref[src];rename'>Door name</a>: \"[doorname]\""
|
||||
dat += "<table>"
|
||||
for(var/i=1; i<=length; i++)
|
||||
dat += "<tr><td>"
|
||||
if(i<=leftcolumn.len)
|
||||
dat += leftcolumn[i]
|
||||
dat += "</td><td>"
|
||||
if(i<=rightcolumn.len)
|
||||
dat += rightcolumn[i]
|
||||
dat += "</td></tr>"
|
||||
|
||||
dat += "</table><hr><a href='?src=\ref[src];done'>Finalize Airlock Construction</a> | <a href='?src=\ref[src];cancel'>Cancel and Destroy Airlock</a>"
|
||||
usr << browse(dat,"window=airlockmaker")
|
||||
|
||||
/datum/airlock_maker/Topic(var/href,var/list/href_list)
|
||||
if(!usr)
|
||||
return
|
||||
if(!src || !linked || !linked.loc)
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
return
|
||||
|
||||
if("rename" in href_list)
|
||||
var/newname = stripped_input(usr,"New airlock name:","Name the airlock",doorname)
|
||||
if(newname)
|
||||
doorname = newname
|
||||
if("access" in href_list)
|
||||
var/value = text2num(href_list["access"])
|
||||
access_used ^= value
|
||||
if("reqall" in href_list)
|
||||
require_all = !require_all
|
||||
if("paint" in href_list)
|
||||
paintjob = href_list["paint"]
|
||||
if("glass" in href_list)
|
||||
glassdoor = !glassdoor
|
||||
|
||||
if("cancel" in href_list)
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
qdel(linked)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if("done" in href_list)
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
var/turf/t_loc = linked.loc
|
||||
qdel(linked)
|
||||
if(!istype(t_loc))
|
||||
return
|
||||
|
||||
var/target_type = "/obj/machinery/door/airlock"
|
||||
if(glassdoor)
|
||||
if(paintjob != "none")
|
||||
if(paintjob in list("external","highsecurity","maintenance")) // no glass version
|
||||
target_type += "/[paintjob]"
|
||||
else
|
||||
target_type += "/glass_[paintjob]"
|
||||
else
|
||||
target_type += "/glass"
|
||||
else if(paintjob != "none")
|
||||
target_type += "/[paintjob]"
|
||||
var/final = target_type
|
||||
target_type = text2path(final)
|
||||
if(!target_type)
|
||||
to_chat(usr, "Didn't work, contact Sayu with this: [final]")
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
return
|
||||
|
||||
var/obj/machinery/door/D = new target_type(t_loc)
|
||||
|
||||
D.name = doorname
|
||||
|
||||
if(access_used.len == 0)
|
||||
D.req_access = null
|
||||
D.req_one_access = null
|
||||
else if(require_all)
|
||||
D.req_access = access_used.Copy()
|
||||
D.req_one_access = null
|
||||
else
|
||||
D.req_access = null
|
||||
D.req_one_access = access_used.Copy()
|
||||
|
||||
return
|
||||
|
||||
interact()
|
||||
/*
|
||||
This is for the sandbox for now,
|
||||
maybe useful later for an actual thing?
|
||||
-Sayu
|
||||
*/
|
||||
|
||||
/obj/structure/door_assembly
|
||||
var/datum/airlock_maker/maker = null
|
||||
|
||||
/obj/structure/door_assembly/attack_hand()
|
||||
..()
|
||||
if(maker)
|
||||
maker.interact()
|
||||
|
||||
/datum/airlock_maker
|
||||
var/obj/structure/door_assembly/linked = null
|
||||
|
||||
var/list/access_used = null
|
||||
var/require_all = 1
|
||||
|
||||
var/paintjob = "none"
|
||||
var/glassdoor = 0
|
||||
|
||||
var/doorname = "airlock"
|
||||
|
||||
/datum/airlock_maker/New(var/atom/target_loc)
|
||||
linked = new(target_loc)
|
||||
linked.maker = src
|
||||
linked.anchored = FALSE
|
||||
access_used = list()
|
||||
|
||||
interact()
|
||||
|
||||
/datum/airlock_maker/proc/linkpretty(href,desc,active)
|
||||
if(!desc)
|
||||
var/static/list/defaults = list("No","Yes")
|
||||
desc = defaults[active+1]
|
||||
if(active)
|
||||
return "<a href='?src=[REF(src)];[href]'><b>[desc]</b></a>"
|
||||
return "<a href='?src=[REF(src)];[href]'><i>[desc]</i></a>"
|
||||
|
||||
/datum/airlock_maker/proc/interact()
|
||||
var/list/leftcolumn = list()
|
||||
var/list/rightcolumn = list()
|
||||
leftcolumn += "<u><b>Required Access</b></u>"
|
||||
for(var/access in get_all_accesses())
|
||||
leftcolumn += linkpretty("access=[access]",get_access_desc(access),access in access_used)
|
||||
leftcolumn += "Require all listed accesses: [linkpretty("reqall",null,require_all)]"
|
||||
|
||||
rightcolumn += "<u><b>Paintjob</b></u>"
|
||||
for(var/option in list("none","engineering","atmos","security","command","medical","research","mining","maintenance","external","highsecurity"))
|
||||
rightcolumn += linkpretty("paint=[option]",option,option == paintjob)
|
||||
rightcolumn += "Glass door: " + linkpretty("glass",null,glassdoor) + "<br><br>"
|
||||
var/length = max(leftcolumn.len,rightcolumn.len)
|
||||
|
||||
var/dat = "You may move the model airlock around. A new airlock will be built in its space when you click done, below.<hr><br>"
|
||||
dat += "<a href='?src=[REF(src)];rename'>Door name</a>: \"[doorname]\""
|
||||
dat += "<table>"
|
||||
for(var/i=1; i<=length; i++)
|
||||
dat += "<tr><td>"
|
||||
if(i<=leftcolumn.len)
|
||||
dat += leftcolumn[i]
|
||||
dat += "</td><td>"
|
||||
if(i<=rightcolumn.len)
|
||||
dat += rightcolumn[i]
|
||||
dat += "</td></tr>"
|
||||
|
||||
dat += "</table><hr><a href='?src=[REF(src)];done'>Finalize Airlock Construction</a> | <a href='?src=[REF(src)];cancel'>Cancel and Destroy Airlock</a>"
|
||||
usr << browse(dat,"window=airlockmaker")
|
||||
|
||||
/datum/airlock_maker/Topic(var/href,var/list/href_list)
|
||||
if(!usr)
|
||||
return
|
||||
if(!src || !linked || !linked.loc)
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
return
|
||||
|
||||
if("rename" in href_list)
|
||||
var/newname = stripped_input(usr,"New airlock name:","Name the airlock",doorname)
|
||||
if(newname)
|
||||
doorname = newname
|
||||
if("access" in href_list)
|
||||
var/value = text2num(href_list["access"])
|
||||
access_used ^= value
|
||||
if("reqall" in href_list)
|
||||
require_all = !require_all
|
||||
if("paint" in href_list)
|
||||
paintjob = href_list["paint"]
|
||||
if("glass" in href_list)
|
||||
glassdoor = !glassdoor
|
||||
|
||||
if("cancel" in href_list)
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
qdel(linked)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if("done" in href_list)
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
var/turf/t_loc = linked.loc
|
||||
qdel(linked)
|
||||
if(!istype(t_loc))
|
||||
return
|
||||
|
||||
var/target_type = "/obj/machinery/door/airlock"
|
||||
if(glassdoor)
|
||||
if(paintjob != "none")
|
||||
if(paintjob in list("external","highsecurity","maintenance")) // no glass version
|
||||
target_type += "/[paintjob]"
|
||||
else
|
||||
target_type += "/glass_[paintjob]"
|
||||
else
|
||||
target_type += "/glass"
|
||||
else if(paintjob != "none")
|
||||
target_type += "/[paintjob]"
|
||||
var/final = target_type
|
||||
target_type = text2path(final)
|
||||
if(!target_type)
|
||||
to_chat(usr, "Didn't work, contact Sayu with this: [final]")
|
||||
usr << browse(null,"window=airlockmaker")
|
||||
return
|
||||
|
||||
var/obj/machinery/door/D = new target_type(t_loc)
|
||||
|
||||
D.name = doorname
|
||||
|
||||
if(access_used.len == 0)
|
||||
D.req_access = null
|
||||
D.req_one_access = null
|
||||
else if(require_all)
|
||||
D.req_access = access_used.Copy()
|
||||
D.req_one_access = null
|
||||
else
|
||||
D.req_access = null
|
||||
D.req_one_access = access_used.Copy()
|
||||
|
||||
return
|
||||
|
||||
interact()
|
||||
|
||||
@@ -77,26 +77,26 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE)
|
||||
hsbinfo = "<center><b>Sandbox Panel</b></center><hr>"
|
||||
if(admin)
|
||||
hsbinfo += "<b>Administration</b><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbtobj'>Toggle Object Spawning</a><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbtac'>Toggle Item Spawn Panel Auto-close</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbtobj'>Toggle Object Spawning</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbtac'>Toggle Item Spawn Panel Auto-close</a><br>"
|
||||
hsbinfo += "<b>Canister Spawning</b><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/toxins]'>Spawn Plasma Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/carbon_dioxide]'>Spawn CO2 Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/nitrogen]'>Spawn Nitrogen Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=\ref[src];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/nitrous_oxide]'>Spawn N2O Canister</a><hr>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/toxins]'>Spawn Plasma Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/carbon_dioxide]'>Spawn CO2 Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/nitrogen]'>Spawn Nitrogen Canister</a><br>"
|
||||
hsbinfo += "- <a href='?src=[REF(src)];hsb=hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/nitrous_oxide]'>Spawn N2O Canister</a><hr>"
|
||||
else
|
||||
hsbinfo += "<i>Some item spawning may be disabled by the administrators.</i><br>"
|
||||
hsbinfo += "<i>Only administrators may spawn dangerous canisters.</i><br>"
|
||||
for(var/T in hrefs)
|
||||
var/href = hrefs[T]
|
||||
if(href)
|
||||
hsbinfo += "- <a href='?\ref[src];hsb=[hrefs[T]]'>[T]</a><br>"
|
||||
hsbinfo += "- <a href='?[REF(src)];hsb=[hrefs[T]]'>[T]</a><br>"
|
||||
else
|
||||
hsbinfo += "<br><b>[T]</b><br>"
|
||||
hsbinfo += "<hr>"
|
||||
hsbinfo += "- <a href='?\ref[src];hsb=hsbcloth'>Spawn Clothing...</a><br>"
|
||||
hsbinfo += "- <a href='?\ref[src];hsb=hsbreag'>Spawn Reagent Container...</a><br>"
|
||||
hsbinfo += "- <a href='?\ref[src];hsb=hsbobj'>Spawn Other Item...</a><br><br>"
|
||||
hsbinfo += "- <a href='?[REF(src)];hsb=hsbcloth'>Spawn Clothing...</a><br>"
|
||||
hsbinfo += "- <a href='?[REF(src)];hsb=hsbreag'>Spawn Reagent Container...</a><br>"
|
||||
hsbinfo += "- <a href='?[REF(src)];hsb=hsbobj'>Spawn Other Item...</a><br><br>"
|
||||
|
||||
usr << browse(hsbinfo, "window=hsbpanel")
|
||||
|
||||
@@ -235,12 +235,12 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE)
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!clothinfo)
|
||||
clothinfo = "<b>Clothing</b> <a href='?\ref[src];hsb=hsbreag'>(Reagent Containers)</a> <a href='?\ref[src];hsb=hsbobj'>(Other Items)</a><hr><br>"
|
||||
clothinfo = "<b>Clothing</b> <a href='?[REF(src)];hsb=hsbreag'>(Reagent Containers)</a> <a href='?[REF(src)];hsb=hsbobj'>(Other Items)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/clothing)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
for(var/O in reverseRange(all_items))
|
||||
clothinfo += "<a href='?src=\ref[src];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
clothinfo += "<a href='?src=[REF(src)];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(clothinfo,"window=sandbox")
|
||||
|
||||
@@ -249,12 +249,12 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE)
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!reaginfo)
|
||||
reaginfo = "<b>Reagent Containers</b> <a href='?\ref[src];hsb=hsbcloth'>(Clothing)</a> <a href='?\ref[src];hsb=hsbobj'>(Other Items)</a><hr><br>"
|
||||
reaginfo = "<b>Reagent Containers</b> <a href='?[REF(src)];hsb=hsbcloth'>(Clothing)</a> <a href='?[REF(src)];hsb=hsbobj'>(Other Items)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/reagent_containers)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
for(var/O in reverseRange(all_items))
|
||||
reaginfo += "<a href='?src=\ref[src];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
reaginfo += "<a href='?src=[REF(src)];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(reaginfo,"window=sandbox")
|
||||
|
||||
@@ -263,13 +263,13 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE)
|
||||
if(!GLOB.hsboxspawn) return
|
||||
|
||||
if(!objinfo)
|
||||
objinfo = "<b>Other Items</b> <a href='?\ref[src];hsb=hsbcloth'>(Clothing)</a> <a href='?\ref[src];hsb=hsbreag'>(Reagent Containers)</a><hr><br>"
|
||||
objinfo = "<b>Other Items</b> <a href='?[REF(src)];hsb=hsbcloth'>(Clothing)</a> <a href='?[REF(src)];hsb=hsbreag'>(Reagent Containers)</a><hr><br>"
|
||||
var/list/all_items = subtypesof(/obj/item/) - typesof(/obj/item/clothing) - typesof(/obj/item/reagent_containers)
|
||||
for(var/typekey in spawn_forbidden)
|
||||
all_items -= typesof(typekey)
|
||||
|
||||
for(var/O in reverseRange(all_items))
|
||||
objinfo += "<a href='?src=\ref[src];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
objinfo += "<a href='?src=[REF(src)];hsb=hsb_safespawn&path=[O]'>[O]</a><br>"
|
||||
|
||||
usr << browse(objinfo,"window=sandbox")
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
/datum/game_mode/traitor/proc/add_latejoin_traitor(datum/mind/character)
|
||||
var/datum/antagonist/traitor/new_antag = new antag_datum(character)
|
||||
new_antag.should_specialise = TRUE
|
||||
character.add_antag_datum(antag_datum)
|
||||
character.add_antag_datum(new_antag)
|
||||
|
||||
|
||||
|
||||
@@ -144,6 +144,7 @@
|
||||
else
|
||||
text += "<br><font color='red'><B>The [special_role_text] has failed!</B></font>"
|
||||
SSblackbox.add_details("traitor_success","FAIL")
|
||||
SEND_SOUND(traitor.current, 'sound/ambience/ambifailure.ogg')
|
||||
|
||||
text += "<br>"
|
||||
|
||||
|
||||
@@ -288,7 +288,7 @@
|
||||
possible = list()
|
||||
if(!link)
|
||||
return
|
||||
for(var/mob/living/carbon/human/H in GLOB.living_mob_list)
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
if(md5(H.dna.uni_identity) in link.fingerprints)
|
||||
possible |= H
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
/proc/makeNewConstruct(mob/living/simple_animal/hostile/construct/ctype, mob/target, mob/stoner = null, cultoverride = 0, loc_override = null)
|
||||
var/mob/living/simple_animal/hostile/construct/newstruct = new ctype((loc_override) ? (loc_override) : (get_turf(target)))
|
||||
if(stoner)
|
||||
newstruct.faction |= "\ref[stoner]"
|
||||
newstruct.faction |= "[REF(stoner)]"
|
||||
newstruct.master = stoner
|
||||
var/datum/action/innate/seek_master/SM = new()
|
||||
SM.Grant(newstruct)
|
||||
@@ -244,7 +244,7 @@
|
||||
S.key = T.key
|
||||
S.language_holder = U.language_holder.copy(S)
|
||||
if(U)
|
||||
S.faction |= "\ref[U]" //Add the master as a faction, allowing inter-mob cooperation
|
||||
S.faction |= "[REF(U)]" //Add the master as a faction, allowing inter-mob cooperation
|
||||
if(U && iscultist(U))
|
||||
SSticker.mode.add_cultist(S.mind, 0)
|
||||
S.cancel_camera()
|
||||
|
||||
@@ -425,7 +425,7 @@
|
||||
|
||||
/datum/spellbook_entry/item/warpwhistle
|
||||
name = "Warp Whistle"
|
||||
desc = "A strange whistle that will transport you to a distant safe place on the station. There is a window of vulnerability at the begining of every use."
|
||||
desc = "A strange whistle that will transport you to a distant safe place on the station. There is a window of vulnerability at the beginning of every use."
|
||||
item_path = /obj/item/warpwhistle
|
||||
category = "Mobility"
|
||||
cost = 1
|
||||
@@ -652,7 +652,7 @@
|
||||
var/list/cat_dat = list()
|
||||
for(var/category in categories)
|
||||
cat_dat[category] = "<hr>"
|
||||
dat += "<li><a [tab==category?"class=selected":""] href='byond://?src=\ref[src];page=[category]'>[category]</a></li>"
|
||||
dat += "<li><a [tab==category?"class=selected":""] href='byond://?src=[REF(src)];page=[category]'>[category]</a></li>"
|
||||
|
||||
dat += "<li><a><b>Points remaining : [uses]</b></a></li>"
|
||||
dat += "</ul>"
|
||||
@@ -663,11 +663,11 @@
|
||||
E = entries[i]
|
||||
spell_info += E.GetInfo()
|
||||
if(E.CanBuy(user,src))
|
||||
spell_info+= "<a href='byond://?src=\ref[src];buy=[i]'>[E.buy_word]</A><br>"
|
||||
spell_info+= "<a href='byond://?src=[REF(src)];buy=[i]'>[E.buy_word]</A><br>"
|
||||
else
|
||||
spell_info+= "<span>Can't [E.buy_word]</span><br>"
|
||||
if(E.CanRefund(user,src))
|
||||
spell_info+= "<a href='byond://?src=\ref[src];refund=[i]'>Refund</A><br>"
|
||||
spell_info+= "<a href='byond://?src=[REF(src)];refund=[i]'>Refund</A><br>"
|
||||
spell_info += "<hr>"
|
||||
if(cat_dat[E.category])
|
||||
cat_dat[E.category] += spell_info
|
||||
|
||||
Reference in New Issue
Block a user