Merge branch 'master' into Spookytime

This commit is contained in:
Fermi
2019-10-11 19:10:48 +01:00
126 changed files with 56362 additions and 55928 deletions

View File

@@ -121,8 +121,13 @@
#define COMSIG_MOVABLE_HEAR "movable_hear" //from base of atom/movable/Hear(): (message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
#define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source)
// /mind signals
#define COMSIG_MIND_TRANSFER "mind_transfer" //from base of mind/transfer_to(): (new_character, old_character)
// /mob signals
#define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed)
#define COMSIG_MOB_GHOSTIZE "mob_ghostize" //from base of mob/Ghostize() (can_reenter_corpse)
#define COMPONENT_BLOCK_GHOSTING 1
#define COMSIG_MOB_ALLOWED "mob_allowed" //from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (magic, holy, protection_sources)
#define COMPONENT_BLOCK_MAGIC 1
@@ -132,6 +137,7 @@
#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters)
#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" //from base of mob/RangedAttack(): (atom/A, params)
#define COMSIG_MOB_THROW "mob_throw" //from base of /mob/throw_item(): (atom/target)
#define COMSIG_MOB_KEY_CHANGE "mob_key_change" //from base of /mob/transfer_ckey()
#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" //from base of /mob/update_sight(): ()
#define COMSIG_MOB_SAY "mob_say" // from /mob/living/say(): (proc args list)
#define COMPONENT_UPPERCASE_SPEECH 1
@@ -159,6 +165,8 @@
#define COMSIG_OBJ_BREAK "obj_break" //from base of /obj/obj_break(): (damage_flag)
#define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value)
// /machinery signals
#define COMSIG_MACHINE_EJECT_OCCUPANT "eject_occupant" //from base of obj/machinery/dropContents() (occupant)
// /obj/item signals
#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user)

View File

@@ -511,7 +511,7 @@
G_found.client.prefs.copy_to(new_character)
new_character.dna.update_dna_identity()
new_character.key = G_found.key
G_found.transfer_ckey(new_character, FALSE)
return new_character

View File

@@ -46,7 +46,7 @@
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s imaginary friend?", ROLE_PAI, null, null, 75, friend)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
friend.key = C.key
C.transfer_ckey(friend, FALSE)
friend_initialized = TRUE
else
qdel(src)

View File

@@ -26,7 +26,7 @@
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s split personality?", ROLE_PAI, null, null, 75, stranger_backseat)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
stranger_backseat.key = C.key
C.transfer_ckey(stranger_backseat, FALSE)
log_game("[key_name(stranger_backseat)] became [key_name(owner)]'s split personality.")
message_admins("[ADMIN_LOOKUPFLW(stranger_backseat)] became [ADMIN_LOOKUPFLW(owner)]'s split personality.")
else
@@ -184,7 +184,7 @@
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s brainwashed mind?", null, null, null, 75, stranger_backseat)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
stranger_backseat.key = C.key
C.transfer_ckey(stranger_backseat, FALSE)
else
qdel(src)

View File

@@ -24,8 +24,9 @@ GLOBAL_LIST_EMPTY(uplinks)
var/unlock_note
var/unlock_code
var/failsafe_code
var/datum/ui_state/checkstate
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20)
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
@@ -57,6 +58,7 @@ GLOBAL_LIST_EMPTY(uplinks)
active = _enabled
gamemode = _gamemode
telecrystals = starting_tc
checkstate = _checkstate
if(!lockable)
active = TRUE
locked = FALSE
@@ -115,6 +117,7 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
state = checkstate ? checkstate : state
active = TRUE
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -123,6 +126,12 @@ GLOBAL_LIST_EMPTY(uplinks)
ui.set_style("syndicate")
ui.open()
/datum/component/uplink/ui_host(mob/user)
if(istype(parent, /obj/item/implant)) //implants are like organs, not really located inside mobs codewise.
var/obj/item/implant/I = parent
return I.imp_in
return ..()
/datum/component/uplink/ui_data(mob/user)
if(!user.mind)
return

View File

@@ -0,0 +1,128 @@
/datum/component/virtual_reality
dupe_mode = COMPONENT_DUPE_ALLOWED //mindswap memes, shouldn't stack up otherwise.
var/datum/mind/mastermind // where is my mind t. pixies
var/datum/mind/current_mind
var/obj/machinery/vr_sleeper/vr_sleeper
var/datum/action/quit_vr/quit_action
var/you_die_in_the_game_you_die_for_real = FALSE
var/datum/component/virtual_reality/inception //The component works on a very fragile link betwixt mind, ckey and death.
/datum/component/virtual_reality/Initialize(mob/M, obj/machinery/vr_sleeper/gaming_pod, yolo = FALSE, new_char = TRUE)
if(!ismob(parent) || !istype(M))
return COMPONENT_INCOMPATIBLE
var/mob/vr_M = parent
mastermind = M.mind
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED), .proc/game_over)
RegisterSignal(M, COMSIG_MOB_KEY_CHANGE, .proc/switch_player)
RegisterSignal(mastermind, COMSIG_MIND_TRANSFER, .proc/switch_player)
you_die_in_the_game_you_die_for_real = yolo
quit_action = new()
if(gaming_pod)
vr_sleeper = gaming_pod
RegisterSignal(vr_sleeper, COMSIG_ATOM_EMAG_ACT, .proc/you_only_live_once)
RegisterSignal(vr_sleeper, COMSIG_MACHINE_EJECT_OCCUPANT, .proc/revert_to_reality)
vr_M.ckey = M.ckey
var/datum/component/virtual_reality/clusterfk = M.GetComponent(/datum/component/virtual_reality)
if(clusterfk && !clusterfk.inception)
clusterfk.inception = src
SStgui.close_user_uis(M, src)
/datum/component/virtual_reality/RegisterWithParent()
var/mob/M = parent
current_mind = M.mind
quit_action.Grant(M)
RegisterSignal(quit_action, COMSIG_ACTION_TRIGGER, .proc/revert_to_reality)
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED), .proc/game_over)
RegisterSignal(M, COMSIG_MOB_GHOSTIZE, .proc/be_a_quitter)
RegisterSignal(M, COMSIG_MOB_KEY_CHANGE, .proc/pass_me_the_remote)
RegisterSignal(current_mind, COMSIG_MIND_TRANSFER, .proc/pass_me_the_remote)
mastermind.current.audiovisual_redirect = M
if(vr_sleeper)
vr_sleeper.vr_mob = M
/datum/component/virtual_reality/UnregisterFromParent()
quit_action.Remove(parent)
UnregisterSignal(parent, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED, COMSIG_MOB_KEY_CHANGE, COMSIG_MOB_GHOSTIZE))
UnregisterSignal(current_mind, COMSIG_MIND_TRANSFER)
UnregisterSignal(quit_action, COMSIG_ACTION_TRIGGER)
current_mind = null
mastermind.current.audiovisual_redirect = null
/datum/component/virtual_reality/proc/switch_player(datum/source, mob/new_mob, mob/old_mob)
if(vr_sleeper || !new_mob.mind)
// Machineries currently don't deal up with the occupant being polymorphed et similar... Or did something fuck up?
revert_to_reality()
return
old_mob.audiovisual_redirect = null
new_mob.audiovisual_redirect = parent
/datum/component/virtual_reality/proc/action_trigger(datum/signal_source, datum/action/source)
if(source != quit_action)
return COMPONENT_ACTION_BLOCK_TRIGGER
revert_to_reality(signal_source)
/datum/component/virtual_reality/proc/you_only_live_once()
if(you_die_in_the_game_you_die_for_real || vr_sleeper?.only_current_user_can_interact)
return FALSE
you_die_in_the_game_you_die_for_real = TRUE
return TRUE
/datum/component/virtual_reality/proc/pass_me_the_remote(datum/source, mob/new_mob)
if(new_mob == mastermind.current)
revert_to_reality(source)
return TRUE
new_mob.TakeComponent(src)
return TRUE
/datum/component/virtual_reality/PostTransfer()
if(!ismob(parent))
return COMPONENT_INCOMPATIBLE
/datum/component/virtual_reality/proc/revert_to_reality(datum/source)
quit_it()
/datum/component/virtual_reality/proc/game_over(datum/source)
quit_it(TRUE, TRUE)
/datum/component/virtual_reality/proc/be_a_quitter(datum/source, can_reenter_corpse)
quit_it()
return COMPONENT_BLOCK_GHOSTING
/datum/component/virtual_reality/proc/virtual_reality_in_a_virtual_reality(mob/player, killme = FALSE, datum/component/virtual_reality/yo_dawg)
var/mob/M = parent
quit_it(FALSE, killme, player, yo_dawg)
yo_dawg.inception = null
if(killme)
M.death(FALSE)
/datum/component/virtual_reality/proc/quit_it(deathcheck = FALSE, cleanup = FALSE, mob/override)
var/mob/M = parent
var/mob/dreamer = override ? override : mastermind.current
if(!mastermind)
to_chat(M, "<span class='warning'>You feel a dreadful sensation, something terrible happened. You try to wake up, but you find yourself unable to...</span>")
else
var/key_transfer = FALSE
if(inception?.parent)
inception.virtual_reality_in_a_virtual_reality(dreamer, cleanup, src)
else
key_transfer = TRUE
if(key_transfer)
M.transfer_ckey(dreamer, FALSE)
dreamer.stop_sound_channel(CHANNEL_HEARTBEAT)
dreamer.audiovisual_redirect = null
if(deathcheck && you_die_in_the_game_you_die_for_real)
to_chat(mastermind, "<span class='warning'>You feel everything fading away...</span>")
dreamer.death(FALSE)
if(cleanup)
var/obj/effect/vr_clean_master/cleanbot = locate() in get_area(M)
if(cleanbot)
LAZYADD(cleanbot.corpse_party, M)
if(vr_sleeper)
vr_sleeper.vr_mob = null
vr_sleeper = null
qdel(src)
/datum/component/virtual_reality/Destroy()
var/datum/action/quit_vr/delet_me = quit_action
. = ..()
qdel(delet_me)

View File

@@ -67,7 +67,7 @@
if(affected_mob.mind)
affected_mob.mind.transfer_to(new_mob)
else
new_mob.key = affected_mob.key
affected_mob.transfer_ckey(new_mob)
new_mob.name = affected_mob.real_name
new_mob.real_name = new_mob.name
@@ -82,7 +82,7 @@
to_chat(affected_mob, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(affected_mob)]) to replace a jobbaned player.")
affected_mob.ghostize(0)
affected_mob.key = C.key
C.transfer_ckey(affected_mob)
else
to_chat(new_mob, "Your mob has been claimed by death! Appeal your job ban if you want to avoid this in the future!")
new_mob.death()

View File

@@ -19,9 +19,9 @@
- IMPORTANT NOTE 2, if you want a player to become a ghost, use mob.ghostize() It does all the hard work for you.
- When creating a new mob which will be a new IC character (e.g. putting a shade in a construct or randomly selecting
a ghost to become a xeno during an event). Simply assign the key or ckey like you've always done.
a ghost to become a xeno during an event), use this mob proc.
new_mob.key = key
mob.transfer_ckey(new_mob)
The Login proc will handle making a new mind for that mobtype (including setting up stuff like mind.name). Simple!
However if you want that mind to have any special properties like being a traitor etc you will have to do that
@@ -89,6 +89,7 @@
return language_holder
/datum/mind/proc/transfer_to(mob/new_character, var/force_key_move = 0)
var/old_character = current
if(current) // remove ourself from our old body's mind variable
current.mind = null
SStgui.on_transfer(current, new_character)
@@ -99,7 +100,7 @@
if(key)
if(new_character.key != key) //if we're transferring into a body with a key associated which is not ours
new_character.ghostize(1) //we'll need to ghostize so that key isn't mobless.
new_character.ghostize(TRUE, TRUE) //we'll need to ghostize so that key isn't mobless.
else
key = new_character.key
@@ -123,6 +124,7 @@
transfer_martial_arts(new_character)
if(active || force_key_move)
new_character.key = key //now transfer the key to link the client to our new body
SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character)
//CIT CHANGE - makes arousal update when transfering bodies
if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs.

View File

@@ -112,7 +112,7 @@
H.update_action_buttons_icon()
if(implants)
for(var/implant_type in implants)
var/obj/item/implant/I = new implant_type(H)
var/obj/item/implant/I = new implant_type
I.implant(H, null, TRUE)
H.update_body()

View File

@@ -103,7 +103,6 @@
/obj/structure/cable,
/obj/machinery/atmospherics,
/obj/item/ammo_casing,
/obj/item/implant,
/obj/singularity
))
if(!can_contaminate || blacklisted[thing.type])

View File

@@ -259,9 +259,9 @@
status_type = STATUS_EFFECT_REPLACE
alert_type = null
var/mutable_appearance/marked_underlay
var/obj/item/twohanded/required/kinetic_crusher/hammer_synced
var/obj/item/twohanded/kinetic_crusher/hammer_synced
/datum/status_effect/crusher_mark/on_creation(mob/living/new_owner, obj/item/twohanded/required/kinetic_crusher/new_hammer_synced)
/datum/status_effect/crusher_mark/on_creation(mob/living/new_owner, obj/item/twohanded/kinetic_crusher/new_hammer_synced)
. = ..()
if(.)
hammer_synced = new_hammer_synced

View File

