Merge branch 'master' into Spookytime
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
128
code/datums/components/virtual_reality.dm
Normal file
128
code/datums/components/virtual_reality.dm
Normal 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)
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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] </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 />"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/obj/machinery/computer/prisoner
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ..()
|
||||
@@ -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)"
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
69
code/game/objects/items/implants/implant_radio.dm
Normal file
69
code/game/objects/items/implants/implant_radio.dm
Normal 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
|
||||
@@ -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)"
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
44
code/modules/VR/vr_mob.dm
Normal 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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
spawned_animals++
|
||||
|
||||
SA.key = SG.key
|
||||
SG.transfer_ckey(SA, FALSE)
|
||||
|
||||
SA.grant_all_languages(TRUE)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
if(brainmob.mind)
|
||||
brainmob.mind.transfer_to(C)
|
||||
else
|
||||
C.key = brainmob.key
|
||||
brainmob.transfer_ckey(C)
|
||||
|
||||
QDEL_NULL(brainmob)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
if(mind)
|
||||
mind.transfer_to(R, 1)
|
||||
else
|
||||
R.key = key
|
||||
transfer_ckey(R)
|
||||
qdel(src)
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user