Merge branch 'master' into FERMICHEMCurTweaks
This commit is contained in:
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -2246,6 +2246,13 @@
|
||||
contains = list(/mob/living/simple_animal/hostile/retaliate/goat)
|
||||
crate_name = "goat crate"
|
||||
|
||||
/datum/supply_pack/critter/goose
|
||||
name = "Goose Crate"
|
||||
desc = "Angry and violent birds. Evil, evil creatures."
|
||||
cost = 2500
|
||||
contains = list(/mob/living/simple_animal/hostile/retaliate/goose)
|
||||
crate_name = "goose crate"
|
||||
|
||||
/datum/supply_pack/critter/monkey
|
||||
name = "Monkey Cube Crate"
|
||||
desc = "Stop monkeying around! Contains seven monkey cubes. Just add water!"
|
||||
|
||||
@@ -41,6 +41,13 @@
|
||||
var/dynamic_hair_suffix = ""//head > mask for head hair
|
||||
var/dynamic_fhair_suffix = ""//mask > head for facial hair
|
||||
|
||||
//basically a restriction list.
|
||||
var/list/species_restricted = null
|
||||
//Basically syntax is species_restricted = list("Species Name","Species Name")
|
||||
//Add a "exclude" string to do the opposite, making it only only species listed that can't wear it.
|
||||
//You append this to clothing objects.
|
||||
|
||||
|
||||
/obj/item/clothing/Initialize()
|
||||
. = ..()
|
||||
if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE))
|
||||
@@ -338,3 +345,38 @@ BLIND // can't see anything
|
||||
deconstruct(FALSE)
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
//Species-restricted clothing check. - Thanks Oraclestation, BS13, /vg/station etc.
|
||||
/obj/item/clothing/mob_can_equip(mob/M, slot, disable_warning = TRUE)
|
||||
|
||||
//if we can't equip the item anyway, don't bother with species_restricted (also cuts down on spam)
|
||||
if(!..())
|
||||
return FALSE
|
||||
|
||||
// Skip species restriction checks on non-equipment slots
|
||||
if(slot in list(SLOT_IN_BACKPACK, SLOT_L_STORE, SLOT_R_STORE))
|
||||
return TRUE
|
||||
|
||||
if(species_restricted && ishuman(M))
|
||||
|
||||
var/wearable = null
|
||||
var/exclusive = null
|
||||
var/mob/living/carbon/human/H = M
|
||||
|
||||
if("exclude" in species_restricted) //TURNS IT INTO A BLACKLIST - AKA ALL MINUS SPECIES LISTED.
|
||||
exclusive = TRUE
|
||||
|
||||
if(H.dna.species)
|
||||
if(exclusive)
|
||||
if(!(H.dna.species.name in species_restricted))
|
||||
wearable = TRUE
|
||||
else
|
||||
if(H.dna.species.name in species_restricted)
|
||||
wearable = TRUE
|
||||
|
||||
if(!wearable)
|
||||
to_chat(M, "<span class='warning'>Your species cannot wear [src].</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -162,7 +162,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
var/list/row = src.connectionHistory[i]
|
||||
if (!row || row.len < 3 || (!row["ckey"] || !row["compid"] || !row["ip"])) //Passed malformed history object
|
||||
return
|
||||
if (world.IsBanned(row["ckey"], row["compid"], row["ip"], real_bans_only=TRUE))
|
||||
if (world.IsBanned(row["ckey"], row["ip"], row["compid"], real_bans_only=TRUE))
|
||||
found = row
|
||||
break
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
|
||||
//Returns if a certain item can be equipped to a certain slot.
|
||||
// Currently invalid for two-handed items - call obj/item/mob_can_equip() instead.
|
||||
/mob/proc/can_equip(obj/item/I, slot, disable_warning = 0)
|
||||
/mob/proc/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
return FALSE
|
||||
|
||||
/mob/proc/can_put_in_hand(I, hand_index)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -865,7 +865,7 @@
|
||||
piggyback(target)
|
||||
return
|
||||
//If you dragged them to you and you're aggressively grabbing try to fireman carry them
|
||||
else if(user != target && can_be_firemanned(target))
|
||||
else if(user != target)
|
||||
fireman_carry(target)
|
||||
return
|
||||
. = ..()
|
||||
|
||||
@@ -9,9 +9,29 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/name // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever
|
||||
var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race
|
||||
|
||||
var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows
|
||||
var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows
|
||||
|
||||
var/list/offset_features = list(OFFSET_UNIFORM = list(0,0), OFFSET_ID = list(0,0), OFFSET_GLOVES = list(0,0), OFFSET_GLASSES = list(0,0), OFFSET_EARS = list(0,0), OFFSET_SHOES = list(0,0), OFFSET_S_STORE = list(0,0), OFFSET_FACEMASK = list(0,0), OFFSET_HEAD = list(0,0), OFFSET_FACE = list(0,0), OFFSET_BELT = list(0,0), OFFSET_BACK = list(0,0), OFFSET_SUIT = list(0,0), OFFSET_NECK = list(0,0))
|
||||
//Species Icon Drawing Offsets - Pixel X, Pixel Y, Aka X = Horizontal and Y = Vertical, from bottom left corner
|
||||
var/list/offset_features = list(
|
||||
OFFSET_UNIFORM = list(0,0),
|
||||
OFFSET_ID = list(0,0),
|
||||
OFFSET_GLOVES = list(0,0),
|
||||
OFFSET_GLASSES = list(0,0),
|
||||
OFFSET_EARS = list(0,0),
|
||||
OFFSET_SHOES = list(0,0),
|
||||
OFFSET_S_STORE = list(0,0),
|
||||
OFFSET_FACEMASK = list(0,0),
|
||||
OFFSET_HEAD = list(0,0),
|
||||
OFFSET_EYES = list(0,0),
|
||||
OFFSET_LIPS = list(0,0),
|
||||
OFFSET_BELT = list(0,0),
|
||||
OFFSET_BACK = list(0,0),
|
||||
OFFSET_HAIR = list(0,0),
|
||||
OFFSET_FHAIR = list(0,0),
|
||||
OFFSET_SUIT = list(0,0),
|
||||
OFFSET_NECK = list(0,0),
|
||||
OFFSET_MUTPARTS = list(0,0)
|
||||
)
|
||||
|
||||
var/hair_color // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color
|
||||
var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent.
|
||||
@@ -401,6 +421,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
|
||||
facial_overlay.alpha = hair_alpha
|
||||
|
||||
if(OFFSET_FHAIR in H.dna.species.offset_features)
|
||||
facial_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FHAIR][1]
|
||||
facial_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FHAIR][2]
|
||||
|
||||
standing += facial_overlay
|
||||
|
||||
if(H.head)
|
||||
@@ -458,9 +482,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
else
|
||||
hair_overlay.color = forced_colour
|
||||
hair_overlay.alpha = hair_alpha
|
||||
if(OFFSET_FACE in H.dna.species.offset_features)
|
||||
hair_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
|
||||
hair_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
|
||||
|
||||
if(OFFSET_HAIR in H.dna.species.offset_features)
|
||||
hair_overlay.pixel_x += H.dna.species.offset_features[OFFSET_HAIR][1]
|
||||
hair_overlay.pixel_y += H.dna.species.offset_features[OFFSET_HAIR][2]
|
||||
|
||||
if(hair_overlay.icon)
|
||||
standing += hair_overlay
|
||||
|
||||
@@ -481,9 +507,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
if(H.lip_style && (LIPS in species_traits))
|
||||
var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[H.lip_style]", -BODY_LAYER)
|
||||
lip_overlay.color = H.lip_color
|
||||
if(OFFSET_FACE in H.dna.species.offset_features)
|
||||
lip_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
|
||||
lip_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
|
||||
|
||||
if(OFFSET_LIPS in H.dna.species.offset_features)
|
||||
lip_overlay.pixel_x += H.dna.species.offset_features[OFFSET_LIPS][1]
|
||||
lip_overlay.pixel_y += H.dna.species.offset_features[OFFSET_LIPS][2]
|
||||
|
||||
standing += lip_overlay
|
||||
|
||||
// eyes
|
||||
@@ -496,9 +524,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER)
|
||||
if((EYECOLOR in species_traits) && has_eyes)
|
||||
eye_overlay.color = "#" + H.eye_color
|
||||
if(OFFSET_FACE in H.dna.species.offset_features)
|
||||
eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
|
||||
eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
|
||||
|
||||
if(OFFSET_EYES in H.dna.species.offset_features)
|
||||
eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_EYES][1]
|
||||
eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_EYES][2]
|
||||
|
||||
standing += eye_overlay
|
||||
|
||||
//Underwear, Undershirts & Socks
|
||||
@@ -851,6 +881,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
for(var/index=1, index<=husklist.len, index++)
|
||||
husklist[index] = husklist[index]/255
|
||||
accessory_overlay.color = husklist
|
||||
|
||||
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
|
||||
accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
|
||||
accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2]
|
||||
|
||||
standing += accessory_overlay
|
||||
|
||||
if(S.hasinner)
|
||||
@@ -863,6 +898,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
if(S.center)
|
||||
inner_accessory_overlay = center_image(inner_accessory_overlay, S.dimension_x, S.dimension_y)
|
||||
|
||||
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
|
||||
inner_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
|
||||
inner_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2]
|
||||
|
||||
standing += inner_accessory_overlay
|
||||
|
||||
if(S.extra) //apply the extra overlay, if there is one
|
||||
@@ -903,6 +942,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
|
||||
if(HORNCOLOR)
|
||||
extra_accessory_overlay.color = "#[H.horn_color]"
|
||||
|
||||
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
|
||||
extra_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
|
||||
extra_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2]
|
||||
|
||||
standing += extra_accessory_overlay
|
||||
|
||||
if(S.extra2) //apply the extra overlay, if there is one
|
||||
@@ -937,6 +981,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
extra2_accessory_overlay.color = "#[H.hair_color]"
|
||||
if(HORNCOLOR)
|
||||
extra2_accessory_overlay.color = "#[H.horn_color]"
|
||||
|
||||
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
|
||||
extra2_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
|
||||
extra2_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2]
|
||||
|
||||
standing += extra2_accessory_overlay
|
||||
|
||||
|
||||
@@ -1343,9 +1392,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/obj/item/organ/cyberimp/chest/thrusters/T = H.getorganslot(ORGAN_SLOT_THRUSTERS)
|
||||
if(!istype(J) && istype(C))
|
||||
J = C.jetpack
|
||||
if(istype(J) && J.full_speed && J.allow_thrust(0.005, H)) //Prevents stacking
|
||||
if(istype(J) && J.full_speed && J.allow_thrust(0.01, H)) //Prevents stacking
|
||||
. -= 0.4
|
||||
else if(istype(T) && T.allow_thrust(0.005, H))
|
||||
else if(istype(T) && T.allow_thrust(0.01, H))
|
||||
. -= 0.4
|
||||
|
||||
if(!ignoreslow && gravity)
|
||||
|
||||
@@ -709,9 +709,9 @@ generate/load female uniform sprites matching all previously decided variables
|
||||
if(lip_style && (LIPS in dna.species.species_traits))
|
||||
var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[lip_style]", -BODY_LAYER)
|
||||
lip_overlay.color = lip_color
|
||||
if(OFFSET_FACE in dna.species.offset_features)
|
||||
lip_overlay.pixel_x += dna.species.offset_features[OFFSET_FACE][1]
|
||||
lip_overlay.pixel_y += dna.species.offset_features[OFFSET_FACE][2]
|
||||
if(OFFSET_LIPS in dna.species.offset_features)
|
||||
lip_overlay.pixel_x += dna.species.offset_features[OFFSET_LIPS][1]
|
||||
lip_overlay.pixel_y += dna.species.offset_features[OFFSET_LIPS][2]
|
||||
add_overlay(lip_overlay)
|
||||
|
||||
// eyes
|
||||
@@ -724,9 +724,9 @@ generate/load female uniform sprites matching all previously decided variables
|
||||
eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER)
|
||||
if((EYECOLOR in dna.species.species_traits) && has_eyes)
|
||||
eye_overlay.color = "#" + eye_color
|
||||
if(OFFSET_FACE in dna.species.offset_features)
|
||||
eye_overlay.pixel_x += dna.species.offset_features[OFFSET_FACE][1]
|
||||
eye_overlay.pixel_y += dna.species.offset_features[OFFSET_FACE][2]
|
||||
if(OFFSET_EYES in dna.species.offset_features)
|
||||
eye_overlay.pixel_x += dna.species.offset_features[OFFSET_EYES][1]
|
||||
eye_overlay.pixel_y += dna.species.offset_features[OFFSET_EYES][2]
|
||||
add_overlay(eye_overlay)
|
||||
|
||||
dna.species.handle_hair(src)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/living/carbon/monkey/can_equip(obj/item/I, slot, disable_warning = 0)
|
||||
/mob/living/carbon/monkey/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
switch(slot)
|
||||
if(SLOT_HANDS)
|
||||
if(get_empty_held_indexes())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -290,7 +290,7 @@
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
else if(istype(W, /obj/item/paicard))
|
||||
insertpai(user, W)
|
||||
else if(istype(W, /obj/item/hemostat) && paicard)
|
||||
else if(W.tool_behaviour == TOOL_HEMOSTAT && paicard)
|
||||
if(open)
|
||||
to_chat(user, "<span class='warning'>Close the access panel before manipulating the personality slot!</span>")
|
||||
else
|
||||
@@ -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
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
return 0
|
||||
|
||||
|
||||
/mob/living/simple_animal/drone/can_equip(obj/item/I, slot)
|
||||
/mob/living/simple_animal/drone/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
switch(slot)
|
||||
if(SLOT_HEAD)
|
||||
if(head)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/dextrous/can_equip(obj/item/I, slot)
|
||||
/mob/living/simple_animal/hostile/guardian/dextrous/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
switch(slot)
|
||||
if(SLOT_GENERC_DEXTROUS_STORAGE)
|
||||
if(internal_storage)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#define GOOSE_SATIATED 50
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goose
|
||||
name = "goose"
|
||||
desc = "It's loose"
|
||||
icon_state = "goose" // sprites by cogwerks from goonstation, used with permission
|
||||
icon_living = "goose"
|
||||
icon_dead = "goose_dead"
|
||||
mob_biotypes = list(MOB_ORGANIC, MOB_BEAST)
|
||||
speak_chance = 0
|
||||
turns_per_move = 5
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = 2)
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "kicks"
|
||||
emote_taunt = list("hisses")
|
||||
taunt_chance = 30
|
||||
speed = 0
|
||||
maxHealth = 25
|
||||
health = 25
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 5
|
||||
attacktext = "pecks"
|
||||
attack_sound = "goose"
|
||||
speak_emote = list("honks")
|
||||
faction = list("neutral")
|
||||
attack_same = TRUE
|
||||
gold_core_spawnable = HOSTILE_SPAWN
|
||||
var/random_retaliate = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goose/handle_automated_movement()
|
||||
. = ..()
|
||||
if(prob(5) && random_retaliate == TRUE)
|
||||
Retaliate()
|
||||
@@ -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
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
|
||||
/obj/item/stock_parts/cell/secborg
|
||||
name = "security borg rechargeable D battery"
|
||||
maxcharge = 1750 //35/17/8 disabler/laser/taser shots.
|
||||
maxcharge = 1250 //25/12/6 disabler/laser/taser shots.
|
||||
materials = list(MAT_GLASS=40)
|
||||
|
||||
/obj/item/stock_parts/cell/secborg/empty/Initialize()
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -25,3 +25,6 @@
|
||||
fire_sound = 'sound/weapons/taser2.ogg'
|
||||
harmful = FALSE
|
||||
click_cooldown_override = 3.5
|
||||
|
||||
/obj/item/ammo_casing/energy/disabler/secborg
|
||||
e_cost = 50
|
||||
@@ -277,12 +277,12 @@
|
||||
..()
|
||||
if(istype(A, /obj/item/ammo_box) || istype(A, /obj/item/ammo_casing))
|
||||
chamber_round()
|
||||
if(A.tool_behaviour == TOOL_SAW || istype(A, /obj/item/gun/energy/plasmacutter))
|
||||
sawoff(user)
|
||||
if(istype(A, /obj/item/melee/transforming/energy))
|
||||
var/obj/item/melee/transforming/energy/W = A
|
||||
if(W.active)
|
||||
sawoff(user)
|
||||
if(istype(A, /obj/item/circular_saw) || istype(A, /obj/item/gun/energy/plasmacutter))
|
||||
sawoff(user)
|
||||
|
||||
/obj/item/gun/ballistic/revolver/doublebarrel/attack_self(mob/living/user)
|
||||
var/num_unloaded = 0
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/riot/attackby(obj/item/A, mob/user, params)
|
||||
..()
|
||||
if(istype(A, /obj/item/circular_saw) || istype(A, /obj/item/gun/energy/plasmacutter))
|
||||
if(A.tool_behaviour == TOOL_SAW || istype(A, /obj/item/gun/energy/plasmacutter))
|
||||
sawoff(user)
|
||||
if(istype(A, /obj/item/melee/transforming/energy))
|
||||
var/obj/item/melee/transforming/energy/W = A
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
name = "cyborg disabler"
|
||||
desc = "An integrated disabler that draws from a cyborg's power cell. This one contains a limiter to prevent the cyborg's power cell from overheating."
|
||||
can_charge = FALSE
|
||||
ammo_type = list(/obj/item/ammo_casing/energy/disabler/secborg)
|
||||
selfcharge = EGUN_SELFCHARGE_BORG
|
||||
cell_type = /obj/item/stock_parts/cell/secborg
|
||||
charge_delay = 5
|
||||
|
||||
@@ -1,14 +1,46 @@
|
||||
//Generates a markdown txt file for use with the wiki
|
||||
|
||||
/proc/find_reagent(input)
|
||||
. = FALSE
|
||||
if(GLOB.chemical_reagents_list[input]) //prefer IDs!
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[input]
|
||||
return R
|
||||
else
|
||||
for(var/X in GLOB.chemical_reagents_list)
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[X]
|
||||
if(input == replacetext(lowertext(R.name), " ", ""))
|
||||
return R
|
||||
if(input == replacetext(lowertext(R.id), " ", ""))
|
||||
return R
|
||||
|
||||
|
||||
|
||||
|
||||
/client/proc/generate_wikichem_list()
|
||||
set name = "Generate Wikichems"
|
||||
set category = "Debug"
|
||||
set desc = "Generate a huge loglist of all the chems. Do not click unless you want lag."
|
||||
|
||||
message_admins("Someone pressed the lag button. (Generate Wikichems)")
|
||||
to_chat(usr, "Generating list")
|
||||
var/prefix = "|Name | Reagents | Reaction vars | Description | Chem properties |\n|---|---|---|-----------|---|\n"
|
||||
|
||||
|
||||
var/prefix = "|Name | Reagents | Reaction vars | Description | Chem properties |\n|---|---|---|-----------|---|\n"
|
||||
var/input_reagent = replacetext(lowertext(input("Input the name/id of a reagent to get it's description on it's own, or leave blank to parse every chem.", "Input") as text), " ", "") //95% of the time, the reagent id is a lowercase/no spaces version of the name
|
||||
if(input_reagent)
|
||||
var/input_reagent2 = find_reagent(input_reagent)
|
||||
if(!input_reagent2)
|
||||
to_chat(usr, "Unable to find reagent, stopping proc.")
|
||||
var/single_parse = generate_chemwiki_line(input_reagent2, input_reagent, FALSE)
|
||||
text2file(single_parse, "[GLOB.log_directory]/chem_parse.md")
|
||||
to_chat(usr, "[single_parse].")
|
||||
|
||||
single_parse = generate_chemwiki_line(input_reagent2, input_reagent, FALSE)
|
||||
text2file(single_parse, "[GLOB.log_directory]/chem_parse.md")
|
||||
to_chat(usr, "[single_parse].")
|
||||
to_chat(usr, "Saved line to (wherever your root folder is, i.e. where the DME is)/[GLOB.log_directory]/chem_parse.md OR use the Get Current Logs verb under the Admin tab. (if you click Open, and it does nothing, that's because you've not set a .md default program! Try downloading it instead, and use that file to set a default program! Also have a cute day.)")
|
||||
//Do things here
|
||||
return
|
||||
to_chat(usr, "Generating big list")
|
||||
message_admins("Someone pressed the lag button. (Generate Wikichems)")
|
||||
///datum/reagent/medicine, /datum/reagent/toxin, /datum/reagent/consumable, /datum/reagent/plantnutriment, /datum/reagent/uranium,
|
||||
///datum/reagent/colorful_reagent, /datum/reagent/mutationtoxin, /datum/reagent/fermi, /datum/reagent/drug, /datum/reagent/impure
|
||||
|
||||
@@ -33,7 +65,7 @@
|
||||
var/alco = ""
|
||||
var/grinded = ""
|
||||
var/blob = ""
|
||||
//var/impure
|
||||
var/impure = ""
|
||||
|
||||
//Chem_dispencer
|
||||
var/list/dispensable_reagents = list(
|
||||
@@ -129,36 +161,46 @@
|
||||
"applejack"
|
||||
)
|
||||
|
||||
|
||||
var/breakout = FALSE
|
||||
for(var/i = 1, i <= 2, i+=1)
|
||||
for(var/X in GLOB.chemical_reagents_list)
|
||||
R = GLOB.chemical_reagents_list[X]
|
||||
if(!R.description) //No description? It's not worth my time.
|
||||
continue
|
||||
|
||||
for(var/Y in dispensable_reagents) //Why do you have to do this
|
||||
if(R.id == Y)
|
||||
basic += generate_chemwiki_line(R, X, processCR)
|
||||
breakout = TRUE
|
||||
continue
|
||||
|
||||
for(var/Y in components)
|
||||
if(R.id == Y)
|
||||
upgraded += generate_chemwiki_line(R, X, processCR)
|
||||
breakout = TRUE
|
||||
continue
|
||||
|
||||
for(var/Y in dispence_drinks)
|
||||
if(R.id == Y)
|
||||
drinks += generate_chemwiki_line(R, X, processCR)
|
||||
breakout = TRUE
|
||||
continue
|
||||
|
||||
for(var/Y in dispence_alco)
|
||||
if(R.id == Y)
|
||||
alco += generate_chemwiki_line(R, X, processCR)
|
||||
breakout = TRUE
|
||||
continue
|
||||
|
||||
for(var/Y in grind)
|
||||
if(R.id == Y)
|
||||
grinded += generate_chemwiki_line(R, X, processCR)
|
||||
breakout = TRUE
|
||||
continue
|
||||
|
||||
if(breakout)
|
||||
breakout = FALSE
|
||||
continue
|
||||
|
||||
if(istype(R, /datum/reagent/medicine))
|
||||
medicine += generate_chemwiki_line(R, X, processCR)
|
||||
@@ -190,10 +232,8 @@
|
||||
else if(istype(R, /datum/reagent/blob))
|
||||
blob += generate_chemwiki_line(R, X, processCR)
|
||||
|
||||
/* when merged
|
||||
else if(istype(R, /datum/reagent/impure))
|
||||
impure += generate_chemwiki_line(R, X, processCR)
|
||||
*/
|
||||
|
||||
else
|
||||
remainder += generate_chemwiki_line(R, X, processCR)
|
||||
@@ -206,8 +246,8 @@
|
||||
|
||||
to_chat(usr, "finished chems")
|
||||
|
||||
var/wholeString = ("\n# DISPENCEABLE REAGENTS\n\n[prefix][basic]\n\n# COMPONENT REAGENTS\n\n[prefix][upgraded]\n\n# GRINDABLE REAGENTS\n\n[prefix][grinded]\n")
|
||||
wholeString += ("\n# MEDICINE:\n\n[prefix][medicine]\n\n# TOXIN:\n\n[prefix][toxin]\n\n# DRUGS\n\n[prefix][drug]\n\n# FERMI\n\nThese chems lie on the cutting edge of chemical technology, and as such are not recommended for beginners!\n\n[prefix][fermi]\n\n# GENERAL REAGENTS\n\n[prefix][remainder]\n\n# DISPENCEABLE SOFT DRINKS\n\n[prefix][drinks]\n\n# DISPENCEABLE HARD DRINKS\n\n[prefix][alco]\n\n# CONSUMABLE\n\n[prefix][consumable]\n\n# PLANTS\n\n[prefix][plant]\n\n# URANIUM\n\n[prefix][uranium]\n\n# COLOURS\n\n[prefix][colours]\n\n# RACE MUTATIONS\n\n[prefix][muta]\n\n\n# BLOB REAGENTS\n\n[prefix][blob]\n")
|
||||
var/wholeString = ("\n# DISPENCEABLE REAGENTS\n\n[prefix][basic]\n\n# COMPONENT REAGENTS\n\n[prefix][upgraded]\n\n# GROUND REAGENTS\n\n[prefix][grinded]\n")
|
||||
wholeString += ("\n# MEDICINE:\n\n[prefix][medicine]\n\n# TOXIN:\n\n[prefix][toxin]\n\n# DRUGS\n\n[prefix][drug]\n\n# FERMI\n\nThese chems lie on the cutting edge of chemical technology, and as such are not recommended for beginners!\n\n[prefix][fermi]\n\n# IMPURE REAGENTS\n\n[prefix][impure]\n\n# GENERAL REAGENTS\n\n[prefix][remainder]\n\n# DISPENCEABLE SOFT DRINKS\n\n[prefix][drinks]\n\n# DISPENCEABLE HARD DRINKS\n\n[prefix][alco]\n\n# CONSUMABLE\n\n[prefix][consumable]\n\n# PLANTS\n\n[prefix][plant]\n\n# URANIUM\n\n[prefix][uranium]\n\n# COLOURS\n\n[prefix][colours]\n\n# RACE MUTATIONS\n\n[prefix][muta]\n\n\n# BLOB REAGENTS\n\n[prefix][blob]\n")
|
||||
|
||||
prefix = "|Name | Reagents | Reaction vars | Description |\n|---|---|---|----------|\n"
|
||||
var/CRparse = ""
|
||||
@@ -257,6 +297,8 @@
|
||||
//Temp, Explosions and pH
|
||||
if(CR)
|
||||
outstring += "<ul>[(CR.FermiChem?"<li>Min react temp: [CR.OptimalTempMin]K</li>":"[(CR.required_temp?"<li>Min react temp: [CR.required_temp]K</li>":"")]")] [(CR.FermiChem?"<li>Explosion_temp: [CR.ExplodeTemp]K</li>":"")] [(CR.FermiChem?"<li>pH range: [max((CR.OptimalpHMin - CR.ReactpHLim), 0)] to [min((CR.OptimalpHMax + CR.ReactpHLim), 14)]</li>":"")] "
|
||||
if(CR.FermiChem)
|
||||
outstring += "[(CR.PurityMin?"<li>Min explosive purity: [CR.PurityMin]</li>":"")] [(CR.FermiExplode?"<li>Special explosion: Yes</li>":"")]"
|
||||
else
|
||||
outstring += ""
|
||||
|
||||
@@ -288,17 +330,15 @@
|
||||
outstring += " | "
|
||||
|
||||
//Description, OD, Addict, Meta
|
||||
outstring += "[R.description] | <ul><li>Metabolism_rate: [R.metabolization_rate/2]u/s</li> [(R.overdose_threshold?"<li>Overdose: [R.overdose_threshold]u</li>":"")] [(R.addiction_threshold?"<li>Addiction: [R.addiction_threshold]u</li>":"")] "
|
||||
outstring += "[R.description] | <ul><li>Metabolism rate: [R.metabolization_rate/2]u/s</li> [(R.overdose_threshold?"<li>Overdose: [R.overdose_threshold]u</li>":"")] [(R.addiction_threshold?"<li>Addiction: [R.addiction_threshold]u</li>":"")] "
|
||||
|
||||
if(R.impure_chem != "fermiTox" && R.impure_chem)
|
||||
if(R.impure_chem && R.impure_chem != "fermiTox")
|
||||
R3 = GLOB.chemical_reagents_list[R.impure_chem]
|
||||
outstring += "<li>Impure chem:<a href=\"#[R3.name]\">[R3.name]</a></li>"
|
||||
|
||||
if(R.inverse_chem != "fermiTox" && R.inverse_chem)
|
||||
if(R.inverse_chem && R.impure_chem != "fermiTox")
|
||||
R3 = GLOB.chemical_reagents_list[R.inverse_chem]
|
||||
outstring += "<li>Inverse chem:<a href=\"#[R3.name]\">[R3.name]</a></li> "
|
||||
|
||||
|
||||
outstring += "<li>Inverse chem:<a href=\"#[R3.name]\">[R3.name]</a></li> [(R3.inverse_chem_val?"<li>Inverse purity: [R3.inverse_chem_val]</li>":"")] "
|
||||
|
||||
if(CR)
|
||||
if(CR.required_container)
|
||||
@@ -307,16 +347,9 @@
|
||||
outstring += "<li>Required container: [I.name]</li>"*/
|
||||
outstring += "<li>Required container: [CR.required_container]</li>"
|
||||
|
||||
if(CR.FermiChem)
|
||||
outstring += "<li>Minimum purity: [CR.PurityMin]</li> [(CR.FermiExplode?"<li>Special explosion: Yes</li>":"")]"
|
||||
|
||||
|
||||
outstring += "</ul>|\n"
|
||||
return outstring
|
||||
|
||||
|
||||
|
||||
|
||||
//Generate the big list of reaction based reactions.
|
||||
//|Name | Reagents | Reaction vars | Description | Chem properties
|
||||
/proc/generate_chemreactwiki_line(datum/chemical_reaction/CR)
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
var/targetVol = 0 //the target volume, i.e. the total amount that can be created during a fermichem reaction.
|
||||
var/reactedVol = 0 //how much of the reagent is reacted during a fermireaction
|
||||
var/fermiIsReacting = FALSE //that prevents multiple reactions from occurring (i.e. add_reagent calls to process_reactions(), this stops any extra reactions.)
|
||||
var/fermiReactID = null //ID of the chem being made during a fermireaction, kept here so it's cache isn't lost between loops/procs.
|
||||
var/fermiReactID //ID of the chem being made during a fermireaction, kept here so it's cache isn't lost between loops/procs.
|
||||
|
||||
/datum/reagents/New(maximum=100, new_flags)
|
||||
maximum_volume = maximum
|
||||
@@ -365,7 +365,7 @@
|
||||
|
||||
|
||||
/datum/reagents/proc/handle_reactions()//HERE EDIT HERE THE MAIN REACTION
|
||||
if(fermiIsReacting == TRUE)
|
||||
if(fermiIsReacting) //This ARRESTS other reactions. If you don't want this, then remove it.
|
||||
return
|
||||
|
||||
if(reagents_holder_flags & NO_REACT)
|
||||
@@ -404,7 +404,7 @@
|
||||
|
||||
|
||||
for(var/B in cached_required_reagents)
|
||||
if(!has_reagent(B, cached_required_reagents[B]))
|
||||
if(!has_reagent(B, cached_required_reagents[B]*CHEMICAL_QUANTISATION_LEVEL))//Allows vols at less than 1 to react.
|
||||
break
|
||||
total_matching_reagents++
|
||||
for(var/B in cached_required_catalysts)
|
||||
@@ -464,7 +464,7 @@
|
||||
//Temperature plays into a larger role too.
|
||||
var/datum/chemical_reaction/C = selected_reaction
|
||||
|
||||
if (C.FermiChem == TRUE && !continue_reacting)
|
||||
if (C.FermiChem && !continue_reacting)
|
||||
if (chem_temp > C.ExplodeTemp) //This is first to ensure explosions.
|
||||
var/datum/chemical_reaction/Ferm = selected_reaction
|
||||
fermiIsReacting = FALSE
|
||||
@@ -472,31 +472,28 @@
|
||||
Ferm.FermiExplode(src, my_atom, volume = total_volume, temp = chem_temp, pH = pH)
|
||||
return 0
|
||||
|
||||
//This is just to calc the on_reaction multiplier, and is a candidate for removal.
|
||||
for(var/B in cached_required_reagents)
|
||||
multiplier = min(multiplier, round((get_reagent_amount(B) / cached_required_reagents[B]), CHEMICAL_QUANTISATION_LEVEL))
|
||||
multiplier = min(multiplier, round((get_reagent_amount(B) / cached_required_reagents[B]), 0.0001))
|
||||
for(var/P in selected_reaction.results)
|
||||
targetVol = cached_results[P]*multiplier
|
||||
|
||||
if( (chem_temp <= C.ExplodeTemp) && (chem_temp >= C.OptimalTempMin))
|
||||
if( (pH >= (C.OptimalpHMin - C.ReactpHLim)) && (pH <= (C.OptimalpHMax + C.ReactpHLim)) )//To prevent pointless reactions
|
||||
|
||||
if (fermiIsReacting == TRUE)
|
||||
return 0
|
||||
else
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
selected_reaction.on_reaction(src, my_atom, multiplier)
|
||||
fermiIsReacting = TRUE
|
||||
fermiReactID = selected_reaction
|
||||
reaction_occurred = 1
|
||||
|
||||
else //It's a little bit of a confusing nest, but esstentially we check if it's a fermireaction, then temperature, then pH. If this is true, the remainer of this handler is run.
|
||||
return 0 //If pH is out of range
|
||||
if(!((chem_temp <= C.ExplodeTemp) && (chem_temp >= C.OptimalTempMin)))
|
||||
return 0 //Not hot enough
|
||||
if(! ((pH >= (C.OptimalpHMin - C.ReactpHLim)) && (pH <= (C.OptimalpHMax + C.ReactpHLim)) ))//To prevent pointless reactions
|
||||
return 0
|
||||
if (fermiIsReacting)
|
||||
return 0
|
||||
else
|
||||
return 0 //If not hot enough
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
selected_reaction.on_reaction(src, my_atom, multiplier)
|
||||
fermiIsReacting = TRUE
|
||||
fermiReactID = selected_reaction
|
||||
reaction_occurred = 1
|
||||
|
||||
//Standard reaction mechanics:
|
||||
else
|
||||
if (C.FermiChem == TRUE)//Just to make sure, should only proc when grenades are combining.
|
||||
if (C.FermiChem)//Just to make sure, should only proc when grenades are combining.
|
||||
if (chem_temp > C.ExplodeTemp) //To allow fermigrenades
|
||||
var/datum/chemical_reaction/fermi/Ferm = selected_reaction
|
||||
fermiIsReacting = FALSE
|
||||
@@ -551,38 +548,43 @@
|
||||
var/multiplier = INFINITY
|
||||
|
||||
for(var/B in cached_required_reagents) //
|
||||
multiplier = min(multiplier, round((get_reagent_amount(B) / cached_required_reagents[B]), 0.001))
|
||||
if (multiplier == 0)
|
||||
multiplier = min(multiplier, round((get_reagent_amount(B) / cached_required_reagents[B]), 0.0001))
|
||||
if (multiplier == 0)//clarity
|
||||
fermiEnd()
|
||||
return
|
||||
|
||||
for(var/P in C.required_catalysts)
|
||||
if(!has_reagent(P))
|
||||
fermiEnd()
|
||||
return
|
||||
for(var/P in cached_results)
|
||||
targetVol = cached_results[P]*multiplier
|
||||
|
||||
if (fermiIsReacting == FALSE)
|
||||
if (!fermiIsReacting)
|
||||
CRASH("Fermi has refused to stop reacting even though we asked her nicely.")
|
||||
|
||||
if (chem_temp > C.OptimalTempMin && fermiIsReacting == TRUE)//To prevent pointless reactions
|
||||
if( (pH >= (C.OptimalpHMin - C.ReactpHLim)) && (pH <= (C.OptimalpHMax + C.ReactpHLim)) )
|
||||
if (reactedVol < targetVol)
|
||||
reactedVol = fermiReact(fermiReactID, chem_temp, pH, reactedVol, targetVol, cached_required_reagents, cached_results, multiplier)
|
||||
else//Volume is used up
|
||||
fermiEnd()
|
||||
return
|
||||
else//pH is out of range
|
||||
fermiEnd()
|
||||
return
|
||||
else//Temperature is too low, or reaction has stopped.
|
||||
if (!(chem_temp >= C.OptimalTempMin))//To prevent pointless reactions
|
||||
fermiEnd()
|
||||
return
|
||||
|
||||
if (!( (pH >= (C.OptimalpHMin - C.ReactpHLim)) && (pH <= (C.OptimalpHMax + C.ReactpHLim)) )) //if pH is too far out, (could possibly allow reactions at this point, after the reaction has started, but make purity = 0)
|
||||
fermiEnd()
|
||||
return
|
||||
|
||||
reactedVol = fermiReact(fermiReactID, chem_temp, pH, reactedVol, targetVol, cached_required_reagents, cached_results, multiplier)
|
||||
if(round(reactedVol, CHEMICAL_QUANTISATION_LEVEL) == round(targetVol, CHEMICAL_QUANTISATION_LEVEL))
|
||||
fermiEnd()
|
||||
if(!reactedVol)//Maybe unnessicary.
|
||||
fermiEnd()
|
||||
return
|
||||
|
||||
/datum/reagents/proc/fermiEnd()
|
||||
var/datum/chemical_reaction/C = fermiReactID
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
fermiIsReacting = FALSE
|
||||
reactedVol = 0
|
||||
targetVol = 0
|
||||
//Cap off values
|
||||
for(var/datum/reagent/R in reagent_list)
|
||||
R.volume = round(R.volume, CHEMICAL_QUANTISATION_LEVEL)//To prevent runaways.
|
||||
//pH check, handled at the end to reduce calls.
|
||||
if(istype(my_atom, /obj/item/reagent_containers))
|
||||
var/obj/item/reagent_containers/RC = my_atom
|
||||
@@ -593,7 +595,6 @@
|
||||
handle_reactions()
|
||||
update_total()
|
||||
//Reaction sounds and words
|
||||
playsound(get_turf(my_atom), C.mix_sound, 80, 1)
|
||||
var/list/seen = viewers(5, get_turf(my_atom))
|
||||
var/iconhtml = icon2html(my_atom, seen)
|
||||
for(var/mob/M in seen)
|
||||
@@ -650,16 +651,18 @@
|
||||
//ONLY WORKS FOR ONE PRODUCT AT THE MOMENT
|
||||
//Calculate how much product to make and how much reactant to remove factors..
|
||||
for(var/P in cached_results)
|
||||
//stepChemAmmount = CLAMP(((deltaT * multiplier), 0, ((targetVol - reactedVol)/cached_results[P])) //used to have multipler, now it does
|
||||
stepChemAmmount = (multiplier*cached_results[P])
|
||||
if (stepChemAmmount >= C.RateUpLim)
|
||||
stepChemAmmount = (C.RateUpLim)
|
||||
if (stepChemAmmount > C.RateUpLim)
|
||||
stepChemAmmount = C.RateUpLim
|
||||
addChemAmmount = deltaT * stepChemAmmount
|
||||
if (addChemAmmount >= (targetVol - reactedVol))
|
||||
addChemAmmount = (targetVol - reactedVol)
|
||||
if (addChemAmmount < CHEMICAL_QUANTISATION_LEVEL)
|
||||
addChemAmmount = CHEMICAL_QUANTISATION_LEVEL
|
||||
removeChemAmmount = (addChemAmmount/cached_results[P])
|
||||
//keep limited.
|
||||
addChemAmmount = round(addChemAmmount, CHEMICAL_QUANTISATION_LEVEL)
|
||||
removeChemAmmount = round(removeChemAmmount, CHEMICAL_QUANTISATION_LEVEL)
|
||||
//This is kept for future bugtesters.
|
||||
//message_admins("Reaction vars: PreReacted: [reactedVol] of [targetVol]. deltaT [deltaT], multiplier [multiplier], Step [stepChemAmmount], uncapped Step [deltaT*(multiplier*cached_results[P])], addChemAmmount [addChemAmmount], removeFactor [removeChemAmmount] Pfactor [cached_results[P]], adding [addChemAmmount]")
|
||||
|
||||
@@ -672,7 +675,7 @@
|
||||
for(var/P in cached_results)
|
||||
SSblackbox.record_feedback("tally", "chemical_reaction", addChemAmmount, P)//log
|
||||
SSblackbox.record_feedback("tally", "fermi_chem", addChemAmmount, P)
|
||||
add_reagent(P, (addChemAmmount), null, cached_temp, purity)//add reagent function!! I THINK I can do this:
|
||||
add_reagent(P, (addChemAmmount), null, cached_temp, purity)
|
||||
TotalStep += addChemAmmount//for multiple products
|
||||
//Above should reduce yeild based on holder purity.
|
||||
//Purity Check
|
||||
@@ -681,9 +684,9 @@
|
||||
if (R.purity < C.PurityMin)//If purity is below the min, blow it up.
|
||||
fermiIsReacting = FALSE
|
||||
SSblackbox.record_feedback("tally", "fermi_chem", 1, ("[P] explosion"))
|
||||
C.FermiExplode(src, my_atom, (reactedVol+targetVol), cached_temp, pH)
|
||||
C.FermiExplode(src, my_atom, (total_volume), cached_temp, pH)
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
return 0
|
||||
return
|
||||
|
||||
C.FermiCreate(src, addChemAmmount, purity)//proc that calls when step is done
|
||||
|
||||
@@ -698,11 +701,11 @@
|
||||
//go to explode proc
|
||||
fermiIsReacting = FALSE
|
||||
SSblackbox.record_feedback("tally", "fermi_chem", 1, ("[C] explosions"))
|
||||
C.FermiExplode(src, my_atom, (reactedVol+targetVol), chem_temp, pH)
|
||||
C.FermiExplode(src, my_atom, (total_volume), chem_temp, pH)
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
return
|
||||
|
||||
//Make sure things are limited.
|
||||
//Make sure things are limited, but superacids/bases can push forward the reaction
|
||||
pH = CLAMP(pH, 0, 14)
|
||||
|
||||
//return said amount to compare for next step.
|
||||
@@ -717,6 +720,8 @@
|
||||
if (R in cached_reagents)
|
||||
cachedPurity += R.purity
|
||||
i++
|
||||
if(!i)//I've never seen it get here with 0, but in case
|
||||
CRASH("No reactants found mid reaction for [fermiReactID]/[C], how it got here is beyond me. Beaker: [holder]")
|
||||
return cachedPurity/i
|
||||
|
||||
/datum/reagents/proc/uncache_purity(id)
|
||||
@@ -758,14 +763,14 @@
|
||||
total_volume = 0
|
||||
for(var/reagent in cached_reagents)
|
||||
var/datum/reagent/R = reagent
|
||||
if(R.volume == 0)
|
||||
if(R.volume <= 0)//For clarity
|
||||
del_reagent(R.id)
|
||||
if((R.volume < 0.01) && !fermiIsReacting)
|
||||
del_reagent(R.id)
|
||||
else
|
||||
total_volume += R.volume
|
||||
if(!reagent_list)
|
||||
pH = 7
|
||||
if(!reagent_list || !total_volume)
|
||||
pH = REAGENT_NORMAL_PH
|
||||
return 0
|
||||
|
||||
/datum/reagents/proc/clear_reagents()
|
||||
@@ -830,7 +835,7 @@
|
||||
if(!isnum(amount) || !amount)
|
||||
return FALSE
|
||||
|
||||
if(amount <= CHEMICAL_QUANTISATION_LEVEL)//To prevent small ammount problems.
|
||||
if(amount < CHEMICAL_QUANTISATION_LEVEL)//To prevent small ammount problems.
|
||||
return FALSE
|
||||
|
||||
var/datum/reagent/D = GLOB.chemical_reagents_list[reagent]
|
||||
@@ -838,7 +843,7 @@
|
||||
WARNING("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])")
|
||||
return FALSE
|
||||
|
||||
if (D.id == "water" && no_react == FALSE && !istype(my_atom, /obj/item/reagent_containers/food)) //Do like an otter, add acid to water, but also don't blow up botany.
|
||||
if (D.id == "water" && !no_react && !istype(my_atom, /obj/item/reagent_containers/food)) //Do like an otter, add acid to water, but also don't blow up botany.
|
||||
if (pH <= 2)
|
||||
SSblackbox.record_feedback("tally", "fermi_chem", 1, "water-acid explosions")
|
||||
var/datum/effect_system/smoke_spread/chem/s = new
|
||||
@@ -881,7 +886,7 @@
|
||||
chem_temp = thermal_energy / (specific_heat * new_total)
|
||||
|
||||
//cacluate reagent based pH shift.
|
||||
if(ignore_pH == TRUE)
|
||||
if(ignore_pH)
|
||||
pH = ((cached_pH * cached_total)+(other_pH * amount))/(cached_total + amount)//should be right
|
||||
else
|
||||
pH = ((cached_pH * cached_total)+(D.pH * amount))/(cached_total + amount)//should be right
|
||||
@@ -960,7 +965,7 @@
|
||||
if((total_volume - amount) <= 0)//Because this can result in 0, I don't want it to crash.
|
||||
pH = 7
|
||||
//In practice this is really confusing and players feel like it randomly melts their beakers, but I'm not sure how else to handle it. We'll see how it goes and I can remove this if it confuses people.
|
||||
else if (ignore_pH == FALSE)
|
||||
else if (!ignore_pH)
|
||||
//if (((pH > R.pH) && (pH <= 7)) || ((pH < R.pH) && (pH >= 7)))
|
||||
pH = (((pH - R.pH) / total_volume) * amount) + pH
|
||||
if(istype(my_atom, /obj/item/reagent_containers/))
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/datum/reagent/impure/fermiTox
|
||||
name = "Chemical Isomers"
|
||||
id = "fermiTox"
|
||||
description = "Toxic chemical isomers made from impure reactions. At low volumes will cause light toxin damage, but as the volume increases, it deals larger amounts, damages the liver, then eventually the heart."
|
||||
description = "Toxic chemical isomers made from impure reactions. At low volumes will cause light toxin damage, but as the volume increases, it deals larger amounts, damages the liver, then eventually the heart. This is default impure chem for all chems, and changes only if stated."
|
||||
data = "merge"
|
||||
color = "FFFFFF"
|
||||
can_synth = FALSE
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
name = "Blood"
|
||||
id = "blood"
|
||||
color = "#C80000" // rgb: 200, 0, 0
|
||||
description = "Blood from a human, or otherwise."
|
||||
metabolization_rate = 5 //fast rate so it disappears fast.
|
||||
taste_description = "iron"
|
||||
taste_mult = 1.3
|
||||
|
||||
@@ -71,8 +71,8 @@
|
||||
/datum/chemical_reaction/synthtissue
|
||||
name = "Synthtissue"
|
||||
id = "synthtissue"
|
||||
results = list("synthtissue" = 0.05)
|
||||
required_reagents = list("synthflesh" = 0.01)
|
||||
results = list("synthtissue" = 5)
|
||||
required_reagents = list("synthflesh" = 1)
|
||||
required_catalysts = list("nutriment" = 0.1)
|
||||
//FermiChem vars:
|
||||
OptimalTempMin = 305 // Lower area of bell curve for determining heat based rate reactions
|
||||
|
||||
@@ -601,63 +601,34 @@
|
||||
|
||||
/datum/design/retractor_adv
|
||||
name = "Advanced Retractor"
|
||||
desc = "A high-class, premium retractor, featuring precision crafted, silver-plated hook-ends and an electrum handle."
|
||||
desc = "An almagation of rods and gears, able to function as both a surgical clamp and retractor. "
|
||||
id = "retractor_adv"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 1500, MAT_GOLD = 1000)
|
||||
build_path = /obj/item/retractor/adv
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
/datum/design/hemostat_adv
|
||||
name = "Advanced Hemostat"
|
||||
desc = "An exceptionally fine pair of arterial forceps. These appear to be plated in electrum and feel soft to the touch."
|
||||
id = "hemostat_adv"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 1000, MAT_GOLD = 1500)
|
||||
build_path = /obj/item/hemostat/adv
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
/datum/design/cautery_adv
|
||||
name = "Electrocautery" //This is based on real-life science.
|
||||
desc = "A high-tech unipolar Electrocauter. This tiny device contains an extremely powerful microbattery that uses arcs of electricity to painlessly sear wounds shut. It seems to recharge with the user's body-heat. Wow!"
|
||||
id = "cautery_adv"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 1000, MAT_GOLD = 1500)
|
||||
build_path = /obj/item/cautery/adv
|
||||
build_path = /obj/item/retractor/advanced
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
/datum/design/surgicaldrill_adv
|
||||
name = "Surgical Autodrill"
|
||||
desc = "With a diamond tip and built-in depth and safety sensors, this drill alerts the user before overpenetrating a patient's skull or tooth. There also appears to be a disable switch."
|
||||
name = "Surgical Laser Drill"
|
||||
desc = "It projects a high power laser used for medical applications."
|
||||
id = "surgicaldrill_adv"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 2500, MAT_GLASS = 2500, MAT_SILVER = 6000, MAT_GOLD = 5500, MAT_DIAMOND = 3500)
|
||||
build_path = /obj/item/surgicaldrill/adv
|
||||
build_path = /obj/item/surgicaldrill/advanced
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
/datum/design/scalpel_adv
|
||||
name = "Precision Scalpel"
|
||||
desc = "A perfectly balanced electrum scalpel with a silicon-coated edge to eliminate wear and tear."
|
||||
name = "Laser Scalpel"
|
||||
desc = "An advanced scalpel which uses laser technology to cut."
|
||||
id = "scalpel_adv"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 1500, MAT_GLASS = 1500, MAT_SILVER = 4000, MAT_GOLD = 2500)
|
||||
build_path = /obj/item/scalpel/adv
|
||||
build_path = /obj/item/scalpel/advanced
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
/datum/design/circular_saw_adv
|
||||
name = "Diamond-Grit Circular Saw"
|
||||
desc = "For those Assistants with REALLY thick skulls."
|
||||
id = "circular_saw_adv"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 7500, MAT_GLASS = 6000, MAT_SILVER = 6500, MAT_GOLD = 7500, MAT_DIAMOND = 4500)
|
||||
build_path = /obj/item/circular_saw/adv
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
/////////////////////////////////////////
|
||||
//////////Alien Surgery Tools////////////
|
||||
@@ -756,7 +727,7 @@
|
||||
research_icon = 'icons/obj/surgery.dmi'
|
||||
research_icon_state = "surgery_any"
|
||||
var/surgery
|
||||
|
||||
|
||||
/datum/design/surgery/experimental_dissection
|
||||
name = "Experimental Dissection"
|
||||
desc = "A surgical procedure which deeply analyzes the biology of a corpse, and automatically adds new findings to the research database."
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
display_name = "Advanced Surgery Tools"
|
||||
description = "Refined and improved redesigns for the run-of-the-mill medical utensils."
|
||||
prereq_ids = list("adv_biotech", "adv_surgery")
|
||||
design_ids = list("drapes", "retractor_adv", "hemostat_adv", "cautery_adv", "surgicaldrill_adv", "scalpel_adv", "circular_saw_adv")
|
||||
design_ids = list("drapes", "retractor_adv", "surgicaldrill_adv", "scalpel_adv")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
export_price = 5000
|
||||
|
||||
|
||||
@@ -325,7 +325,7 @@
|
||||
if(SLIME_ACTIVATE_MAJOR)
|
||||
var/turf/open/T = get_turf(user)
|
||||
if(istype(T))
|
||||
T.atmos_spawn_air("nitrogen=40;TEMP=2.7")
|
||||
T.atmos_spawn_air("n2=40;TEMP=2.7")
|
||||
to_chat(user, "<span class='warning'>You activate [src], and icy air bursts out of your skin!</span>")
|
||||
return 900
|
||||
|
||||
@@ -681,7 +681,7 @@
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as [SM.name]?", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, SM, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
SM.key = C.key
|
||||
C.transfer_ckey(SM, FALSE)
|
||||
SM.mind.enslave_mind_to_creator(user)
|
||||
SM.sentience_act()
|
||||
to_chat(SM, "<span class='warning'>All at once it makes sense: you know what you are and who you are! Self awareness is yours!</span>")
|
||||
@@ -705,7 +705,7 @@
|
||||
desc = "A miraculous chemical mix that grants human like intelligence to living beings. It has been modified with Syndicate technology to also grant an internal radio implant to the target and authenticate with identification systems."
|
||||
|
||||
/obj/item/slimepotion/slime/sentience/nuclear/after_success(mob/living/user, mob/living/simple_animal/SM)
|
||||
var/obj/item/implant/radio/syndicate/imp = new(src)
|
||||
var/obj/item/implant/radio/syndicate/imp = new
|
||||
imp.implant(SM, user)
|
||||
|
||||
SM.access_card = new /obj/item/card/id/syndicate(SM)
|
||||
@@ -969,7 +969,7 @@
|
||||
|
||||
to_chat(user, "<span class='notice'>You feed the potion to [M].</span>")
|
||||
to_chat(M, "<span class='notice'>Your mind tingles as you are fed the potion. You can hear radio waves now!</span>")
|
||||
var/obj/item/implant/radio/slime/imp = new(src)
|
||||
var/obj/item/implant/radio/slime/imp = new
|
||||
imp.implant(M, user)
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -70,12 +70,12 @@ Also, you never added distance checking after target is selected. I've went ahea
|
||||
var/mob/living/caster = user//The wizard/whomever doing the body transferring.
|
||||
|
||||
//MIND TRANSFER BEGIN
|
||||
var/mob/dead/observer/ghost = victim.ghostize(0)
|
||||
var/mob/dead/observer/ghost = victim.ghostize(FALSE, TRUE)
|
||||
caster.mind.transfer_to(victim)
|
||||
|
||||
ghost.mind.transfer_to(caster)
|
||||
if(ghost.key)
|
||||
caster.key = ghost.key //have to transfer the key since the mind was not active
|
||||
ghost.transfer_ckey(caster) //have to transfer the key since the mind was not active
|
||||
qdel(ghost)
|
||||
|
||||
//MIND TRANSFER END
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
/datum/surgery_step/dissection
|
||||
name = "dissection"
|
||||
implements = list(/obj/item/scalpel = 60, /obj/item/kitchen/knife = 30, /obj/item/shard = 15)
|
||||
implements = list(TOOL_SCALPEL = 60, /obj/item/kitchen/knife = 30, /obj/item/shard = 15)
|
||||
time = 125
|
||||
|
||||
/datum/surgery_step/dissection/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
/datum/surgery_step/clamp_bleeders,
|
||||
/datum/surgery_step/brainwash,
|
||||
/datum/surgery_step/close)
|
||||
|
||||
|
||||
species = list(/mob/living/carbon/human)
|
||||
possible_locs = list(BODY_ZONE_HEAD)
|
||||
/datum/surgery/advanced/brainwashing/can_start(mob/user, mob/living/carbon/target)
|
||||
@@ -24,7 +24,7 @@
|
||||
return TRUE
|
||||
/datum/surgery_step/brainwash
|
||||
name = "brainwash"
|
||||
implements = list(/obj/item/hemostat = 85, TOOL_WIRECUTTER = 50, /obj/item/stack/packageWrap = 35, /obj/item/stack/cable_coil = 15)
|
||||
implements = list(TOOL_HEMOSTAT = 85, TOOL_WIRECUTTER = 50, /obj/item/stack/packageWrap = 35, /obj/item/stack/cable_coil = 15)
|
||||
time = 200
|
||||
var/objective
|
||||
/datum/surgery_step/brainwash/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
return TRUE
|
||||
/datum/surgery_step/lobotomize
|
||||
name = "perform lobotomy"
|
||||
implements = list(/obj/item/scalpel = 85, /obj/item/melee/transforming/energy/sword = 55, /obj/item/kitchen/knife = 35,
|
||||
implements = list(TOOL_SCALPEL = 85, /obj/item/melee/transforming/energy/sword = 55, /obj/item/kitchen/knife = 35,
|
||||
/obj/item/shard = 25, /obj/item = 20)
|
||||
time = 100
|
||||
/datum/surgery_step/lobotomize/tool_check(mob/user, obj/item/tool)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
/datum/surgery_step/bionecrosis
|
||||
name = "start bionecrosis"
|
||||
implements = list(/obj/item/hemostat = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15)
|
||||
implements = list(TOOL_HEMOSTAT = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15)
|
||||
implements = list(/obj/item/reagent_containers/syringe = 100, /obj/item/pen = 30)
|
||||
time = 50
|
||||
chems_needed = list("zombiepowder", "rezadone")
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
return FALSE
|
||||
/datum/surgery_step/pacify
|
||||
name = "rewire brain"
|
||||
implements = list(/obj/item/hemostat = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15)
|
||||
implements = list(TOOL_HEMOSTAT = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15)
|
||||
time = 40
|
||||
|
||||
/datum/surgery_step/pacify/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
@@ -37,4 +37,4 @@
|
||||
"<span class='warning'>[user] screws up, causing brain damage!</span>",
|
||||
"[user] completes the surgery on [target]'s brain.")
|
||||
target.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_LOBOTOMY)
|
||||
return FALSE
|
||||
return FALSE
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/datum/surgery_step/reconstruct
|
||||
name = "repair body"
|
||||
implements = list(/obj/item/hemostat = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15)
|
||||
implements = list(TOOL_HEMOSTAT = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15)
|
||||
repeatable = TRUE
|
||||
time = 25
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/datum/surgery/advanced/toxichealing
|
||||
name = "Body Rejuvenation"
|
||||
desc = "A surgical procedure that helps deal with oxygen deprecation, and treat toxic damaged. Works on corpses and alive alike without chemicals."
|
||||
desc = "A surgical procedure that helps deal with oxygen deprivation, and treats parts damaged due to toxic compounds. Works on corpses and alive alike without chemicals."
|
||||
steps = list(/datum/surgery_step/incise,
|
||||
/datum/surgery_step/incise,
|
||||
/datum/surgery_step/retract_skin,
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/datum/surgery_step/toxichealing
|
||||
name = "rejuvenate body"
|
||||
implements = list(/obj/item/hemostat = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15)
|
||||
implements = list(TOOL_HEMOSTAT = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15)
|
||||
repeatable = TRUE
|
||||
time = 25
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
return TRUE
|
||||
/datum/surgery_step/viral_bond
|
||||
name = "viral bond"
|
||||
implements = list(/obj/item/cautery = 100, TOOL_WELDER = 50, /obj/item = 30) // 30% success with any hot item.
|
||||
implements = list(TOOL_CAUTERY = 100, TOOL_WELDER = 50, /obj/item = 30) // 30% success with any hot item.
|
||||
time = 100
|
||||
chems_needed = list("spaceacillin","virusfood","formaldehyde")
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
requires_bodypart_type = 0
|
||||
/datum/surgery_step/sever_limb
|
||||
name = "sever limb"
|
||||
implements = list(/obj/item/scalpel = 100, /obj/item/circular_saw = 100, /obj/item/melee/transforming/energy/sword/cyborg/saw = 100, /obj/item/melee/arm_blade = 80, /obj/item/twohanded/required/chainsaw = 80, /obj/item/mounted_chainsaw = 80, /obj/item/twohanded/fireaxe = 50, /obj/item/hatchet = 40, /obj/item/kitchen/knife/butcher = 25)
|
||||
implements = list(TOOL_SCALPEL = 100, TOOL_SAW = 100, /obj/item/melee/transforming/energy/sword/cyborg/saw = 100, /obj/item/melee/arm_blade = 80, /obj/item/twohanded/required/chainsaw = 80, /obj/item/mounted_chainsaw = 80, /obj/item/twohanded/fireaxe = 50, /obj/item/hatchet = 40, /obj/item/kitchen/knife/butcher = 25)
|
||||
time = 64
|
||||
|
||||
/datum/surgery_step/sever_limb/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
requires_bodypart_type = 0
|
||||
/datum/surgery_step/fix_brain
|
||||
name = "fix brain"
|
||||
implements = list(/obj/item/hemostat = 85, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15) //don't worry, pouring some alcohol on their open brain will get that chance to 100
|
||||
implements = list(TOOL_HEMOSTAT = 85, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15) //don't worry, pouring some alcohol on their open brain will get that chance to 100
|
||||
time = 120 //long and complicated
|
||||
/datum/surgery/brain_surgery/can_start(mob/user, mob/living/carbon/target)
|
||||
var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
//extract brain
|
||||
/datum/surgery_step/extract_core
|
||||
name = "extract core"
|
||||
implements = list(/obj/item/hemostat = 100, TOOL_CROWBAR = 100)
|
||||
implements = list(TOOL_HEMOSTAT = 100, TOOL_CROWBAR = 100)
|
||||
time = 16
|
||||
|
||||
/datum/surgery_step/extract_core/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/datum/surgery/embalming //Fast and easy way to husk bodys
|
||||
name = "Embalming"
|
||||
desc = "A surgical procedure that prevents a corps from producing."
|
||||
desc = "A surgical procedure that prevents a corpse from producing miasma."
|
||||
steps = list(/datum/surgery_step/incise,
|
||||
/datum/surgery_step/embalming,
|
||||
/datum/surgery_step/close)
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
/datum/surgery_step/embalming
|
||||
name = "embalming body"
|
||||
implements = list(/obj/item/hemostat = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15)
|
||||
implements = list(TOOL_HEMOSTAT = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15)
|
||||
implements = list(/obj/item/reagent_containers/syringe = 100, /obj/item/pen = 30)
|
||||
time = 10
|
||||
chems_needed = list("drying_agent", "sterilizine")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user