@@ -357,6 +357,7 @@
to_chat(quirk_holder, "<span class='boldannounce'>Your antagonistic nature has caused your voice to be heard.</span>")
qdel(src)
/datum/quirk/unstable
name = "Unstable"
desc = "Due to past troubles, you are unable to recover your sanity if you lose it. Be very careful managing your mood!"
@@ -365,3 +366,21 @@
gain_text = "<span class='danger'>There's a lot on your mind right now.</span>"
lose_text = "<span class='notice'>Your mind finally feels calm.</span>"
medical_record_text = "Patient's mind is in a vulnerable state, and cannot recover from traumatic events."
/datum/quirk/blindness
name = "Blind"
desc = "You are completely blind, nothing can counteract this."
value = -4
gain_text = "<span class='danger'>You can't see anything.</span>"
lose_text = "<span class='notice'>You miraculously gain back your vision.</span>"
medical_record_text = "Subject has permanent blindness."
/datum/quirk/blindness/add()
quirk_holder.become_blind(ROUNDSTART_TRAIT)
/datum/quirk/blindness/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/clothing/glasses/sunglasses/blindfold/white/glasses = new(get_turf(H))
if(!H.equip_to_slot_if_possible(glasses, SLOT_GLASSES, bypass_equip_delay_self = TRUE)) //if you can't put it on the user's eyes, put it in their hands, otherwise put it on their eyes eyes
H.put_in_hands(glasses)
H.regenerate_icons()

View File

@@ -8,7 +8,7 @@
ruletype = "Midround"
/// If the ruleset should be restricted from ghost roles.
var/restrict_ghost_roles = TRUE
/// What type the ruleset is restricted to.
/// What type the ruleset is restricted to.
var/required_type = /mob/living/carbon/human
var/list/living_players = list()
var/list/living_antags = list()
@@ -101,7 +101,7 @@
log_game("DYNAMIC: Polling [possible_volunteers.len] players to apply for the [name] ruleset.")
candidates = pollGhostCandidates("The mode is looking for volunteers to become [antag_flag] for [name]", antag_flag, SSticker.mode, antag_flag, poll_time = 300)
if(!candidates || candidates.len <= 0)
message_admins("The ruleset [name] received no applications.")
log_game("DYNAMIC: The ruleset [name] received no applications.")
@@ -194,7 +194,7 @@
..()
for(var/mob/living/player in living_players)
if(issilicon(player)) // Your assigned role doesn't change when you are turned into a silicon.
living_players -= player
living_players -= player
continue
if(is_centcom_level(player.z))
living_players -= player // We don't autotator people in CentCom
@@ -407,7 +407,7 @@
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/generate_ruleset_body(mob/applicant)
var/obj/vent = pick_n_take(vents)
var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc)
new_xeno.key = applicant.key
applicant.transfer_ckey(new_xeno, FALSE)
message_admins("[ADMIN_LOOKUPFLW(new_xeno)] has been made into an alien by the midround ruleset.")
log_game("DYNAMIC: [key_name(new_xeno)] was spawned as an alien by the midround ruleset.")
return new_xeno

View File

@@ -155,9 +155,9 @@
var/obj/item/U = new uplink_type(H, H.key, tc)
H.equip_to_slot_or_del(U, SLOT_IN_BACKPACK)
var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(H)
var/obj/item/implant/weapons_auth/W = new
W.implant(H)
var/obj/item/implant/explosive/E = new/obj/item/implant/explosive(H)
var/obj/item/implant/explosive/E = new
E.implant(H)
H.faction |= ROLE_SYNDICATE
H.update_icons()

View File

@@ -186,6 +186,7 @@ Class Procs:
if(isliving(A))
var/mob/living/L = A
L.update_canmove()
SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant)
occupant = null
/obj/machinery/proc/can_be_occupant(atom/movable/am)
@@ -498,6 +499,7 @@ Class Procs:
/obj/machinery/Exited(atom/movable/AM, atom/newloc)
. = ..()
if (AM == occupant)
SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant)
occupant = null
/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8

View File

@@ -159,11 +159,11 @@
if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
if(!autoprocess)
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoprocess</a>"
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoclone</a>"
else
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoprocess</a>"
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoclone</a>"
else
dat += "<span class='linkOff'>Autoprocess</span>"
dat += "<span class='linkOff'>Autoclone</span>"
dat += "<h3>Cloning Pod Status</h3>"
dat += "<div class='statusDisplay'>[temp]&nbsp;</div>"
@@ -228,7 +228,7 @@
dat += "<h4>[src.active_record.fields["name"]]</h4>"
dat += "Scan ID [src.active_record.fields["id"]] <a href='byond://?src=[REF(src)];clone=[active_record.fields["id"]]'>Clone</a><br>"
var/obj/item/implant/health/H = locate(src.active_record.fields["imp"])
var/obj/item/implant/health/H = locate(active_record.fields["imp"])
if ((H) && (istype(H)))
dat += "<b>Health Implant Data:</b><br />[H.sensehealth()]<br><br />"

View File

@@ -1 +0,0 @@
/obj/machinery/computer/prisoner

View File

@@ -35,11 +35,11 @@
dat += "<HR>Chemical Implants<BR>"
var/turf/Tr = null
for(var/obj/item/implant/chem/C in GLOB.tracked_chem_implants)
Tr = get_turf(C)
if((Tr) && (Tr.z != src.z))
continue//Out of range
if(!C.imp_in)
continue
Tr = get_turf(C.imp_in)
if((Tr) && (Tr.z != src.z))
continue//Out of range
dat += "ID: [C.imp_in.name] | Remaining Units: [C.reagents.total_volume] <BR>"
dat += "| Inject: "
dat += "<A href='?src=[REF(src)];inject1=[REF(C)]'>(<font class='bad'>(1)</font>)</A>"
@@ -48,9 +48,9 @@
dat += "********************************<BR>"
dat += "<HR>Tracking Implants<BR>"
for(var/obj/item/implant/tracking/T in GLOB.tracked_implants)
if(!isliving(T.imp_in))
if(!T.imp_in || !isliving(T.imp_in))
continue
Tr = get_turf(T)
Tr = get_turf(T.imp_in)
if((Tr) && (Tr.z != src.z))
continue//Out of range

View File

@@ -124,14 +124,14 @@
L[avoid_assoc_duplicate_keys(A.name, areaindex)] = R
for(var/obj/item/implant/tracking/I in GLOB.tracked_implants)
if(!I.imp_in || !isliving(I.loc))
if(!I.imp_in || !isliving(I.imp_in))
continue
else
var/mob/living/M = I.loc
var/mob/living/M = I.imp_in
if(M.stat == DEAD)
if(M.timeofdeath + 6000 < world.time)
continue
if(is_eligible(I))
if(is_eligible(M))
L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = I
var/desc = input("Please select a location to lock in.", "Locking Computer") as null|anything in L

View File

@@ -52,7 +52,7 @@
var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
H.key = C.key
C.transfer_ckey(H)
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()

View File

@@ -303,9 +303,10 @@
drawing = pick(all_drawables)
var/temp = "rune"
if(is_alpha(drawing))
var/ascii = (length(drawing) == 1) ? TRUE : FALSE
if(ascii && is_alpha(drawing))
temp = "letter"
else if(is_digit(drawing))
else if(ascii && is_digit(drawing))
temp = "number"
else if(drawing in punctuation)
temp = "punctuation mark"

View File

@@ -167,8 +167,19 @@ GLOBAL_LIST_EMPTY(GPS_list)
gpstag = "Eerie Signal"
desc = "Report to a coder immediately."
invisibility = INVISIBILITY_MAXIMUM
var/obj/item/implant/gps/implant
/obj/item/gps/mining/internal
/obj/item/gps/internal/Initialize(mapload, obj/item/implant/gps/_implant)
. = ..()
implant = _implant
/obj/item/gps/internal/Destroy()
if(implant?.imp_in)
qdel(implant)
else
return ..()
/obj/item/gps/internal/mining
icon_state = "gps-m"
gpstag = "MINER"
desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life."

View File

@@ -413,3 +413,16 @@
/obj/item/radio/off // Station bounced radios, their only difference is spawning with the speakers off, this was made to help the lag.
listening = 0 // And it's nice to have a subtype too for future features.
dog_fashion = /datum/dog_fashion/back
/obj/item/radio/internal
var/obj/item/implant/radio/implant
/obj/item/radio/internal/Initialize(mapload, obj/item/implant/radio/_implant)
. = ..()
implant = _implant
/obj/item/radio/internal/Destroy()
if(implant?.imp_in)
qdel(implant)
else
return ..()

View File

@@ -72,7 +72,7 @@
else
return FALSE
forceMove(target)
moveToNullspace()
imp_in = target
target.implants += src
if(activated)
@@ -89,7 +89,6 @@
return TRUE
/obj/item/implant/proc/removed(mob/living/source, silent = FALSE, special = 0)
moveToNullspace()
imp_in = null
source.implants -= src
for(var/X in actions)

View File

@@ -3,6 +3,7 @@
desc = "Injects things."
icon_state = "reagents"
activated = FALSE
var/obj/item/imp_chemholder/chemholder
/obj/item/implant/chem/get_data()
var/dat = {"<b>Implant Specifications:</b><BR>
@@ -29,6 +30,26 @@
GLOB.tracked_chem_implants -= src
return ..()
/obj/item/implant/chem/implant(mob/living/target, mob/user, silent = FALSE)
. = ..()
if(!.)
return
if(chemholder)
chemholder.forceMove(target)
return
chemholder = new(imp_in, src)
reagents.trans_to(chemholder, reagents.total_volume)
/obj/item/implant/chem/removed(mob/target, silent = FALSE, special = 0)
. = ..()
if(!.)
return
if(!special)
chemholder.reagents.trans_to(src, chemholder.reagents.total_volume)
QDEL_NULL(chemholder)
else
chemholder?.moveToNullspace()
/obj/item/implant/chem/trigger(emote, mob/living/source)
if(emote == "deathgasp")
if(istype(source) && !(source.stat == DEAD))
@@ -45,13 +66,12 @@
injectamount = reagents.total_volume
else
injectamount = cause
reagents.trans_to(R, injectamount)
chemholder.reagents.trans_to(R, injectamount)
to_chat(R, "<span class='italics'>You hear a faint beep.</span>")
if(!reagents.total_volume)
if(!chemholder.reagents.total_volume)
to_chat(R, "<span class='italics'>You hear a faint click from your chest.</span>")
qdel(src)
/obj/item/implantcase/chem
name = "implant case - 'Remote Chemical'"
desc = "A glass case containing a remote chemical implant."
@@ -63,3 +83,17 @@
return TRUE
else
return ..()
/obj/item/imp_chemholder
var/obj/item/implant/chem/implant
/obj/item/imp_chemholder/Initialize(mapload, obj/item/implant/chem/_implant)
. = ..()
create_reagents(50)
implant = _implant
/obj/item/imp_chemholder/Destroy()
if(implant?.imp_in)
qdel(implant)
else
return ..()

View File

@@ -11,7 +11,7 @@
/obj/item/implant/sad_trombone/trigger(emote, mob/source)
if(emote == "deathgasp")
playsound(loc, 'sound/misc/sadtrombone.ogg', 50, 0)
playsound(source.loc, 'sound/misc/sadtrombone.ogg', 50, 0)
/obj/item/implanter/sad_trombone
name = "implanter (sad trombone)"

View File

@@ -11,8 +11,9 @@
var/popup = FALSE // is the DOUWANNABLOWUP window open?
var/active = FALSE
/obj/item/implant/explosive/on_mob_death(mob/living/L, gibbed)
activate("death")
/obj/item/implant/explosive/trigger(emote, mob/source)
if(emote == "deathgasp")
activate("death")
/obj/item/implant/explosive/get_data()
var/dat = {"<b>Implant Specifications:</b><BR>
@@ -29,32 +30,18 @@
/obj/item/implant/explosive/activate(cause)
. = ..()
if(!cause || !imp_in || active)
return 0
return FALSE
if(cause == "action_button" && !popup)
popup = TRUE
var/response = alert(imp_in, "Are you sure you want to activate your [name]? This will cause you to explode!", "[name] Confirmation", "Yes", "No")
popup = FALSE
if(response == "No")
return 0
heavy = round(heavy)
medium = round(medium)
weak = round(weak)
to_chat(imp_in, "<span class='notice'>You activate your [name].</span>")
active = TRUE
var/turf/boomturf = get_turf(imp_in)
message_admins("[ADMIN_LOOKUPFLW(imp_in)] has activated their [name] at [ADMIN_VERBOSEJMP(boomturf)], with cause of [cause].")
//If the delay is short, just blow up already jeez
if(delay <= 7)
explosion(src,heavy,medium,weak,weak, flame_range = weak)
if(imp_in)
imp_in.gib(1)
qdel(src)
return
timed_explosion()
return FALSE
addtimer(CALLBACK(src, .proc/timed_explosion, cause), 1)
/obj/item/implant/explosive/implant(mob/living/target)
for(var/X in target.implants)
if(istype(X, type))
if(istype(X, /obj/item/implant/explosive))
var/obj/item/implant/explosive/imp_e = X
imp_e.heavy += heavy
imp_e.medium += medium
@@ -65,22 +52,37 @@
return ..()
/obj/item/implant/explosive/proc/timed_explosion()
imp_in.visible_message("<span class='warning'>[imp_in] starts beeping ominously!</span>")
playsound(loc, 'sound/items/timer.ogg', 30, 0)
sleep(delay*0.25)
if(imp_in && !imp_in.stat)
/obj/item/implant/explosive/proc/timed_explosion(cause)
if(cause == "death" && imp_in.stat != DEAD)
return FALSE
heavy = round(heavy)
medium = round(medium)
weak = round(weak)
to_chat(imp_in, "<span class='notice'>You activate your [name].</span>")
active = TRUE
var/turf/boomturf = get_turf(imp_in)
message_admins("[ADMIN_LOOKUPFLW(imp_in)] has activated their [name] at [ADMIN_VERBOSEJMP(boomturf)], with cause of [cause].")
if(delay > 7)
imp_in?.visible_message("<span class='warning'>[imp_in] starts beeping ominously!</span>")
playsound(get_turf(imp_in ? imp_in : src), 'sound/items/timer.ogg', 30, 0)
addtimer(CALLBACK(src, .proc/double_pain, TRUE), delay * 0.25)
addtimer(CALLBACK(src, .proc/double_pain), delay * 0.5)
addtimer(CALLBACK(src, .proc/double_pain), delay * 0.75)
addtimer(CALLBACK(src, .proc/boom_goes_the_weasel), delay)
else //If the delay is short, just blow up already jeez
boom_goes_the_weasel()
/obj/item/implant/explosive/proc/double_pain(message = FALSE)
playsound(get_turf(imp_in ? imp_in : src), 'sound/items/timer.ogg', 30, 0)
if(!imp_in)
return
if(message && imp_in.stat == CONSCIOUS)
imp_in.visible_message("<span class='warning'>[imp_in] doubles over in pain!</span>")
imp_in.Knockdown(140)
playsound(loc, 'sound/items/timer.ogg', 30, 0)
sleep(delay*0.25)
playsound(loc, 'sound/items/timer.ogg', 30, 0)
sleep(delay*0.25)
playsound(loc, 'sound/items/timer.ogg', 30, 0)
sleep(delay*0.25)
explosion(src,heavy,medium,weak,weak, flame_range = weak)
if(imp_in)
imp_in.gib(1)
imp_in.Knockdown(140)
/obj/item/implant/explosive/proc/boom_goes_the_weasel()
explosion(get_turf(imp_in ? imp_in : src), heavy, medium, weak, weak, flame_range = weak)
imp_in?.gib(TRUE)
qdel(src)
/obj/item/implant/explosive/macro
@@ -95,17 +97,7 @@
/obj/item/implant/explosive/macro/implant(mob/living/target)
for(var/X in target.implants)
if(istype(X, type))
return 0
for(var/Y in target.implants)
if(istype(Y, /obj/item/implant/explosive))
var/obj/item/implant/explosive/imp_e = Y
heavy += imp_e.heavy
medium += imp_e.medium
weak += imp_e.weak
delay += imp_e.delay
qdel(imp_e)
break
return FALSE
return ..()

View File

@@ -1,7 +1,6 @@
/obj/item/implant/mindshield
name = "mindshield implant"
desc = "Protects against brainwashing."
resistance_flags = INDESTRUCTIBLE
activated = 0
/obj/item/implant/mindshield/get_data()

View File

@@ -69,62 +69,4 @@
healthstring = "<small>Oxygen Deprivation Damage => [round(L.getOxyLoss())]<br />Fire Damage => [round(L.getFireLoss())]<br />Toxin Damage => [round(L.getToxLoss())]<br />Brute Force Damage => [round(L.getBruteLoss())]</small>"
if (!healthstring)
healthstring = "ERROR"
return healthstring
/obj/item/implant/radio
name = "internal radio implant"
activated = TRUE
var/obj/item/radio/radio
var/radio_key
var/subspace_transmission = FALSE
icon = 'icons/obj/radio.dmi'
icon_state = "walkietalkie"
/obj/item/implant/radio/activate()
. = ..()
// needs to be GLOB.deep_inventory_state otherwise it won't open
radio.ui_interact(usr, "main", null, FALSE, null, GLOB.deep_inventory_state)
/obj/item/implant/radio/Initialize(mapload)
. = ..()
radio = new(src)
// almost like an internal headset, but without the
// "must be in ears to hear" restriction.
radio.name = "internal radio"
radio.subspace_transmission = subspace_transmission
radio.canhear_range = 0
if(radio_key)
radio.keyslot = new radio_key
radio.recalculateChannels()
/obj/item/implant/radio/mining
radio_key = /obj/item/encryptionkey/headset_cargo
/obj/item/implant/radio/syndicate
desc = "Are you there God? It's me, Syndicate Comms Agent."
radio_key = /obj/item/encryptionkey/syndicate
subspace_transmission = TRUE
/obj/item/implant/radio/slime
name = "slime radio"
icon = 'icons/obj/surgery.dmi'
icon_state = "adamantine_resonator"
radio_key = /obj/item/encryptionkey/headset_sci
subspace_transmission = TRUE
/obj/item/implant/radio/get_data()
var/dat = {"<b>Implant Specifications:</b><BR>
<b>Name:</b> Internal Radio Implant<BR>
<b>Life:</b> 24 hours<BR>
<b>Implant Details:</b> Allows user to use an internal radio, useful if user expects equipment loss, or cannot equip conventional radios."}
return dat
/obj/item/implanter/radio
name = "implanter (internal radio)"
imp_type = /obj/item/implant/radio
/obj/item/implanter/radio/syndicate
name = "implanter (internal syndicate radio)"
imp_type = /obj/item/implant/radio/syndicate
return healthstring

View File

@@ -0,0 +1,69 @@
/obj/item/implant/radio
name = "internal radio implant"
activated = TRUE
var/obj/item/radio/internal/radio
var/radio_key
var/subspace_transmission = FALSE
icon = 'icons/obj/radio.dmi'
icon_state = "walkietalkie"
/obj/item/implant/radio/activate()
. = ..()
// needs to be GLOB.deep_inventory_state otherwise it won't open
radio.ui_interact(usr, "main", null, FALSE, null, GLOB.deep_inventory_state)
/obj/item/implant/radio/implant(mob/living/target, mob/user, silent = FALSE)
. = ..()
if(!.)
return
if(radio)
radio.forceMove(target)
return
radio = new(target)
// almost like an internal headset, but without the
// "must be in ears to hear" restriction.
radio.name = "internal radio"
radio.subspace_transmission = subspace_transmission
radio.canhear_range = 0
if(radio_key)
radio.keyslot = new radio_key
radio.recalculateChannels()
/obj/item/implant/radio/removed(mob/target, silent = FALSE, special = 0)
. = ..()
if(!.)
return
if(!special)
qdel(radio)
else
radio?.moveToNullspace()
/obj/item/implant/radio/mining
radio_key = /obj/item/encryptionkey/headset_cargo
/obj/item/implant/radio/syndicate
desc = "Are you there God? It's me, Syndicate Comms Agent."
radio_key = /obj/item/encryptionkey/syndicate
subspace_transmission = TRUE
/obj/item/implant/radio/slime
name = "slime radio"
icon = 'icons/obj/surgery.dmi'
icon_state = "adamantine_resonator"
radio_key = /obj/item/encryptionkey/headset_sci
subspace_transmission = TRUE
/obj/item/implant/radio/get_data()
var/dat = {"<b>Implant Specifications:</b><BR>
<b>Name:</b> Internal Radio Implant<BR>
<b>Life:</b> 24 hours<BR>
<b>Implant Details:</b> Allows user to use an internal radio, useful if user expects equipment loss, or cannot equip conventional radios."}
return dat
/obj/item/implanter/radio
name = "implanter (internal radio)"
imp_type = /obj/item/implant/radio
/obj/item/implanter/radio/syndicate
name = "implanter (internal syndicate radio)"
imp_type = /obj/item/implant/radio/syndicate

View File

@@ -4,30 +4,44 @@
icon_state = "storage"
item_color = "r"
var/max_slot_stacking = 4
var/obj/item/storage/bluespace_pocket/pocket
/obj/item/implant/storage/activate()
. = ..()
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SHOW, imp_in, TRUE)
SEND_SIGNAL(pocket, COMSIG_TRY_STORAGE_SHOW, imp_in, TRUE)
/obj/item/implant/storage/removed(source, silent = FALSE, special = 0)
. = ..()
if(.)
if(!special)
qdel(GetComponent(/datum/component/storage/concrete/implant))
if(!special)
qdel(pocket)
else
pocket?.moveToNullspace()
return ..()
/obj/item/implant/storage/implant(mob/living/target, mob/user, silent = FALSE)
for(var/X in target.implants)
if(istype(X, type))
var/obj/item/implant/storage/imp_e = X
GET_COMPONENT_FROM(STR, /datum/component/storage, imp_e)
GET_COMPONENT_FROM(STR, /datum/component/storage, imp_e.pocket)
if(!STR || (STR && STR.max_items < max_slot_stacking))
imp_e.AddComponent(/datum/component/storage/concrete/implant)
imp_e.pocket.AddComponent(/datum/component/storage/concrete/implant)
qdel(src)
return TRUE
return FALSE
AddComponent(/datum/component/storage/concrete/implant)
. = ..()
if(.)
if(pocket)
pocket.forceMove(target)
else
pocket = new(target)
return ..()
/obj/item/storage/bluespace_pocket
name = "internal bluespace pocket"
icon_state = "pillbox"
w_class = WEIGHT_CLASS_TINY
desc = "A tiny yet spacious pocket, usually found implanted inside sneaky syndicate agents and nowhere else."
component_type = /datum/component/storage/concrete/implant
resistance_flags = INDESTRUCTIBLE //A bomb!
item_flags = DROPDEL
/obj/item/implanter/storage
name = "implanter (storage)"

View File

@@ -3,8 +3,8 @@
desc = "Track with this."
activated = 0
/obj/item/implant/tracking/New()
..()
/obj/item/implant/tracking/Initialize()
. = ..()
GLOB.tracked_implants += src
/obj/item/implant/tracking/Destroy()
@@ -15,7 +15,31 @@
imp_type = /obj/item/implant/tracking
/obj/item/implanter/tracking/gps
imp_type = /obj/item/gps/mining/internal
imp_type = /obj/item/implant/gps
/obj/item/implant/gps
name = "\improper GPS implant"
desc = "Track with this and a GPS."
activated = FALSE
var/obj/item/gps/internal/mining/real_gps
/obj/item/implant/gps/implant(mob/living/target, mob/user, silent = FALSE)
. = ..()
if(!.)
return
if(real_gps)
real_gps.forceMove(target)
else
real_gps = new(target)
/obj/item/implant/gps/removed(mob/living/source, silent = FALSE, special = 0)
. = ..()
if(!.)
return
if(!special)
qdel(real_gps)
else
real_gps?.moveToNullspace()
/obj/item/implant/tracking/get_data()
var/dat = {"<b>Implant Specifications:</b><BR>

View File

@@ -1,23 +1,23 @@
/obj/item/implant/uplink
name = "uplink implant"
desc = "Sneeki breeki."
icon = 'icons/obj/radio.dmi'
icon_state = "radio"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
var/starting_tc = 0
/obj/item/implant/uplink/Initialize(mapload, _owner)
. = ..()
AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc)
/obj/item/implanter/uplink
name = "implanter (uplink)"
imp_type = /obj/item/implant/uplink
/obj/item/implanter/uplink/precharged
name = "implanter (precharged uplink)"
imp_type = /obj/item/implant/uplink/precharged
/obj/item/implant/uplink/precharged
starting_tc = 10
/obj/item/implant/uplink
name = "uplink implant"
desc = "Sneeki breeki."
icon = 'icons/obj/radio.dmi'
icon_state = "radio"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
var/starting_tc = 0
/obj/item/implant/uplink/Initialize(mapload, _owner)
. = ..()
AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc, GLOB.not_incapacitated_state)
/obj/item/implanter/uplink
name = "implanter (uplink)"
imp_type = /obj/item/implant/uplink
/obj/item/implanter/uplink/precharged
name = "implanter (precharged uplink)"
imp_type = /obj/item/implant/uplink/precharged
/obj/item/implant/uplink/precharged
starting_tc = 10

View File

@@ -9,9 +9,10 @@
item_flags = NOBLUDGEON
/obj/item/stack/telecrystal/attack(mob/target, mob/user)
if(target == user) //You can't go around smacking people with crystals to find out if they have an uplink or not.
for(var/obj/item/implant/uplink/I in target)
if(I && I.imp_in)
if(target == user && isliving(user)) //You can't go around smacking people with crystals to find out if they have an uplink or not.
var/mob/living/L = user
for(var/obj/item/implant/uplink/I in L.implants)
if(I?.imp_in)
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, I)
if(hidden_uplink)
hidden_uplink.telecrystals += amount

View File

@@ -75,15 +75,14 @@
temp += "<B>Implant Signals:</B><BR>"
for (var/obj/item/implant/tracking/W in GLOB.tracked_implants)
if (!W.imp_in || !isliving(W.loc))
if (!isliving(W.imp_in))
continue
else
var/mob/living/M = W.loc
if (M.stat == DEAD)
if (M.timeofdeath + 6000 < world.time)
continue
var/mob/living/M = W.imp_in
if (M.stat == DEAD)
if (M.timeofdeath + 6000 < world.time)
continue
var/turf/tr = get_turf(W)
var/turf/tr = get_turf(M)
if (tr.z == sr.z && tr)
var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
if (direct < 20)

View File

@@ -35,7 +35,7 @@
if(!wielded || !user)
return
wielded = 0
if(force_unwielded)
if(!isnull(force_unwielded))
force = force_unwielded
var/sf = findtext(name," (Wielded)")
if(sf)

View File

@@ -1,61 +0,0 @@
/mob/living/carbon/human/virtual_reality
var/datum/mind/real_mind // where is my mind t. pixies
var/obj/machinery/vr_sleeper/vr_sleeper
var/datum/action/quit_vr/quit_action
/mob/living/carbon/human/virtual_reality/Initialize()
. = ..()
quit_action = new()
quit_action.Grant(src)
/mob/living/carbon/human/virtual_reality/death()
revert_to_reality()
..()
/mob/living/carbon/human/virtual_reality/Destroy()
revert_to_reality()
return ..()
/mob/living/carbon/human/virtual_reality/Life()
. = ..()
if(real_mind)
var/mob/living/real_me = real_mind.current
if (real_me && real_me.stat == CONSCIOUS)
return
revert_to_reality(FALSE)
/mob/living/carbon/human/virtual_reality/ghostize()
stack_trace("Ghostize was called on a virtual reality mob")
/mob/living/carbon/human/virtual_reality/ghost()
set category = "OOC"
set name = "Ghost"
set desc = "Relinquish your life and enter the land of the dead."
revert_to_reality(FALSE)
/mob/living/carbon/human/virtual_reality/proc/revert_to_reality(deathchecks = TRUE)
if(real_mind && mind)
real_mind.current.audiovisual_redirect = null
real_mind.current.ckey = ckey
real_mind.current.stop_sound_channel(CHANNEL_HEARTBEAT)
if(deathchecks && vr_sleeper)
if(vr_sleeper.you_die_in_the_game_you_die_for_real)
to_chat(real_mind, "<span class='warning'>You feel everything fading away...</span>")
real_mind.current.death(0)
if(deathchecks && vr_sleeper)
vr_sleeper.vr_human = null
vr_sleeper = null
real_mind = null
/datum/action/quit_vr
name = "Quit Virtual Reality"
icon_icon = 'icons/mob/actions/actions_vr.dmi'
button_icon_state = "logout"
/datum/action/quit_vr/Trigger()
if(..())
if(istype(owner, /mob/living/carbon/human/virtual_reality))
var/mob/living/carbon/human/virtual_reality/VR = owner
VR.revert_to_reality(FALSE)
else
Remove(owner)

44
code/modules/VR/vr_mob.dm Normal file
View File

@@ -0,0 +1,44 @@
/mob/proc/build_virtual_character(mob/M)
mind_initialize()
if(!M)
return FALSE
name = M.name
real_name = M.real_name
mind.name = M.real_name
return TRUE
/mob/living/carbon/build_virtual_character(mob/M)
. = ..()
if(!.)
return
if(iscarbon(M))
var/mob/living/carbon/C = M
C.dna?.transfer_identity(src)
/mob/living/carbon/human/build_virtual_character(mob/M, datum/outfit/outfit)
. = ..()
if(!.)
return
var/mob/living/carbon/human/H
if(ishuman(M))
H = M
socks = H ? H.socks : random_socks()
socks_color = H ? H.socks_color : random_color()
undershirt = H ? H.undershirt : random_undershirt(M.gender)
shirt_color = H ? H.shirt_color : random_color()
underwear = H ? H.underwear : random_underwear(M.gender)
undie_color = H ? H.undie_color : random_color()
give_genitals(TRUE)
if(outfit)
var/datum/outfit/O = new outfit()
O.equip(src)
/datum/action/quit_vr
name = "Quit Virtual Reality"
icon_icon = 'icons/mob/actions/actions_vr.dmi'
button_icon_state = "logout"
/datum/action/quit_vr/Trigger() //this merely a trigger for /datum/component/virtual_reality
. = ..()
if(!.)
Remove(owner)

View File

@@ -1,5 +1,3 @@
//Glorified teleporter that puts you in a new human body.
// it's """VR"""
/obj/machinery/vr_sleeper
@@ -12,9 +10,10 @@
circuit = /obj/item/circuitboard/machine/vr_sleeper
var/you_die_in_the_game_you_die_for_real = FALSE
var/datum/effect_system/spark_spread/sparks
var/mob/living/carbon/human/virtual_reality/vr_human
var/mob/living/vr_mob
var/virtual_mob_type = /mob/living/carbon/human
var/vr_category = "default" //Specific category of spawn points to pick from
var/allow_creating_vr_humans = TRUE //So you can have vr_sleepers that always spawn you as a specific person or 1 life/chance vr games
var/allow_creating_vr_mobs = TRUE //So you can have vr_sleepers that always spawn you as a specific person or 1 life/chance vr games
var/only_current_user_can_interact = FALSE
/obj/machinery/vr_sleeper/Initialize()
@@ -44,7 +43,7 @@
/obj/machinery/vr_sleeper/Destroy()
open_machine()
cleanup_vr_human()
cleanup_vr_mob()
QDEL_NULL(sparks)
return ..()
@@ -58,8 +57,9 @@
/obj/machinery/vr_sleeper/emag_act(mob/user)
. = ..()
if(you_die_in_the_game_you_die_for_real)
if(!(obj_flags & EMAGGED))
return
obj_flags |= EMAGGED
you_die_in_the_game_you_die_for_real = TRUE
sparks.start()
addtimer(CALLBACK(src, .proc/emagNotify), 150)
@@ -69,12 +69,11 @@
icon_state = "[initial(icon_state)][state_open ? "-open" : ""]"
/obj/machinery/vr_sleeper/open_machine()
if(!state_open)
if(vr_human)
vr_human.revert_to_reality(FALSE)
if(occupant)
SStgui.close_user_uis(occupant, src)
..()
if(state_open)
return
if(occupant)
SStgui.close_user_uis(occupant, src)
return ..()
/obj/machinery/vr_sleeper/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
@@ -94,22 +93,20 @@
if("vr_connect")
var/mob/living/carbon/human/human_occupant = occupant
if(human_occupant && human_occupant.mind && usr == occupant)
to_chat(occupant, "<span class='warning'>Transferring to virtual reality...</span>")
if(vr_human && vr_human.stat == CONSCIOUS && !vr_human.real_mind)
SStgui.close_user_uis(occupant, src)
human_occupant.audiovisual_redirect = vr_human
vr_human.real_mind = human_occupant.mind
vr_human.ckey = human_occupant.ckey
to_chat(vr_human, "<span class='notice'>Transfer successful! You are now playing as [vr_human] in VR!</span>")
if(vr_mob && (!istype(vr_mob) || !vr_mob.InCritical()) && !vr_mob.GetComponent(/datum/component/virtual_reality))
vr_mob.AddComponent(/datum/component/virtual_reality, human_occupant, src, you_die_in_the_game_you_die_for_real)
to_chat(vr_mob, "<span class='notice'>Transfer successful! You are now playing as [vr_mob] in VR!</span>")
else
if(allow_creating_vr_humans)
if(allow_creating_vr_mobs)
to_chat(occupant, "<span class='warning'>Virtual avatar not found, attempting to create one...</span>")
var/obj/effect/landmark/vr_spawn/V = get_vr_spawnpoint()
var/turf/T = get_turf(V)
if(T)
SStgui.close_user_uis(occupant, src)
build_virtual_human(occupant, T, V.vr_outfit)
to_chat(vr_human, "<span class='notice'>Transfer successful! You are now playing as [vr_human] in VR!</span>")
new_player(occupant, T, V.vr_outfit)
to_chat(vr_mob, "<span class='notice'>Transfer successful! You are now playing as [vr_mob] in VR!</span>")
else
to_chat(occupant, "<span class='warning'>Virtual world misconfigured, aborting transfer</span>")
else
@@ -117,8 +114,8 @@
. = TRUE
if("delete_avatar")
if(!occupant || usr == occupant)
if(vr_human)
cleanup_vr_human()
if(vr_mob)
cleanup_vr_mob()
else
to_chat(usr, "<span class='warning'>The VR Sleeper's safeties prevent you from doing that.</span>")
. = TRUE
@@ -131,19 +128,22 @@
/obj/machinery/vr_sleeper/ui_data(mob/user)
var/list/data = list()
if(vr_human && !QDELETED(vr_human))
if(vr_mob && !QDELETED(vr_mob))
data["can_delete_avatar"] = TRUE
var/status
switch(vr_human.stat)
if(CONSCIOUS)
status = "Conscious"
if(DEAD)
status = "Dead"
if(UNCONSCIOUS)
status = "Unconscious"
if(SOFT_CRIT)
status = "Barely Conscious"
data["vr_avatar"] = list("name" = vr_human.name, "status" = status, "health" = vr_human.health, "maxhealth" = vr_human.maxHealth)
data["vr_avatar"] = list("name" = vr_mob.name)
data["isliving"] = istype(vr_mob)
if(data["isliving"])
var/status
switch(vr_mob.stat)
if(CONSCIOUS)
status = "Conscious"
if(DEAD)
status = "Dead"
if(UNCONSCIOUS)
status = "Unconscious"
if(SOFT_CRIT)
status = "Barely Conscious"
data["vr_avatar"] += list("status" = status, "health" = vr_mob.health, "maxhealth" = vr_mob.maxHealth)
data["toggle_open"] = state_open
data["emagged"] = you_die_in_the_game_you_die_for_real
data["isoccupant"] = (user == occupant)
@@ -157,40 +157,25 @@
for(var/obj/effect/landmark/vr_spawn/V in GLOB.landmarks_list)
GLOB.vr_spawnpoints[V.vr_category] = V
/obj/machinery/vr_sleeper/proc/build_virtual_human(mob/living/carbon/human/H, location, var/datum/outfit/outfit, transfer = TRUE)
if(H)
cleanup_vr_human()
vr_human = new /mob/living/carbon/human/virtual_reality(location)
vr_human.mind_initialize()
vr_human.vr_sleeper = src
vr_human.real_mind = H.mind
H.dna.transfer_identity(vr_human)
vr_human.name = H.name
vr_human.real_name = H.real_name
vr_human.socks = H.socks
vr_human.socks_color = H.socks_color
vr_human.undershirt = H.undershirt
vr_human.shirt_color = H.shirt_color
vr_human.underwear = H.underwear
vr_human.undie_color = H.undie_color
vr_human.updateappearance(TRUE, TRUE, TRUE)
vr_human.give_genitals(TRUE) //CITADEL ADD
if(outfit)
var/datum/outfit/O = new outfit()
O.equip(vr_human)
if(transfer && H.mind)
SStgui.close_user_uis(H, src)
H.audiovisual_redirect = vr_human
vr_human.ckey = H.ckey
/obj/machinery/vr_sleeper/proc/new_player(mob/living/carbon/human/H, location, datum/outfit/outfit, transfer = TRUE)
if(!H)
return
cleanup_vr_mob()
vr_mob = new virtual_mob_type(location)
if(vr_mob.build_virtual_character(H, outfit))
var/mob/living/carbon/human/vr_H = vr_mob
vr_H.updateappearance(TRUE, TRUE, TRUE)
if(!transfer || !H.mind)
return
vr_mob.AddComponent(/datum/component/virtual_reality, H, src, you_die_in_the_game_you_die_for_real)
/obj/machinery/vr_sleeper/proc/cleanup_vr_human()
if(vr_human)
vr_human.vr_sleeper = null // Prevents race condition where a new human could get created out of order and set to null.
QDEL_NULL(vr_human)
/obj/machinery/vr_sleeper/proc/cleanup_vr_mob()
if(vr_mob)
QDEL_NULL(vr_mob)
/obj/machinery/vr_sleeper/proc/emagNotify()
if(vr_human)
vr_human.Dizzy(10)
if(vr_mob)
vr_mob.Dizzy(10)
/obj/effect/landmark/vr_spawn //places you can spawn in VR, auto selected by the vr_sleeper during get_vr_spawnpoint()
var/vr_category = "default" //So we can have specific sleepers, eg: "Basketball VR Sleeper", etc.
@@ -222,6 +207,7 @@
color = "#00FF00"
invisibility = INVISIBILITY_ABSTRACT
var/area/vr_area
var/list/corpse_party
/obj/effect/vr_clean_master/Initialize()
. = ..()
@@ -234,7 +220,8 @@
qdel(casing)
for(var/obj/effect/decal/cleanable/C in vr_area)
qdel(C)
for (var/mob/living/carbon/human/virtual_reality/H in vr_area)
if (H.stat == DEAD && !H.vr_sleeper && !H.real_mind)
qdel(H)
for (var/A in corpse_party)
var/mob/M = A
if(get_area(M) == vr_area && M.stat == DEAD)
qdel(M)
addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES)

View File

@@ -61,7 +61,7 @@
to_chat(body, "Your mob has been taken over by a ghost!")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(body)])")
body.ghostize(0)
body.key = C.key
C.transfer_ckey(body)
new /obj/effect/temp_visual/gravpush(get_turf(body))
/obj/effect/fun_balloon/sentience/emergency_shuttle

View File

@@ -744,7 +744,7 @@
var/mob/chosen = players[1]
if (chosen.client)
chosen.client.prefs.copy_to(spawnedMob)
spawnedMob.key = chosen.key
chosen.transfer_ckey(spawnedMob)
players -= chosen
if (ishuman(spawnedMob) && ispath(humanoutfit, /datum/outfit))
var/mob/living/carbon/human/H = spawnedMob

View File

@@ -306,7 +306,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
var/mob/living/silicon/pai/pai = new(card)
pai.name = input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text
pai.real_name = pai.name
pai.key = choice.key
choice.transfer_ckey(pai)
card.setPersonality(pai)
for(var/datum/paiCandidate/candidate in SSpai.candidates)
if(candidate.key == choice.key)

View File

@@ -412,7 +412,7 @@
//Spawn the body
var/mob/living/carbon/human/ERTOperative = new ertemplate.mobtype(spawnloc)
chosen_candidate.client.prefs.copy_to(ERTOperative)
ERTOperative.key = chosen_candidate.key
chosen_candidate.transfer_ckey(ERTOperative)
if(ertemplate.enforce_human || ERTOperative.dna.species.dangerous_existence) // Don't want any exploding plasmemes
ERTOperative.set_species(/datum/species/human)

View File

@@ -384,7 +384,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
//Now to give them their mind back.
G_found.mind.transfer_to(new_xeno) //be careful when doing stuff like this! I've already checked the mind isn't in use
new_xeno.key = G_found.key
G_found.transfer_ckey(new_xeno, FALSE)
to_chat(new_xeno, "You have been fully respawned. Enjoy the game.")
var/msg = "<span class='adminnotice'>[key_name_admin(usr)] has respawned [new_xeno.key] as a filthy xeno.</span>"
message_admins(msg)
@@ -397,7 +397,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/mob/living/carbon/monkey/new_monkey = new
SSjob.SendToLateJoin(new_monkey)
G_found.mind.transfer_to(new_monkey) //be careful when doing stuff like this! I've already checked the mind isn't in use
new_monkey.key = G_found.key
G_found.transfer_ckey(new_monkey, FALSE)
to_chat(new_monkey, "You have been fully respawned. Enjoy the game.")
var/msg = "<span class='adminnotice'>[key_name_admin(usr)] has respawned [new_monkey.key] as a filthy xeno.</span>"
message_admins(msg)
@@ -437,7 +437,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!new_character.mind.assigned_role)
new_character.mind.assigned_role = "Assistant"//If they somehow got a null assigned role.
new_character.key = G_found.key
G_found.transfer_ckey(new_character, FALSE)
/*
The code below functions with the assumption that the mob is already a traitor if they have a special role.

View File

@@ -15,7 +15,7 @@ GLOBAL_LIST_EMPTY(antagonists)
var/antag_memory = ""//These will be removed with antag datum
var/antag_moodlet //typepath of moodlet that the mob will gain with their status
var/can_hijack = HIJACK_NEUTRAL //If these antags are alone on shuttle hijack happens.
//Antag panel properties
var/show_in_antagpanel = TRUE //This will hide adding this antag type in antag panel, use only for internal subtypes that shouldn't be added directly but still show if possessed by mind
var/antagpanel_category = "Uncategorized" //Antagpanel will display these together, REQUIRED
@@ -87,7 +87,7 @@ GLOBAL_LIST_EMPTY(antagonists)
to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
owner.current.ghostize(0)
owner.current.key = C.key
C.transfer_ckey(owner.current, FALSE)
/datum/antagonist/proc/on_removal()
remove_innate_effects()

View File

@@ -52,5 +52,5 @@
/datum/outfit/abductor/scientist/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
..()
if(!visualsOnly)
var/obj/item/implant/abductor/beamplant = new /obj/item/implant/abductor(H)
var/obj/item/implant/abductor/beamplant = new
beamplant.implant(H)

View File

@@ -172,7 +172,7 @@
blobber.adjustHealth(blobber.maxHealth * 0.5)
blob_mobs += blobber
var/mob/dead/observer/C = pick(candidates)
blobber.key = C.key
C.transfer_ckey(blobber)
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>")

View File

@@ -349,7 +349,7 @@
to_chat(L, "<span class='userdanger'>Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form!</span>")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(L)]) to replace an inactive clock cultist.")
L.ghostize(0)
L.key = C.key
C.transfer_ckey(L, FALSE)
var/obj/effect/temp_visual/ratvar/sigil/vitality/V = new /obj/effect/temp_visual/ratvar/sigil/vitality(get_turf(src))
animate(V, alpha = 0, transform = matrix()*2, time = 8)
playsound(L, 'sound/magic/staff_healing.ogg', 50, 1)

View File

@@ -55,7 +55,7 @@
pre_spawn()
visible_message(creation_message)
var/mob/living/construct = new construct_type(get_turf(src))
construct.key = user.key
user.transfer_ckey(construct, FALSE)
post_spawn(construct)
qdel(user)
qdel(src)

View File

@@ -216,6 +216,9 @@
if(is_reebe(invoker.z))
to_chat(invoker, "<span class='danger'>You're already at Reebe.</span>")
return
if(!isturf(invoker.loc))
to_chat(invoker, "<span class='danger'>You must be visible to return!</span>")
return
return TRUE
/datum/clockwork_scripture/abscond/recital()

View File

@@ -64,7 +64,7 @@
message_admins("<span class='danger'>Admin [key_name_admin(user)] directly became the Eminence of the cult!</span>")
log_admin("Admin [key_name(user)] made themselves the Eminence.")
var/mob/camera/eminence/eminence = new(get_turf(src))
eminence.key = user.key
user.transfer_ckey(eminence, FALSE)
hierophant_message("<span class='bold large_brass'>Ratvar has directly assigned the Eminence!</span>")
for(var/mob/M in servants_and_ghosts())
M.playsound_local(M, 'sound/machines/clockcult/eminence_selected.ogg', 50, FALSE)
@@ -138,7 +138,7 @@
playsound(src, 'sound/machines/clockcult/ark_damage.ogg', 50, FALSE)
var/mob/camera/eminence/eminence = new(get_turf(src))
eminence_nominee = pick(candidates)
eminence.key = eminence_nominee.key
eminence_nominee.transfer_ckey(eminence)
hierophant_message("<span class='bold large_brass'>A ghost has ascended into the Eminence!</span>")
for(var/mob/M in servants_and_ghosts())
M.playsound_local(M, 'sound/machines/clockcult/eminence_selected.ogg', 50, FALSE)

View File

@@ -45,7 +45,7 @@
return FALSE
var/mob/living/simple_animal/drone/cogscarab/ratvar/R = new/mob/living/simple_animal/drone/cogscarab/ratvar(get_turf(src))
R.visible_message("<span class='heavy_brass'>[R] forms, and its eyes blink open, glowing bright red!</span>")
R.key = O.key
O.transfer_ckey(R, FALSE)
/obj/structure/destructible/clockwork/massive/ratvar/Bump(atom/A)
var/turf/T = get_turf(A)

View File

@@ -575,7 +575,7 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(mob_to_revive.mind, "Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form.")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(mob_to_revive)]) to replace an AFK player.")
mob_to_revive.ghostize(0)
mob_to_revive.key = C.key
C.transfer_ckey(mob_to_revive, FALSE)
else
fail_invoke()
return
@@ -870,7 +870,7 @@ structure_check() searches for nearby cultist structures required for the invoca
visible_message("<span class='warning'>A cloud of red mist forms above [src], and from within steps... a [new_human.gender == FEMALE ? "wo":""]man.</span>")
to_chat(user, "<span class='cultitalic'>Your blood begins flowing into [src]. You must remain in place and conscious to maintain the forms of those summoned. This will hurt you slowly but surely...</span>")
var/obj/structure/emergency_shield/invoker/N = new(T)
new_human.key = ghost_to_spawn.key
ghost_to_spawn.transfer_ckey(new_human, FALSE)
SSticker.mode.add_cultist(new_human.mind, 0)
to_chat(new_human, "<span class='cultitalic'><b>You are a servant of the Geometer. You have been made semi-corporeal by the cult of Nar'Sie, and you are to serve them at all costs.</b></span>")

View File

@@ -146,7 +146,7 @@
/mob/living/carbon/true_devil/attack_ghost(mob/dead/observer/user as mob)
if(ascended || user.mind.soulOwner == src.mind)
var/mob/living/simple_animal/imp/S = new(get_turf(loc))
S.key = user.key
user.transfer_ckey(S, FALSE)
S.mind.assigned_role = "Imp"
S.mind.special_role = "Imp"
var/datum/objective/newobjective = new

View File

@@ -18,7 +18,7 @@
var/mob/dead/observer/selected = pick_n_take(candidates)
var/mob/camera/disease/virus = new /mob/camera/disease(SSmapping.get_station_center())
virus.key = selected.key
selected.transfer_ckey(virus, FALSE)
INVOKE_ASYNC(virus, /mob/camera/disease/proc/pick_name)
message_admins("[ADMIN_LOOKUPFLW(virus)] has been made into a sentient disease by an event.")
log_game("[key_name(virus)] was spawned as a sentient disease by an event.")

View File

@@ -1,7 +1,8 @@
#define CHALLENGE_TELECRYSTALS 280
#define PLAYER_SCALING 1.5
#define CHALLENGE_TIME_LIMIT 3000
#define CHALLENGE_MIN_PLAYERS 50
#define CHALLENGE_PLAYERS_TARGET 50 //target players population. anything below is a malus to the challenge tc bonus.
#define TELECRYSTALS_MALUS_SCALING 1 //the higher the value, the bigger the malus.
#define CHALLENGE_SHUTTLE_DELAY 15000 // 25 minutes, so the ops have at least 5 minutes before the shuttle is callable.
GLOBAL_LIST_EMPTY(jam_on_wardec)
@@ -62,12 +63,15 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
for(var/obj/machinery/computer/camera_advanced/shuttle_docker/D in GLOB.jam_on_wardec)
D.jammed = TRUE
GLOB.war_declared = TRUE
var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop)
var/actual_players = GLOB.joined_player_list.len - nukeops.len
var/tc_malus = 0
if(actual_players < CHALLENGE_PLAYERS_TARGET)
tc_malus = FLOOR(((CHALLENGE_TELECRYSTALS / CHALLENGE_PLAYERS_TARGET) * (CHALLENGE_PLAYERS_TARGET - actual_players)) * TELECRYSTALS_MALUS_SCALING, 1)
new uplink_type(get_turf(user), user.key, CHALLENGE_TELECRYSTALS + CEILING(PLAYER_SCALING * actual_players, 1))
new uplink_type(get_turf(user), user.key, CHALLENGE_TELECRYSTALS - tc_malus + CEILING(PLAYER_SCALING * actual_players, 1))
CONFIG_SET(number/shuttle_refuel_delay, max(CONFIG_GET(number/shuttle_refuel_delay), CHALLENGE_SHUTTLE_DELAY))
SSblackbox.record_feedback("amount", "nuclear_challenge_mode", 1)
@@ -79,11 +83,6 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
to_chat(user, "You are already in the process of declaring war! Make your mind up.")
return FALSE
var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop)
var/actual_players = GLOB.joined_player_list.len - nukeops.len
if(actual_players < CHALLENGE_MIN_PLAYERS)
to_chat(user, "The enemy crew is too small to be worth declaring war on.")
return FALSE
if(!user.onSyndieBase())
to_chat(user, "You have to be at your base to use this.")
return FALSE
@@ -102,5 +101,6 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
#undef CHALLENGE_TELECRYSTALS
#undef CHALLENGE_TIME_LIMIT
#undef CHALLENGE_MIN_PLAYERS
#undef CHALLENGE_PLAYERS_TARGET
#undef TELECRYSTALS_MALUS_SCALING
#undef CHALLENGE_SHUTTLE_DELAY

View File

@@ -107,9 +107,9 @@
/datum/antagonist/overthrow/proc/equip_overthrow()
if(!owner || !owner.current || !ishuman(owner.current)) // only equip existing human overthrow members. This excludes the AI, in particular.
return
var/obj/item/implant/storage/S = locate(/obj/item/implant/storage) in owner.current
var/obj/item/implant/storage/S = locate(/obj/item/implant/storage) in owner.current.implants
if(!S)
S = new(owner.current)
S = new
S.implant(owner.current)
var/I = pick(possible_useful_items)
if(ispath(I)) // in case some admin decides to fuck the list up for fun

View File

@@ -377,14 +377,15 @@
/obj/item/ectoplasm/revenant/proc/reform()
if(QDELETED(src) || QDELETED(revenant) || inert)
return
var/key_of_revenant
var/key_of_revenant = FALSE
message_admins("Revenant ectoplasm was left undestroyed for 1 minute and is reforming into a new revenant.")
forceMove(drop_location()) //In case it's in a backpack or someone's hand
revenant.forceMove(loc)
if(old_key)
for(var/mob/M in GLOB.dead_mob_list)
if(M.client && M.client.key == old_key) //Only recreates the mob if the mob the client is in is dead
key_of_revenant = old_key
M.transfer_ckey(revenant.key, FALSE)
key_of_revenant = TRUE
break
if(!key_of_revenant)
message_admins("The new revenant's old client either could not be found or is in a new, living mob - grabbing a random candidate instead...")
@@ -396,22 +397,21 @@
visible_message("<span class='revenwarning'>[src] settles down and seems lifeless.</span>")
return
var/mob/dead/observer/C = pick(candidates)
key_of_revenant = C.key
if(!key_of_revenant)
C.transfer_ckey(revenant.key, FALSE)
if(!revenant.key)
qdel(revenant)
message_admins("No ckey was found for the new revenant. Oh well!")
inert = TRUE
visible_message("<span class='revenwarning'>[src] settles down and seems lifeless.</span>")
return
message_admins("[key_of_revenant] has been [old_key == key_of_revenant ? "re":""]made into a revenant by reforming ectoplasm.")
log_game("[key_of_revenant] was [old_key == key_of_revenant ? "re":""]made as a revenant by reforming ectoplasm.")
message_admins("[key_of_revenant] has been [old_key == revenant.key ? "re":""]made into a revenant by reforming ectoplasm.")
log_game("[key_of_revenant] was [old_key == revenant.key ? "re":""]made as a revenant by reforming ectoplasm.")
visible_message("<span class='revenboldnotice'>[src] suddenly rises into the air before fading away.</span>")
revenant.essence = essence
revenant.essence_regen_cap = essence
revenant.death_reset()
revenant.key = key_of_revenant
revenant = null
qdel(src)

View File

@@ -52,7 +52,7 @@
return MAP_ERROR
var/mob/living/simple_animal/revenant/revvie = new(pick(spawn_locs))
revvie.key = selected.key
selected.transfer_ckey(revvie, FALSE)
message_admins("[ADMIN_LOOKUPFLW(revvie)] has been made into a revenant by an event.")
log_game("[key_name(revvie)] was spawned as a revenant by an event.")
spawned_mobs += revvie

View File

@@ -218,7 +218,7 @@
newstruct.master = stoner
var/datum/action/innate/seek_master/SM = new()
SM.Grant(newstruct)
newstruct.key = target.key
target.transfer_ckey(newstruct)
var/obj/screen/alert/bloodsense/BS
if(newstruct.mind && ((stoner && iscultist(stoner)) || cultoverride) && SSticker && SSticker.mode)
SSticker.mode.add_cultist(newstruct.mind, 0)
@@ -243,7 +243,7 @@
S.canmove = FALSE//Can't move out of the soul stone
S.name = "Shade of [T.real_name]"
S.real_name = "Shade of [T.real_name]"
S.key = T.key
T.transfer_ckey(S)
S.language_holder = U.language_holder.copy(S)
if(U)
S.faction |= "[REF(U)]" //Add the master as a faction, allowing inter-mob cooperation

View File

@@ -245,7 +245,7 @@
if(!istype(M))
return
var/obj/item/implant/exile/Implant = new/obj/item/implant/exile(M)
var/obj/item/implant/exile/Implant = new
Implant.implant(M)
/datum/antagonist/wizard/academy/create_objectives()

View File

@@ -133,7 +133,7 @@
var/mob/dead/observer/C = pick(candidates)
message_admins("[ADMIN_LOOKUPFLW(C)] was spawned as Wizard Academy Defender")
current_wizard.ghostize() // on the off chance braindead defender gets back in
current_wizard.key = C.key
C.transfer_ckey(current_wizard, FALSE)
/obj/structure/academy_wizard_spawner/proc/summon_wizard()
var/turf/T = src.loc
@@ -210,8 +210,6 @@
if(4)
//Destroy Equipment
for (var/obj/item/I in user)
if (istype(I, /obj/item/implant))
continue
qdel(I)
if(5)
//Monkeying
@@ -274,7 +272,7 @@
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
message_admins("[ADMIN_LOOKUPFLW(C)] was spawned as Dice Servant")
H.key = C.key
C.transfer_ckey(H, FALSE)
var/obj/effect/proc_holder/spell/targeted/summonmob/S = new
S.target_mob = H

View File

@@ -281,6 +281,33 @@
..()
user.cure_blind("blindfold_[REF(src)]")
/obj/item/clothing/glasses/sunglasses/blindfold/white
name = "blind personnel blindfold"
desc = "Indicates that the wearer suffers from blindness."
icon_state = "blindfoldwhite"
item_state = "blindfoldwhite"
var/colored_before = FALSE
/obj/item/clothing/glasses/sunglasses/blindfold/white/equipped(mob/living/carbon/human/user, slot)
if(ishuman(user) && slot == SLOT_GLASSES)
update_icon(user)
user.update_inv_glasses() //Color might have been changed by update_icon.
..()
/obj/item/clothing/glasses/sunglasses/blindfold/white/update_icon(mob/living/carbon/human/user)
if(ishuman(user) && !colored_before)
add_atom_colour("#[user.eye_color]", FIXED_COLOUR_PRIORITY)
colored_before = TRUE
/obj/item/clothing/glasses/sunglasses/blindfold/white/worn_overlays(isinhands = FALSE, file2use)
. = list()
if(!isinhands && ishuman(loc) && !colored_before)
var/mob/living/carbon/human/H = loc
var/mutable_appearance/M = mutable_appearance('icons/mob/eyes.dmi', "blindfoldwhite")
M.appearance_flags |= RESET_COLOR
M.color = "#[H.eye_color]"
. += M
/obj/item/clothing/glasses/sunglasses/big
desc = "Strangely ancient technology used to help provide rudimentary eye cover. Larger than average enhanced shielding blocks flashes."
icon_state = "bigsunglasses"

View File

@@ -10,7 +10,7 @@
if(visualsOnly)
return
var/obj/item/implant/mindshield/L = new/obj/item/implant/mindshield(H)
var/obj/item/implant/mindshield/L = new
L.implant(H, null, 1)
var/obj/item/radio/R = H.ears

View File

@@ -399,7 +399,7 @@
R.set_frequency(FREQ_CENTCOM)
R.freqlock = TRUE
var/obj/item/implant/mindshield/L = new/obj/item/implant/mindshield(H)//Here you go Deuryn
var/obj/item/implant/mindshield/L = new //Here you go Deuryn
L.implant(H, null, 1)
@@ -426,7 +426,7 @@
/datum/outfit/debug //Debug objs plus hardsuit
name = "Debug outfit"
uniform = /obj/item/clothing/under/patriotsuit
uniform = /obj/item/clothing/under/patriotsuit
suit = /obj/item/clothing/suit/space/hardsuit/syndi/elite
shoes = /obj/item/clothing/shoes/magboots/advance
suit_store = /obj/item/tank/internals/oxygen

View File

@@ -29,9 +29,9 @@
. = ..()
var/obj/item/uplink/U = new /obj/item/uplink/nuclear_restricted(H, H.key, 80)
H.equip_to_slot_or_del(U, SLOT_IN_BACKPACK)
var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(H)
var/obj/item/implant/weapons_auth/W = new
W.implant(H)
var/obj/item/implant/explosive/E = new/obj/item/implant/explosive(H)
var/obj/item/implant/explosive/E = new
E.implant(H)
H.faction |= ROLE_SYNDICATE
H.update_icons()

View File

@@ -599,6 +599,7 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95)
slowdown = 1
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
mutantrace_variation = NO_MUTANTRACE_VARIATION
can_adjust = FALSE
strip_delay = 80
var/next_extinguish = 0

View File

@@ -77,7 +77,7 @@
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
santa = new /mob/living/carbon/human(pick(GLOB.blobstart))
santa.key = C.key
C.transfer_ckey(santa, FALSE)
santa.equipOutfit(/datum/outfit/santa)
santa.update_icons()

View File

@@ -48,7 +48,7 @@
spawned_animals++
SA.key = SG.key
SG.transfer_ckey(SA, FALSE)
SA.grant_all_languages(TRUE)

View File

@@ -23,7 +23,7 @@
I.name = I.dna.real_name
I.updateappearance(mutcolor_update=1)
I.domutcheck()
I.key = C.key
C.transfer_ckey(I, FALSE)
var/datum/antagonist/wizard/master = M.has_antag_datum(/datum/antagonist/wizard)
if(!master.wiz_team)
master.create_wiz_team()

View File

@@ -1,50 +1,51 @@
/*********************Mining Hammer****************/
/obj/item/twohanded/required/kinetic_crusher
/obj/item/twohanded/kinetic_crusher
icon = 'icons/obj/mining.dmi'
icon_state = "mining_hammer1"
item_state = "mining_hammer1"
icon_state = "crusher"
item_state = "crusher0"
lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi'
name = "proto-kinetic crusher"
desc = "An early design of the proto-kinetic accelerator, it is little more than an combination of various mining tools cobbled together, forming a high-tech club. \
While it is an effective mining tool, it did little to aid any but the most skilled and/or suicidal miners against local fauna."
force = 20 //As much as a bone spear, but this is significantly more annoying to carry around due to requiring the use of both hands at all times
force = 0 //You can't hit stuff unless wielded
w_class = WEIGHT_CLASS_BULKY
slot_flags = ITEM_SLOT_BACK
force_unwielded = 20 //It's never not wielded so these are the same
force_unwielded = 0
force_wielded = 20
throwforce = 5
throw_speed = 4
light_range = 7
light_power = 2
armour_penetration = 10
materials = list(MAT_METAL=1150, MAT_GLASS=2075)
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("smashed", "crushed", "cleaved", "chopped", "pulped")
sharpness = IS_SHARP
actions_types = list(/datum/action/item_action/toggle_light)
var/list/trophies = list()
var/charged = TRUE
var/charge_time = 15
var/detonation_damage = 50
var/backstab_bonus = 30
var/light_on = FALSE
var/brightness_on = 7
/obj/item/twohanded/required/kinetic_crusher/Initialize()
/obj/item/twohanded/kinetic_crusher/Initialize()
. = ..()
AddComponent(/datum/component/butchering, 60, 110) //technically it's huge and bulky, but this provides an incentive to use it
/obj/item/twohanded/required/kinetic_crusher/Destroy()
/obj/item/twohanded/kinetic_crusher/Destroy()
QDEL_LIST(trophies)
return ..()
/obj/item/twohanded/required/kinetic_crusher/examine(mob/living/user)
/obj/item/twohanded/kinetic_crusher/examine(mob/living/user)
..()
to_chat(user, "<span class='notice'>Mark a large creature with the destabilizing force, then hit them in melee to do <b>[force + detonation_damage]</b> damage.</span>")
to_chat(user, "<span class='notice'>Does <b>[force + detonation_damage + backstab_bonus]</b> damage if the target is backstabbed, instead of <b>[force + detonation_damage]</b>.</span>")
to_chat(user, "<span class='notice'>Mark a large creature with the destabilizing force, then hit them in melee to do <b>[force_wielded + detonation_damage]</b> damage.</span>")
to_chat(user, "<span class='notice'>Does <b>[force_wielded + detonation_damage + backstab_bonus]</b> damage if the target is backstabbed, instead of <b>[force_wielded + detonation_damage]</b>.</span>")
for(var/t in trophies)
var/obj/item/crusher_trophy/T = t
to_chat(user, "<span class='notice'>It has \a [T] attached, which causes [T.effect_desc()].</span>")
/obj/item/twohanded/required/kinetic_crusher/attackby(obj/item/I, mob/living/user)
/obj/item/twohanded/kinetic_crusher/attackby(obj/item/I, mob/living/user)
if(istype(I, /obj/item/crowbar))
if(LAZYLEN(trophies))
to_chat(user, "<span class='notice'>You remove [src]'s trophies.</span>")
@@ -60,7 +61,11 @@
else
return ..()
/obj/item/twohanded/required/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user)
/obj/item/twohanded/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user)
if(!wielded)
to_chat(user, "<span class='warning'>[src] is too heavy to use with one hand. You fumble and drop everything.")
user.drop_all_held_items()
return
var/datum/status_effect/crusher_damage/C = target.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
var/target_health = target.health
..()
@@ -71,11 +76,13 @@
if(!QDELETED(C) && !QDELETED(target))
C.total_damage += target_health - target.health //we did some damage, but let's not assume how much we did
/obj/item/twohanded/required/kinetic_crusher/afterattack(atom/target, mob/living/user, proximity_flag, clickparams)
/obj/item/twohanded/kinetic_crusher/afterattack(atom/target, mob/living/user, proximity_flag, clickparams)
. = ..()
if(istype(target, /obj/item/crusher_trophy))
var/obj/item/crusher_trophy/T = target
T.add_to(src, user)
if(!wielded)
return
if(!proximity_flag && charged)//Mark a target, or mine a tile.
var/turf/proj_turf = user.loc
if(!isturf(proj_turf))
@@ -90,7 +97,7 @@
playsound(user, 'sound/weapons/plasma_cutter.ogg', 100, 1)
D.fire()
charged = FALSE
icon_state = "mining_hammer1_uncharged"
update_icon()
addtimer(CALLBACK(src, .proc/Recharge), charge_time)
return
if(proximity_flag && isliving(target))
@@ -122,12 +129,37 @@
if(user && lavaland_equipment_pressure_check(get_turf(user))) //CIT CHANGE - makes sure below only happens in low pressure environments
user.adjustStaminaLoss(-30)//CIT CHANGE - makes crushers heal stamina
/obj/item/twohanded/required/kinetic_crusher/proc/Recharge()
/obj/item/twohanded/kinetic_crusher/proc/Recharge()
if(!charged)
charged = TRUE
icon_state = "mining_hammer1"
update_icon()
playsound(src.loc, 'sound/weapons/kenetic_reload.ogg', 60, 1)
/obj/item/twohanded/kinetic_crusher/ui_action_click(mob/user, actiontype)
light_on = !light_on
playsound(user, 'sound/weapons/empty.ogg', 100, TRUE)
update_brightness(user)
update_icon()
/obj/item/twohanded/kinetic_crusher/proc/update_brightness(mob/user = null)
if(light_on)
set_light(brightness_on)
else
set_light(0)
/obj/item/twohanded/kinetic_crusher/update_icon()
..()
cut_overlays()
if(!charged)
add_overlay("[icon_state]_uncharged")
if(light_on)
add_overlay("[icon_state]_lit")
spawn(1)
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
item_state = "crusher[wielded]"
//destablizing force
/obj/item/projectile/destabilizer
name = "destabilizing force"
@@ -138,7 +170,7 @@
flag = "bomb"
range = 6
log_override = TRUE
var/obj/item/twohanded/required/kinetic_crusher/hammer_synced
var/obj/item/twohanded/kinetic_crusher/hammer_synced
/obj/item/projectile/destabilizer/Destroy()
hammer_synced = null
@@ -177,12 +209,12 @@
return "errors"
/obj/item/crusher_trophy/attackby(obj/item/A, mob/living/user)
if(istype(A, /obj/item/twohanded/required/kinetic_crusher))
if(istype(A, /obj/item/twohanded/kinetic_crusher))
add_to(A, user)
else
..()
/obj/item/crusher_trophy/proc/add_to(obj/item/twohanded/required/kinetic_crusher/H, mob/living/user)
/obj/item/crusher_trophy/proc/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
for(var/t in H.trophies)
var/obj/item/crusher_trophy/T = t
if(istype(T, denied_type) || istype(src, T.denied_type))
@@ -194,7 +226,7 @@
to_chat(user, "<span class='notice'>You attach [src] to [H].</span>")
return TRUE
/obj/item/crusher_trophy/proc/remove_from(obj/item/twohanded/required/kinetic_crusher/H, mob/living/user)
/obj/item/crusher_trophy/proc/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
forceMove(get_turf(H))
H.trophies -= src
return TRUE
@@ -281,12 +313,12 @@
/obj/item/crusher_trophy/legion_skull/effect_desc()
return "a kinetic crusher to recharge <b>[bonus_value*0.1]</b> second\s faster"
/obj/item/crusher_trophy/legion_skull/add_to(obj/item/twohanded/required/kinetic_crusher/H, mob/living/user)
/obj/item/crusher_trophy/legion_skull/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
. = ..()
if(.)
H.charge_time -= bonus_value
/obj/item/crusher_trophy/legion_skull/remove_from(obj/item/twohanded/required/kinetic_crusher/H, mob/living/user)
/obj/item/crusher_trophy/legion_skull/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
. = ..()
if(.)
H.charge_time += bonus_value
@@ -339,7 +371,7 @@
/obj/item/crusher_trophy/demon_claws/effect_desc()
return "melee hits to do <b>[bonus_value * 0.2]</b> more damage and heal you for <b>[bonus_value * 0.1]</b>, with <b>5X</b> effect on mark detonation"
/obj/item/crusher_trophy/demon_claws/add_to(obj/item/twohanded/required/kinetic_crusher/H, mob/living/user)
/obj/item/crusher_trophy/demon_claws/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
. = ..()
if(.)
H.force += bonus_value * 0.2
@@ -347,7 +379,7 @@
H.force_wielded += bonus_value * 0.2
H.detonation_damage += bonus_value * 0.8
/obj/item/crusher_trophy/demon_claws/remove_from(obj/item/twohanded/required/kinetic_crusher/H, mob/living/user)
/obj/item/crusher_trophy/demon_claws/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
. = ..()
if(.)
H.force -= bonus_value * 0.2

View File

@@ -30,7 +30,7 @@
new /datum/data/mining_equipment("500 Point Transfer Card", /obj/item/card/mining_point_card/mp500, 500),
new /datum/data/mining_equipment("Tracking Implant Kit", /obj/item/storage/box/minertracker, 600),
new /datum/data/mining_equipment("Jaunter", /obj/item/wormhole_jaunter, 750),
new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/twohanded/required/kinetic_crusher, 750),
new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/twohanded/kinetic_crusher, 750),
new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/gun/energy/kinetic_accelerator, 750),
new /datum/data/mining_equipment("Survival Medipen", /obj/item/reagent_containers/hypospray/medipen/survival, 750),
new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/storage/firstaid/brute, 800),
@@ -172,7 +172,7 @@
new /obj/item/stack/marker_beacon/thirty(drop_location)
if("Crusher Kit")
new /obj/item/extinguisher/mini(drop_location)
new /obj/item/twohanded/required/kinetic_crusher(drop_location)
new /obj/item/twohanded/kinetic_crusher(drop_location)
if("Mining Conscription Kit")
new /obj/item/storage/backpack/duffelbag/mining_conscript(drop_location)

View File

@@ -49,7 +49,7 @@
toggle_mode_action.Grant(src)
var/datum/action/innate/minedrone/dump_ore/dump_ore_action = new()
dump_ore_action.Grant(src)
var/obj/item/implant/radio/mining/imp = new(src)
var/obj/item/implant/radio/mining/imp = new
imp.implant(src)
access_card = new /obj/item/card/id(src)

File diff suppressed because it is too large Load Diff

View File

@@ -558,7 +558,7 @@
/datum/sprite_accessory/mam_tails_animated/horse
name = "Horse"
icon_state = "Horse"
icon_state = "horse"
color_src = HAIR
/datum/sprite_accessory/mam_tails/husky

View File

@@ -260,16 +260,16 @@ Transfer_mind is there to check if mob is being deleted/not going to have a body
Works together with spawning an observer, noted above.
*/
/mob/proc/ghostize(can_reenter_corpse = 1)
if(key)
if(!cmptext(copytext(key,1,2),"@")) // Skip aghosts.
stop_sound_channel(CHANNEL_HEARTBEAT) //Stop heartbeat sounds because You Are A Ghost Now
var/mob/dead/observer/ghost = new(src) // Transfer safety to observer spawning proc.
SStgui.on_transfer(src, ghost) // Transfer NanoUIs.
ghost.can_reenter_corpse = can_reenter_corpse
ghost.can_reenter_round = (can_reenter_corpse && !suiciding)
ghost.key = key
return ghost
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE)
if(!key || cmptext(copytext(key,1,2),"@") || (!special && SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special) & COMPONENT_BLOCK_GHOSTING))
return //mob has no key, is an aghost or some component hijacked.
stop_sound_channel(CHANNEL_HEARTBEAT) //Stop heartbeat sounds because You Are A Ghost Now
var/mob/dead/observer/ghost = new(src) // Transfer safety to observer spawning proc.
SStgui.on_transfer(src, ghost) // Transfer NanoUIs.
ghost.can_reenter_corpse = can_reenter_corpse
ghost.can_reenter_round = (can_reenter_corpse && !suiciding)
transfer_ckey(ghost, FALSE)
return ghost
/*
This is the proc mobs get to turn into a ghost. Forked from ghostize due to compatibility issues.
@@ -280,6 +280,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set name = "Ghost"
set desc = "Relinquish your life and enter the land of the dead."
if(SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, (stat == DEAD) ? TRUE : FALSE, FALSE) & COMPONENT_BLOCK_GHOSTING)
return
// CITADEL EDIT
if(istype(loc, /obj/machinery/cryopod))
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
@@ -306,6 +309,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set name = "Ghost"
set desc = "Relinquish your life and enter the land of the dead."
if(SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, FALSE, FALSE) & COMPONENT_BLOCK_GHOSTING)
return
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
if(response != "Ghost")
return
@@ -348,7 +354,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return
client.change_view(CONFIG_GET(string/default_view))
SStgui.on_transfer(src, mind.current) // Transfer NanoUIs.
mind.current.key = key
transfer_ckey(mind.current, FALSE)
return 1
/mob/dead/observer/proc/notify_cloning(var/message, var/sound, var/atom/source, flashwindow = TRUE)
@@ -628,7 +634,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(src, "<span class='warning'>Someone has taken this body while you were choosing!</span>")
return 0
target.key = key
transfer_ckey(target, FALSE)
target.faction = list("neutral")
return 1

View File

@@ -42,7 +42,7 @@
if(brainmob.mind)
brainmob.mind.transfer_to(C)
else
C.key = brainmob.key
brainmob.transfer_ckey(C)
QDEL_NULL(brainmob)

View File

@@ -87,7 +87,7 @@
var/atom/xeno_loc = get_turf(owner)
var/mob/living/carbon/alien/larva/new_xeno = new(xeno_loc)
new_xeno.key = ghost.key
ghost.transfer_ckey(new_xeno, FALSE)
SEND_SOUND(new_xeno, sound('sound/voice/hiss5.ogg',0,0,0,100)) //To get the player's attention
new_xeno.canmove = 0 //so we don't move during the bursting animation
new_xeno.notransform = 1

View File

@@ -13,6 +13,10 @@
if(!no_bodyparts)
spread_bodyparts(no_brain, no_organs)
for(var/X in implants)
var/obj/item/implant/I = X
qdel(I)
spawn_gibs(no_bodyparts)
qdel(src)

View File

@@ -912,7 +912,7 @@
if(mind)
mind.transfer_to(new_mob)
else
new_mob.key = key
transfer_ckey(new_mob)
for(var/para in hasparasites())
var/mob/living/simple_animal/hostile/guardian/G = para

View File

@@ -357,8 +357,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
return message
/mob/living/proc/radio(message, message_mode, list/spans, language)
var/obj/item/implant/radio/imp = locate() in src
if(imp && imp.radio.on)
var/obj/item/implant/radio/imp = locate() in implants
if(imp?.radio.on)
if(message_mode == MODE_HEADSET)
imp.radio.talk_into(src, message, , spans, language)
return ITALICS | REDUCE_RANGE

View File

@@ -192,7 +192,7 @@
/mob/proc/makePAI(delold)
var/obj/item/paicard/card = new /obj/item/paicard(get_turf(src))
var/mob/living/silicon/pai/pai = new /mob/living/silicon/pai(card)
pai.key = key
transfer_ckey(pai)
pai.name = name
card.setPersonality(pai)
if(delold)

View File

@@ -915,7 +915,7 @@ Pass a positive integer as an argument to override a bot's default speed.
if(mind && paicard.pai)
mind.transfer_to(paicard.pai)
else if(paicard.pai)
paicard.pai.key = key
transfer_ckey(paicard.pai)
else
ghostize(0) // The pAI card that just got ejected was dead.
key = null

View File

@@ -160,7 +160,7 @@
if(mind)
mind.transfer_to(R, 1)
else
R.key = key
transfer_ckey(R)
qdel(src)

View File

@@ -61,5 +61,5 @@
var/obj/item/new_hat = new hat_type(D)
D.equip_to_slot_or_del(new_hat, SLOT_HEAD)
D.flags_1 |= (flags_1 & ADMIN_SPAWNED_1)
D.key = user.key
user.transfer_ckey(D, FALSE)
qdel(src)

View File

@@ -49,7 +49,7 @@
. = ..()
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, internal_storage)
hidden_uplink.telecrystals = 30
var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(src)
var/obj/item/implant/weapons_auth/W = new
W.implant(src)
/mob/living/simple_animal/drone/snowflake

View File

@@ -429,9 +429,9 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
to_chat(G, "<span class='holoparasite'>Your user reset you, and your body was taken over by a ghost. Looks like they weren't happy with your performance.</span>")
to_chat(src, "<span class='holoparasite bold'>Your <font color=\"[G.namedatum.colour]\">[G.real_name]</font> has been successfully reset.</span>")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(G)])")
G.ghostize(0)
G.ghostize(FALSE)
G.setthemename(G.namedatum.theme) //give it a new color, to show it's a new person
G.key = C.key
C.transfer_ckey(G)
G.reset = 1
switch(G.namedatum.theme)
if("tech")

View File

@@ -90,7 +90,7 @@
if(key)
to_chat(user, "<span class='notice'>Someone else already took this spider.</span>")
return 1
key = user.key
user.transfer_ckey(src, FALSE)
return 1
//nursemaids - these create webs and eggs

View File

@@ -585,7 +585,7 @@ Difficulty: Very Hard
var/be_helper = alert("Become a Lightgeist? (Warning, You can no longer be cloned!)",,"Yes","No")
if(be_helper == "Yes" && !QDELETED(src) && isobserver(user))
var/mob/living/simple_animal/hostile/lightgeist/W = new /mob/living/simple_animal/hostile/lightgeist(get_turf(loc))
W.key = user.key
user.transfer_ckey(W, FALSE)
/obj/machinery/anomalous_crystal/helpers/Topic(href, href_list)
@@ -649,7 +649,7 @@ Difficulty: Very Hard
L.heal_overall_damage(heal_power, heal_power)
new /obj/effect/temp_visual/heal(get_turf(target), "#80F5FF")
/mob/living/simple_animal/hostile/lightgeist/ghostize()
/mob/living/simple_animal/hostile/lightgeist/ghostize(can_reenter_corpse = TRUE, send_the_signal = TRUE)
. = ..()
if(.)
death()

View File

@@ -127,7 +127,7 @@
var/client/C = L.client
SSmedals.UnlockMedal("Boss [BOSS_KILL_MEDAL]", C)
SSmedals.UnlockMedal("[medaltype] [BOSS_KILL_MEDAL]", C)
if(crusher_kill && istype(L.get_active_held_item(), /obj/item/twohanded/required/kinetic_crusher))
if(crusher_kill && istype(L.get_active_held_item(), /obj/item/twohanded/kinetic_crusher))
SSmedals.UnlockMedal("[medaltype] [BOSS_KILL_MEDAL_CRUSHER]", C)
SSmedals.SetScore(BOSS_SCORE, C, 1)
SSmedals.SetScore(score_type, C, 1)

View File

@@ -46,7 +46,8 @@
fireball.human_req = 0
fireball.player_lock = 0
AddSpell(fireball)
implants += new /obj/item/implant/exile(src)
var/obj/item/implant/exile/I = new
I.implant(src, null, TRUE)
mm = new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile
mm.clothes_req = 0

View File

@@ -916,7 +916,7 @@
if(mind)
mind.transfer_to(G)
else
G.key = key
transfer_ckey(G)
..(gibbed)
/mob/living/simple_animal/parrot/Poly/proc/Read_Memory()

View File

@@ -198,7 +198,7 @@
if(src.mind)
src.mind.transfer_to(new_slime)
else
new_slime.key = src.key
transfer_ckey(new_slime)
qdel(src)
else
to_chat(src, "<i>I am not ready to reproduce yet...</i>")

View File

@@ -444,7 +444,13 @@
// M.Login() //wat
return
/mob/proc/transfer_ckey(mob/new_mob, send_signal = TRUE)
if(!ckey)
return FALSE
if(send_signal)
SEND_SIGNAL(src, COMSIG_MOB_KEY_CHANGE, new_mob, src)
new_mob.ckey = ckey
return TRUE
/mob/verb/cancel_camera()
set name = "Cancel Camera View"

View File

@@ -429,8 +429,8 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
var/mob/dead/observer/C = pick(candidates)
to_chat(M, "Your mob has been taken over by a ghost!")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(M)])")
M.ghostize(0)
M.key = C.key
M.ghostize(FALSE, TRUE)
C.transfer_ckey(M, FALSE)
return TRUE
else
to_chat(M, "There were no ghosts willing to take control.")

View File

@@ -53,7 +53,7 @@
if(mind && isliving(M))
mind.transfer_to(M, 1) // second argument to force key move to new mob
else
M.key = key
transfer_ckey(M)
if(delete_old_mob)
QDEL_IN(src, 1)

View File

@@ -382,7 +382,7 @@
mind.active = FALSE
mind.transfer_to(R)
else if(transfer_after)
R.key = key
transfer_ckey(R)
R.apply_pref_name("cyborg")
@@ -401,7 +401,7 @@
qdel(src)
//human -> alien
/mob/living/carbon/human/proc/Alienize()
/mob/living/carbon/human/proc/Alienize(mind_transfer = TRUE)
if (notransform)
return
for(var/obj/item/W in src)
@@ -425,13 +425,16 @@
new_xeno = new /mob/living/carbon/alien/humanoid/drone(loc)
new_xeno.a_intent = INTENT_HARM
new_xeno.key = key
if(mind && mind_transfer)
mind.transfer_to(new_xeno)
else
transfer_ckey(new_xeno)
to_chat(new_xeno, "<B>You are now an alien.</B>")
. = new_xeno
qdel(src)
/mob/living/carbon/human/proc/slimeize(reproduce as num)
/mob/living/carbon/human/proc/slimeize(reproduce, mind_transfer = TRUE)
if (notransform)
return
for(var/obj/item/W in src)
@@ -457,20 +460,26 @@
else
new_slime = new /mob/living/simple_animal/slime(loc)
new_slime.a_intent = INTENT_HARM
new_slime.key = key
if(mind && mind_transfer)
mind.transfer_to(new_slime)
else
transfer_ckey(new_slime)
to_chat(new_slime, "<B>You are now a slime. Skreee!</B>")
. = new_slime
qdel(src)
/mob/proc/become_overmind(starting_points = 60)
/mob/proc/become_overmind(starting_points = 60, mind_transfer = FALSE)
var/mob/camera/blob/B = new /mob/camera/blob(get_turf(src), starting_points)
B.key = key
if(mind && mind_transfer)
mind.transfer_to(B)
else
transfer_ckey(B)
. = B
qdel(src)
/mob/living/carbon/human/proc/corgize()
/mob/living/carbon/human/proc/corgize(mind_transfer = TRUE)
if (notransform)
return
for(var/obj/item/W in src)
@@ -485,13 +494,16 @@
var/mob/living/simple_animal/pet/dog/corgi/new_corgi = new /mob/living/simple_animal/pet/dog/corgi (loc)
new_corgi.a_intent = INTENT_HARM
new_corgi.key = key
if(mind && mind_transfer)
mind.transfer_to(new_corgi)
else
transfer_ckey(new_corgi)
to_chat(new_corgi, "<B>You are now a Corgi. Yap Yap!</B>")
. = new_corgi
qdel(src)
/mob/living/carbon/proc/gorillize()
/mob/living/carbon/proc/gorillize(mind_transfer = TRUE)
if(notransform)
return
@@ -509,22 +521,22 @@
invisibility = INVISIBILITY_MAXIMUM
var/mob/living/simple_animal/hostile/gorilla/new_gorilla = new (get_turf(src))
new_gorilla.a_intent = INTENT_HARM
if(mind)
if(mind && mind_transfer)
mind.transfer_to(new_gorilla)
else
new_gorilla.key = key
transfer_ckey(new_gorilla)
to_chat(new_gorilla, "<B>You are now a gorilla. Ooga ooga!</B>")
. = new_gorilla
qdel(src)
/mob/living/carbon/human/Animalize()
/mob/living/carbon/human/Animalize(mind_transfer = TRUE)
var/list/mobtypes = typesof(/mob/living/simple_animal)
var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") in mobtypes
if(!safe_animal(mobpath))
to_chat(usr, "<span class='danger'>Sorry but this mob type is currently unavailable.</span>")
var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") as null|anything in mobtypes
if(!mobpath)
return
if(mind)
mind_transfer = alert("Want to transfer their mind into the new mob", "Mind Transfer", "Yes", "No") == "Yes" ? TRUE : FALSE
if(notransform)
return
@@ -532,8 +544,8 @@
dropItemToGround(W)
regenerate_icons()
notransform = 1
canmove = 0
notransform = TRUE
canmove = FALSE
icon = null
invisibility = INVISIBILITY_MAXIMUM
@@ -541,8 +553,10 @@
qdel(t)
var/mob/new_mob = new mobpath(src.loc)
new_mob.key = key
if(mind && mind_transfer)
mind.transfer_to(new_mob)
else
transfer_ckey(new_mob)
new_mob.a_intent = INTENT_HARM
@@ -550,59 +564,23 @@
. = new_mob
qdel(src)
/mob/proc/Animalize()
/mob/proc/Animalize(mind_transfer = TRUE)
var/list/mobtypes = typesof(/mob/living/simple_animal)
var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") in mobtypes
if(!safe_animal(mobpath))
to_chat(usr, "<span class='danger'>Sorry but this mob type is currently unavailable.</span>")
var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") as null|anything in mobtypes
if(!mobpath)
return
if(mind)
mind_transfer = alert("Want to transfer their mind into the new mob", "Mind Transfer", "Yes", "No") == "Yes" ? TRUE : FALSE
var/mob/new_mob = new mobpath(src.loc)
new_mob.key = key
if(mind && mind_transfer)
mind.transfer_to(new_mob)
else
transfer_ckey(new_mob)
new_mob.a_intent = INTENT_HARM
to_chat(new_mob, "You feel more... animalistic")
. = new_mob
qdel(src)
/* Certain mob types have problems and should not be allowed to be controlled by players.
*
* This proc is here to force coders to manually place their mob in this list, hopefully tested.
* This also gives a place to explain -why- players shouldnt be turn into certain mobs and hopefully someone can fix them.
*/
/mob/proc/safe_animal(MP)
//Bad mobs! - Remember to add a comment explaining what's wrong with the mob
if(!MP)
return 0 //Sanity, this should never happen.
if(ispath(MP, /mob/living/simple_animal/hostile/construct))
return 0 //Verbs do not appear for players.
//Good mobs!
if(ispath(MP, /mob/living/simple_animal/pet/cat))
return 1
if(ispath(MP, /mob/living/simple_animal/pet/dog/corgi))
return 1
if(ispath(MP, /mob/living/simple_animal/crab))
return 1
if(ispath(MP, /mob/living/simple_animal/hostile/carp))
return 1
if(ispath(MP, /mob/living/simple_animal/hostile/mushroom))
return 1
if(ispath(MP, /mob/living/simple_animal/shade))
return 1
if(ispath(MP, /mob/living/simple_animal/hostile/killertomato))
return 1
if(ispath(MP, /mob/living/simple_animal/mouse))
return 1 //It is impossible to pull up the player panel for mice (Fixed! - Nodrak)
if(ispath(MP, /mob/living/simple_animal/hostile/bear))
return 1 //Bears will auto-attack mobs, even if they're player controlled (Fixed! - Nodrak)
if(ispath(MP, /mob/living/simple_animal/parrot))
return 1 //Parrots are no longer unfinished! -Nodrak
//Not in here? Must be untested!
return 0

View File

@@ -329,6 +329,12 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
if(power)
soundloop.volume = min(40, (round(power/100)/50)+1) // 5 +1 volume per 20 power. 2500 power is max
if(isclosedturf(T))
var/turf/did_it_melt = T.Melt()
if(!isclosedturf(did_it_melt)) //In case some joker finds way to place these on indestructible walls
visible_message("<span class='warning'>[src] melts through [T]!</span>")
return
//Ok, get the air from the turf
var/datum/gas_mixture/env = T.return_air()

View File

@@ -125,12 +125,6 @@
else
cut_overlays()
/obj/machinery/computer/pandemic/proc/eject_beaker()
if(beaker)
beaker.forceMove(drop_location())
beaker = null
update_icon()
/obj/machinery/computer/pandemic/ui_interact(mob/user, ui_key = "main", datum/tgui/ui, force_open = FALSE, datum/tgui/master_ui, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -165,7 +159,7 @@
return
switch(action)
if("eject_beaker")
eject_beaker()
replace_beaker(usr)
. = TRUE
if("empty_beaker")
if(beaker)
@@ -174,7 +168,7 @@
if("empty_eject_beaker")
if(beaker)
beaker.reagents.clear_reagents()
eject_beaker()
replace_beaker(usr)
. = TRUE
if("rename_disease")
var/id = get_virus_id_by_index(text2num(params["index"]))
@@ -234,18 +228,32 @@
. = TRUE //no afterattack
if(stat & (NOPOWER|BROKEN))
return
if(beaker)
to_chat(user, "<span class='warning'>A container is already loaded into [src]!</span>")
var/obj/item/reagent_containers/B = I
if(!user.transferItemToLoc(B, src))
return
if(!user.transferItemToLoc(I, src))
return
beaker = I
replace_beaker(user, B)
to_chat(user, "<span class='notice'>You insert [I] into [src].</span>")
update_icon()
else
return ..()
/obj/machinery/computer/pandemic/AltClick(mob/living/user)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
replace_beaker(user)
return
/obj/machinery/computer/pandemic/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
if(beaker)
beaker.forceMove(drop_location())
if(user && Adjacent(user) && !issiliconoradminghost(user))
user.put_in_hands(beaker)
if(new_beaker)
beaker = new_beaker
else
beaker = null
update_icon()
return TRUE
/obj/machinery/computer/pandemic/on_deconstruction()
eject_beaker()
replace_beaker(usr)
. = ..()

View File

@@ -325,7 +325,7 @@
if(SLIME_ACTIVATE_MAJOR)
var/turf/open/T = get_turf(user)
if(istype(T))
T.atmos_spawn_air("nitrogen=40;TEMP=2.7")
T.atmos_spawn_air("n2=40;TEMP=2.7")
to_chat(user, "<span class='warning'>You activate [src], and icy air bursts out of your skin!</span>")
return 900
@@ -681,7 +681,7 @@
var/list/candidates = pollCandidatesForMob("Do you want to play as [SM.name]?", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, SM, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
SM.key = C.key
C.transfer_ckey(SM, FALSE)
SM.mind.enslave_mind_to_creator(user)
SM.sentience_act()
to_chat(SM, "<span class='warning'>All at once it makes sense: you know what you are and who you are! Self awareness is yours!</span>")
@@ -705,7 +705,7 @@
desc = "A miraculous chemical mix that grants human like intelligence to living beings. It has been modified with Syndicate technology to also grant an internal radio implant to the target and authenticate with identification systems."
/obj/item/slimepotion/slime/sentience/nuclear/after_success(mob/living/user, mob/living/simple_animal/SM)
var/obj/item/implant/radio/syndicate/imp = new(src)
var/obj/item/implant/radio/syndicate/imp = new
imp.implant(SM, user)
SM.access_card = new /obj/item/card/id/syndicate(SM)
@@ -969,7 +969,7 @@
to_chat(user, "<span class='notice'>You feed the potion to [M].</span>")
to_chat(M, "<span class='notice'>Your mind tingles as you are fed the potion. You can hear radio waves now!</span>")
var/obj/item/implant/radio/slime/imp = new(src)
var/obj/item/implant/radio/slime/imp = new
imp.implant(M, user)
qdel(src)

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