Merge branch 'master' into 91-files-changed-fml
This commit is contained in:
@@ -81,7 +81,7 @@ GLOBAL_PROTECT(admin_verbs_admin)
|
||||
)
|
||||
GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/DB_ban_panel, /client/proc/stickybanpanel))
|
||||
GLOBAL_PROTECT(admin_verbs_ban)
|
||||
GLOBAL_LIST_INIT(admin_verbs_sounds, list(/client/proc/play_local_sound, /client/proc/play_sound, /client/proc/set_round_end_sound))
|
||||
GLOBAL_LIST_INIT(admin_verbs_sounds, list(/client/proc/play_local_sound, /client/proc/play_sound, /client/proc/manual_play_web_sound, /client/proc/set_round_end_sound))
|
||||
GLOBAL_PROTECT(admin_verbs_sounds)
|
||||
GLOBAL_LIST_INIT(admin_verbs_fun, list(
|
||||
/client/proc/cmd_admin_dress,
|
||||
|
||||
@@ -138,6 +138,49 @@
|
||||
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Play Internet Sound")
|
||||
|
||||
/client/proc/manual_play_web_sound()
|
||||
set category = "Fun"
|
||||
set name = "Manual Play Internet Sound"
|
||||
if(!check_rights(R_SOUNDS))
|
||||
return
|
||||
|
||||
var/web_sound_input = input("Enter content stream URL (fetch this from local youtube-dl!)", "Play Internet Sound via direct URL") as text|null
|
||||
if(istext(web_sound_input))
|
||||
if(!length(web_sound_input))
|
||||
log_admin("[key_name(src)] stopped web sound")
|
||||
message_admins("[key_name(src)] stopped web sound")
|
||||
var/mob/M
|
||||
for(var/i in GLOB.player_list)
|
||||
M = i
|
||||
M?.client?.chatOutput?.stopMusic()
|
||||
return
|
||||
else
|
||||
if(web_sound_input && !findtext(web_sound_input, GLOB.is_http_protocol))
|
||||
to_chat(src, "<span class='boldwarning'>BLOCKED: Content URL not using http(s) protocol</span>")
|
||||
return
|
||||
var/freq = input(usr, "What frequency would you like the sound to play at?",, 1) as null|num
|
||||
if(isnull(freq))
|
||||
return
|
||||
if(!freq)
|
||||
freq = 1
|
||||
SSblackbox.record_feedback("nested tally", "played_url", 1, list("[ckey]", "[web_sound_input]"))
|
||||
var/logstr = "[key_name(src)] played web sound at freq [freq]: [web_sound_input]"
|
||||
log_admin(logstr)
|
||||
message_admins(logstr)
|
||||
var/mob/M
|
||||
var/client/C
|
||||
var/datum/chatOutput/O
|
||||
for(var/i in GLOB.player_list)
|
||||
M = i
|
||||
C = M.client
|
||||
if(!(C?.prefs?.toggles & SOUND_MIDI))
|
||||
continue
|
||||
O = C.chatOutput
|
||||
if(!O || O.broken || !O.loaded)
|
||||
continue
|
||||
O.sendMusic(web_sound_input, freq)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Manual Play Internet Sound")
|
||||
|
||||
/client/proc/set_round_end_sound(S as sound)
|
||||
set category = "Fun"
|
||||
set name = "Set Round End Sound"
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
if(objective.completable)
|
||||
var/completion = objective.check_completion()
|
||||
if(completion >= 1)
|
||||
report += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
|
||||
report += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</B></span>"
|
||||
else if(completion <= 0)
|
||||
report += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
win = FALSE
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
set waitfor = FALSE // Don't make on_gain() wait for this function to finish. This lets this code run on the side.
|
||||
var/notice_healing
|
||||
while(owner && !AmFinalDeath()) // owner.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) == src
|
||||
if(owner.current.stat == CONSCIOUS && !poweron_feed && !HAS_TRAIT(owner.current, TRAIT_DEATHCOMA)) // Deduct Blood
|
||||
if(owner.current.stat == CONSCIOUS && !poweron_feed && !HAS_TRAIT(owner.current, TRAIT_FAKEDEATH)) // Deduct Blood
|
||||
AddBloodVolume(passive_blood_drain) // -.1 currently
|
||||
if(HandleHealing(1)) // Heal
|
||||
if(notice_healing == FALSE && owner.current.blood_volume > 0)
|
||||
if(!notice_healing && owner.current.blood_volume > 0)
|
||||
to_chat(owner, "<span class='notice'>The power of your blood begins knitting your wounds...</span>")
|
||||
notice_healing = TRUE
|
||||
else if(notice_healing == TRUE)
|
||||
@@ -25,7 +25,7 @@
|
||||
HandleStarving() // Death
|
||||
HandleDeath() // Standard Update
|
||||
update_hud()// Daytime Sleep in Coffin
|
||||
if(SSticker.mode.is_daylight() && !HAS_TRAIT_FROM(owner.current, TRAIT_DEATHCOMA, "bloodsucker"))
|
||||
if(SSticker.mode.is_daylight() && !HAS_TRAIT_FROM(owner.current, TRAIT_FAKEDEATH, "bloodsucker"))
|
||||
if(istype(owner.current.loc, /obj/structure/closet/crate/coffin))
|
||||
Torpor_Begin()
|
||||
// Wait before next pass
|
||||
@@ -83,7 +83,7 @@
|
||||
// NOTE: Mult of 0 is just a TEST to see if we are injured and need to go into Torpor!
|
||||
//It is called from your coffin on close (by you only)
|
||||
var/actual_regen = regen_rate + additional_regen
|
||||
if(poweron_masquerade == TRUE || owner.current.AmStaked())
|
||||
if(poweron_masquerade|| owner.current.AmStaked())
|
||||
return FALSE
|
||||
if(owner.current.reagents.has_reagent(/datum/reagent/consumable/garlic))
|
||||
return FALSE
|
||||
@@ -101,8 +101,8 @@
|
||||
var/mob/living/carbon/C = owner.current
|
||||
var/costMult = 1 // Coffin makes it cheaper
|
||||
var/fireheal = 0 // BURN: Heal in Coffin while Fakedeath, or when damage above maxhealth (you can never fully heal fire)
|
||||
var/amInCoffinWhileTorpor = istype(C.loc, /obj/structure/closet/crate/coffin) && (mult == 0 || HAS_TRAIT(C, TRAIT_FAKEDEATH)) // Check for mult 0 OR death coma. (mult 0 means we're testing from coffin)
|
||||
if(amInCoffinWhileTorpor)
|
||||
// Check for mult 0 OR death coma. (mult 0 means we're testing from coffin)
|
||||
if(istype(C.loc, /obj/structure/closet/crate/coffin) && (mult == 0 || HAS_TRAIT(C, TRAIT_FAKEDEATH)))
|
||||
mult *= 4 // Increase multiplier if we're sleeping in a coffin.
|
||||
fireheal = min(C.getFireLoss(), regen_rate) // NOTE: Burn damage ONLY heals in torpor.
|
||||
C.ExtinguishMob()
|
||||
@@ -112,6 +112,9 @@
|
||||
CheckVampOrgans() // Heart, Eyes
|
||||
if(check_limbs(costMult))
|
||||
return TRUE
|
||||
else if(owner.current.stat >= UNCONSCIOUS) //Faster regeneration and slight burn healing while unconcious
|
||||
mult *= 2
|
||||
fireheal = min(C.getFireLoss(), regen_rate * 0.2)
|
||||
|
||||
// BRUTE: Always Heal
|
||||
var/bruteheal = min(C.getBruteLoss(), actual_regen)
|
||||
@@ -120,8 +123,6 @@
|
||||
if(bruteheal + fireheal + toxinheal > 0) // Just a check? Don't heal/spend, and return.
|
||||
if(mult == 0)
|
||||
return TRUE
|
||||
if(owner.current.stat >= UNCONSCIOUS) //Faster regeneration while unconcious, so you dont have to wait all day
|
||||
mult *= 2
|
||||
// We have damage. Let's heal (one time)
|
||||
C.adjustBruteLoss(-bruteheal * mult, forced = TRUE)// Heal BRUTE / BURN in random portions throughout the body.
|
||||
C.adjustFireLoss(-fireheal * mult, forced = TRUE)
|
||||
@@ -146,12 +147,6 @@
|
||||
to_chat(C, "<span class='notice'>Your flesh knits as it regrows your [L]!</span>")
|
||||
playsound(C, 'sound/magic/demon_consume.ogg', 50, TRUE)
|
||||
return TRUE
|
||||
/*for(var/obj/item/bodypart/BP in C.bodyparts)
|
||||
if(!istype(BP) && !BP.status == 2)
|
||||
return FALSE
|
||||
to_chat(C, "<span class='notice'>Your body expels the [BP]!</span>")
|
||||
BP.drop_limb()
|
||||
return TRUE */
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/CureDisabilities()
|
||||
var/mob/living/carbon/C = owner.current
|
||||
@@ -176,7 +171,7 @@
|
||||
// EMPTY: Frenzy!
|
||||
// BLOOD_VOLUME_GOOD: [336] Pale (handled in bloodsucker_integration.dm
|
||||
// BLOOD_VOLUME_BAD: [224] Jitter
|
||||
if(owner.current.blood_volume < BLOOD_VOLUME_BAD && !prob(0.5))
|
||||
if(owner.current.blood_volume < BLOOD_VOLUME_BAD && !prob(0.5 && HAS_TRAIT(owner, TRAIT_FAKEDEATH)) && !poweron_masquerade)
|
||||
owner.current.Jitter(3)
|
||||
// BLOOD_VOLUME_SURVIVE: [122] Blur Vision
|
||||
if(owner.current.blood_volume < BLOOD_VOLUME_BAD / 2)
|
||||
@@ -230,16 +225,16 @@
|
||||
Torpor_Begin()
|
||||
to_chat(owner, "<span class='danger'>Your immortal body will not yet relinquish your soul to the abyss. You enter Torpor.</span>")
|
||||
sleep(30) //To avoid spam
|
||||
if(poweron_masquerade == TRUE)
|
||||
if(poweron_masquerade)
|
||||
to_chat(owner, "<span class='warning'>Your wounds will not heal until you disable the <span class='boldnotice'>Masquerade</span> power.</span>")
|
||||
// End Torpor:
|
||||
else // No damage, OR toxin healed AND brute healed and NOT in coffin (since you cannot heal burn)
|
||||
if(total_damage <= 0 || total_toxloss <= 0 && total_brute <= 0 && !istype(owner.current.loc, /obj/structure/closet/crate/coffin))
|
||||
// Not Daytime, Not in Torpor
|
||||
if(!SSticker.mode.is_daylight() && HAS_TRAIT_FROM(owner.current, TRAIT_FAKEDEATH, "bloodsucker"))
|
||||
// Not Daytime, Not in Torpor, enough health to not die the moment you end torpor
|
||||
if(!SSticker.mode.is_daylight() && HAS_TRAIT_FROM(owner.current, TRAIT_FAKEDEATH, "bloodsucker") && total_damage < owner.current.getMaxHealth())
|
||||
Torpor_End()
|
||||
// Fake Unconscious
|
||||
if(poweron_masquerade == TRUE && total_damage >= owner.current.getMaxHealth() - HEALTH_THRESHOLD_FULLCRIT)
|
||||
if(poweron_masquerade && total_damage >= owner.current.getMaxHealth() - HEALTH_THRESHOLD_FULLCRIT)
|
||||
owner.current.Unconscious(20, 1)
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/Torpor_Begin(amInCoffin = FALSE)
|
||||
@@ -249,6 +244,7 @@
|
||||
ADD_TRAIT(owner.current, TRAIT_NODEATH, "bloodsucker") // Without this, you'll just keep dying while you recover.
|
||||
ADD_TRAIT(owner.current, TRAIT_RESISTHIGHPRESSURE, "bloodsucker") // So you can heal in space. Otherwise you just...heal forever.
|
||||
ADD_TRAIT(owner.current, TRAIT_RESISTLOWPRESSURE, "bloodsucker")
|
||||
owner.current.Jitter(0)
|
||||
// Visuals
|
||||
owner.current.update_sight()
|
||||
owner.current.reload_fullscreen()
|
||||
@@ -256,6 +252,9 @@
|
||||
for(var/datum/action/bloodsucker/power in powers)
|
||||
if(power.active && !power.can_use_in_torpor)
|
||||
power.DeactivatePower()
|
||||
if(owner.current.suiciding)
|
||||
owner.current.suiciding = FALSE //Youll die but not for long.
|
||||
to_chat(owner.current, "<span class='warning'>Your body keeps you going, even as you try to end yourself.</span>")
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/Torpor_End()
|
||||
owner.current.stat = SOFT_CRIT
|
||||
|
||||
@@ -45,15 +45,15 @@
|
||||
// (FINAL LIL WARNING)
|
||||
while(time_til_cycle > 5)
|
||||
sleep(10)
|
||||
if (cancel_me)
|
||||
if(cancel_me)
|
||||
return
|
||||
//sleep(TIME_BLOODSUCKER_DAY_FINAL_WARN - 50)
|
||||
warn_daylight(3,"<span class = 'userdanger'>Seek cover, for Sol rises!</span>")
|
||||
|
||||
// Part 3: Night Ending
|
||||
while (time_til_cycle > 0)
|
||||
while(time_til_cycle > 0)
|
||||
sleep(10)
|
||||
if (cancel_me)
|
||||
if(cancel_me)
|
||||
return
|
||||
//sleep(50)
|
||||
warn_daylight(4,"<span class = 'userdanger'>Solar flares bombard the station with deadly UV light!</span><br><span class = ''>Stay in cover for the next [TIME_BLOODSUCKER_DAY / 60] minutes or risk Final Death!</span>",\
|
||||
@@ -69,11 +69,11 @@
|
||||
while(time_til_cycle > 0)
|
||||
punish_vamps()
|
||||
sleep(TIME_BLOODSUCKER_BURN_INTERVAL)
|
||||
if (cancel_me)
|
||||
if(cancel_me)
|
||||
return
|
||||
//daylight_time -= TIME_BLOODSUCKER_BURN_INTERVAL
|
||||
// Issue Level Up!
|
||||
if(!issued_XP && time_til_cycle <= 15)
|
||||
if(!issued_XP && time_til_cycle <= 5)
|
||||
issued_XP = TRUE
|
||||
vamps_rank_up()
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@
|
||||
// Traits
|
||||
for(var/T in defaultTraits)
|
||||
REMOVE_TRAIT(owner.current, T, BLOODSUCKER_TRAIT)
|
||||
if(had_toxlover == TRUE)
|
||||
if(had_toxlover)
|
||||
ADD_TRAIT(owner.current, TRAIT_TOXINLOVER, SPECIES_TRAIT)
|
||||
|
||||
// Traits: Species
|
||||
|
||||
@@ -18,14 +18,11 @@
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
// must have nobody around to see the cloak
|
||||
var/watchers = viewers(9,get_turf(owner))
|
||||
for(var/mob/living/M in watchers)
|
||||
for(var/mob/living/M in viewers(9, owner))
|
||||
if(M != owner)
|
||||
to_chat(owner, "<span class='warning'>You may only vanish into the shadows unseen.</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/cloak/ActivatePower()
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
REMOVE_TRAIT(user, TRAIT_NOHARDCRIT, "bloodsucker")
|
||||
REMOVE_TRAIT(user, TRAIT_NOSOFTCRIT, "bloodsucker")
|
||||
REMOVE_TRAIT(user, TRAIT_VIRUSIMMUNE, "bloodsucker")
|
||||
REMOVE_TRAIT(user, TRAIT_NOBREATH, "bloodsucker")
|
||||
var/obj/item/organ/heart/vampheart/H = user.getorganslot(ORGAN_SLOT_HEART)
|
||||
var/obj/item/organ/eyes/vassal/bloodsucker/E = user.getorganslot(ORGAN_SLOT_EYES)
|
||||
E.flash_protect = 0
|
||||
@@ -93,6 +94,7 @@
|
||||
ADD_TRAIT(user, TRAIT_NOHARDCRIT, "bloodsucker")
|
||||
ADD_TRAIT(user, TRAIT_NOSOFTCRIT, "bloodsucker")
|
||||
ADD_TRAIT(user, TRAIT_VIRUSIMMUNE, "bloodsucker")
|
||||
ADD_TRAIT(user, TRAIT_NOBREATH, "bloodsucker")
|
||||
|
||||
// HEART
|
||||
var/obj/item/organ/heart/H = user.getorganslot(ORGAN_SLOT_HEART)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
/datum/action/bloodsucker/targeted/trespass/CheckValidTarget(atom/A)
|
||||
// Can't target my tile
|
||||
if (A == get_turf(owner) || get_turf(A) == get_turf(owner))
|
||||
if(A == get_turf(owner) || get_turf(A) == get_turf(owner))
|
||||
return FALSE
|
||||
|
||||
return TRUE // All we care about is destination. Anything you click is fine.
|
||||
@@ -43,13 +43,13 @@
|
||||
// Are either tiles WALLS?
|
||||
var/turf/from_turf = get_turf(owner)
|
||||
var/this_dir // = get_dir(from_turf, target_turf)
|
||||
for (var/i=1 to 2)
|
||||
for(var/i=1 to 2)
|
||||
// Keep Prev Direction if we've reached final turf
|
||||
if (from_turf != final_turf)
|
||||
if(from_turf != final_turf)
|
||||
this_dir = get_dir(from_turf, final_turf) // Recalculate dir so we don't overshoot on a diagonal.
|
||||
from_turf = get_step(from_turf, this_dir)
|
||||
// ERROR! Wall!
|
||||
if (iswallturf(from_turf))
|
||||
if(iswallturf(from_turf))
|
||||
if (display_error)
|
||||
var/wallwarning = (i == 1) ? "in the way" : "at your destination"
|
||||
to_chat(owner, "<span class='warning'>There is a solid wall [wallwarning].</span>")
|
||||
@@ -84,7 +84,7 @@
|
||||
user.next_move = world.time + mist_delay
|
||||
user.Stun(mist_delay, ignore_canstun = TRUE)
|
||||
user.notransform = TRUE
|
||||
user.density = 0
|
||||
user.density = FALSE
|
||||
var/invis_was = user.invisibility
|
||||
user.invisibility = INVISIBILITY_MAXIMUM
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
sleep(mist_delay / 2)
|
||||
|
||||
// Move & Freeze
|
||||
if (isturf(target_turf))
|
||||
if(isturf(target_turf))
|
||||
do_teleport(owner, target_turf, no_effects=TRUE, channel = TELEPORT_CHANNEL_QUANTUM) // in teleport.dm?
|
||||
user.next_move = world.time + mist_delay / 2
|
||||
user.Stun(mist_delay / 2, ignore_canstun = TRUE)
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
if(objective.completable)
|
||||
var/completion = objective.check_completion()
|
||||
if(completion >= 1)
|
||||
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
|
||||
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</B></span>"
|
||||
else if(completion <= 0)
|
||||
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
win = FALSE
|
||||
|
||||
@@ -563,7 +563,7 @@
|
||||
if(objective.completable)
|
||||
var/completion = objective.check_completion()
|
||||
if(completion >= 1)
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</B></span>"
|
||||
else if(completion <= 0)
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
changelingwin = FALSE
|
||||
|
||||
@@ -441,7 +441,7 @@
|
||||
if(objective.completable)
|
||||
var/completion = objective.check_completion()
|
||||
if(completion >= 1)
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</B></span>"
|
||||
else if(completion <= 0)
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
else
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
if(objective.completable)
|
||||
var/completion = objective.check_completion()
|
||||
if(completion >= 1)
|
||||
result += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
|
||||
result += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</B></span>"
|
||||
else if(completion <= 0)
|
||||
result += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
win = FALSE
|
||||
|
||||
@@ -239,7 +239,7 @@
|
||||
if(objective.completable)
|
||||
var/completion = objective.check_completion()
|
||||
if(completion >= 1)
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</B></span>"
|
||||
else if(completion <= 0)
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
traitorwin = FALSE
|
||||
|
||||
@@ -269,7 +269,7 @@
|
||||
if(objective.completable)
|
||||
var/completion = objective.check_completion()
|
||||
if(completion >= 1)
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</B></span>"
|
||||
else if(completion <= 0)
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
wizardwin = FALSE
|
||||
|
||||
@@ -3,14 +3,35 @@
|
||||
desc = "A small electronic device able to control a blast door remotely."
|
||||
icon_state = "control"
|
||||
attachable = TRUE
|
||||
var/id = null
|
||||
var/can_change_id = 0
|
||||
/// Our ID. Make the first character ! if you want to obfuscate it as a mapper via randomization.
|
||||
var/id
|
||||
/// Can the ID be changed if used in hand?
|
||||
var/can_change_id = FALSE
|
||||
/// Show ID?
|
||||
var/show_id = TRUE
|
||||
var/cooldown = FALSE //Door cooldowns
|
||||
|
||||
/obj/item/assembly/control/Initialize(mapload)
|
||||
if(mapload && id)
|
||||
if(copytext(id, 1, 2) == "!")
|
||||
id = SSmapping.get_obfuscated_id(id)
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/control/examine(mob/user)
|
||||
. = ..()
|
||||
if(id)
|
||||
if(id && show_id)
|
||||
. += "<span class='notice'>Its channel ID is '[id]'.</span>"
|
||||
if(can_change_id)
|
||||
. += "<span class='notice'>Use in hand to change ID.</span>"
|
||||
|
||||
/obj/item/assembly/control/attack_self(mob/living/user)
|
||||
. = ..()
|
||||
if(!can_change_id)
|
||||
return
|
||||
var/new_id
|
||||
new_id = input(user, "Set ID", "Set ID", show_id? id : null) as text|null
|
||||
if(!isnull(new_id)) //0/"" is considered !, so check null instead of just !.
|
||||
id = new_id
|
||||
|
||||
/obj/item/assembly/control/activate()
|
||||
cooldown = TRUE
|
||||
@@ -22,7 +43,6 @@
|
||||
INVOKE_ASYNC(M, openclose ? /obj/machinery/door/poddoor.proc/open : /obj/machinery/door/poddoor.proc/close)
|
||||
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
|
||||
|
||||
|
||||
/obj/item/assembly/control/airlock
|
||||
name = "airlock controller"
|
||||
desc = "A small electronic device able to control an airlock remotely."
|
||||
@@ -123,7 +143,6 @@
|
||||
|
||||
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 50)
|
||||
|
||||
|
||||
/obj/item/assembly/control/crematorium
|
||||
name = "crematorium controller"
|
||||
desc = "An evil-looking remote controller for a crematorium."
|
||||
@@ -135,3 +154,14 @@
|
||||
C.cremate(usr)
|
||||
|
||||
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 50)
|
||||
|
||||
/obj/item/assembly/control/electrochromatic
|
||||
name = "electrochromatic window controller"
|
||||
desc = "Toggles linked electrochromatic windows."
|
||||
can_change_id = TRUE
|
||||
/// Stores our status to prevent windows from desyncing.
|
||||
var/on = FALSE
|
||||
|
||||
/obj/item/assembly/control/electrochromatic/activate()
|
||||
on = !on
|
||||
do_electrochromatic_toggle(on, id)
|
||||
|
||||
@@ -192,6 +192,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(/datum/gas/oxygen, /datum/g
|
||||
anchored = TRUE // should only appear in vis_contents, but to be safe
|
||||
layer = FLY_LAYER
|
||||
appearance_flags = TILE_BOUND
|
||||
vis_flags = NONE
|
||||
|
||||
/obj/effect/overlay/gas/New(state, alph)
|
||||
. = ..()
|
||||
|
||||
@@ -225,6 +225,7 @@
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
target_temperature = min_temperature
|
||||
to_chat(user,"<span class='notice'>You minimize the temperature on the [src].</span>")
|
||||
investigate_log("was set to [target_temperature] K by [key_name(usr)]", INVESTIGATE_ATMOS)
|
||||
message_admins("[src.name] was minimized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
|
||||
return TRUE
|
||||
@@ -257,6 +258,7 @@
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
target_temperature = max_temperature
|
||||
to_chat(user,"<span class='notice'>You maximize the temperature on the [src].</span>")
|
||||
investigate_log("was set to [target_temperature] K by [key_name(usr)]", INVESTIGATE_ATMOS)
|
||||
message_admins("[src.name] was maximized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
|
||||
return TRUE
|
||||
|
||||
@@ -262,7 +262,15 @@
|
||||
return
|
||||
random_look(owner)
|
||||
|
||||
/obj/item/clothing/under/chameleon
|
||||
// Forgive me for my sins...
|
||||
#define CHAMELEON_CLOTHING_DEFINE(path) \
|
||||
##path/syndicate/Initialize(mapload){\
|
||||
. = ..();\
|
||||
AddComponent(/datum/component/identification/syndicate, ID_COMPONENT_DEL_ON_IDENTIFY, ID_COMPONENT_EFFECT_NO_ACTIONS, ID_COMPONENT_IDENTIFY_WITH_DECONSTRUCTOR);\
|
||||
}\
|
||||
##path
|
||||
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/under/chameleon)
|
||||
//starts off as black
|
||||
name = "black jumpsuit"
|
||||
icon_state = "black"
|
||||
@@ -300,7 +308,7 @@
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
/obj/item/clothing/suit/chameleon
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/suit/chameleon)
|
||||
name = "armor"
|
||||
desc = "A slim armored vest that protects against most types of damage."
|
||||
icon_state = "armor"
|
||||
@@ -329,7 +337,7 @@
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
/obj/item/clothing/glasses/chameleon
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/glasses/chameleon)
|
||||
name = "Optical Meson Scanner"
|
||||
desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition."
|
||||
icon_state = "meson"
|
||||
@@ -357,7 +365,7 @@
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
/obj/item/clothing/gloves/chameleon
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/gloves/chameleon)
|
||||
desc = "These gloves will protect the wearer from electric shock."
|
||||
name = "insulated gloves"
|
||||
icon_state = "yellow"
|
||||
@@ -368,6 +376,9 @@
|
||||
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/gloves/chameleon/insulated)
|
||||
siemens_coefficient = 0
|
||||
|
||||
/obj/item/clothing/gloves/chameleon/Initialize()
|
||||
. = ..()
|
||||
chameleon_action = new(src)
|
||||
@@ -386,7 +397,7 @@
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
/obj/item/clothing/head/chameleon
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/head/chameleon)
|
||||
name = "grey cap"
|
||||
desc = "It's a baseball hat in a tasteful grey colour."
|
||||
icon_state = "greysoft"
|
||||
@@ -429,7 +440,7 @@
|
||||
var/datum/action/item_action/chameleon/drone/randomise/randomise_action = new(src)
|
||||
randomise_action.UpdateButtonIcon()
|
||||
|
||||
/obj/item/clothing/mask/chameleon
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/mask/chameleon)
|
||||
name = "gas mask"
|
||||
desc = "A face-covering mask that can be connected to an air supply. While good for concealing your identity, it isn't good for blocking gas flow." //More accurate
|
||||
icon_state = "gas_alt"
|
||||
@@ -486,7 +497,7 @@
|
||||
/obj/item/clothing/mask/chameleon/drone/attack_self(mob/user)
|
||||
to_chat(user, "<span class='notice'>[src] does not have a voice changer.</span>")
|
||||
|
||||
/obj/item/clothing/shoes/chameleon
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/shoes/chameleon)
|
||||
name = "black shoes"
|
||||
icon_state = "black"
|
||||
desc = "A pair of black shoes."
|
||||
@@ -511,7 +522,7 @@
|
||||
return
|
||||
chameleon_action.emp_randomise()
|
||||
|
||||
/obj/item/clothing/shoes/chameleon/noslip
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/shoes/chameleon/noslip)
|
||||
name = "black shoes"
|
||||
icon_state = "black"
|
||||
desc = "A pair of black shoes."
|
||||
@@ -521,7 +532,7 @@
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
/obj/item/storage/backpack/chameleon
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/storage/backpack/chameleon)
|
||||
name = "backpack"
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
@@ -542,7 +553,7 @@
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
/obj/item/storage/belt/chameleon
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/storage/belt/chameleon)
|
||||
name = "toolbelt"
|
||||
desc = "Holds tools."
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
@@ -570,7 +581,7 @@
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
/obj/item/radio/headset/chameleon
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/radio/headset/chameleon)
|
||||
name = "radio headset"
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
@@ -591,7 +602,7 @@
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
/obj/item/pda/chameleon
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/pda/chameleon)
|
||||
name = "PDA"
|
||||
var/datum/action/item_action/chameleon/change/pda/chameleon_action
|
||||
|
||||
@@ -613,7 +624,7 @@
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
/obj/item/stamp/chameleon
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/stamp/chameleon)
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/stamp/chameleon/Initialize()
|
||||
@@ -627,7 +638,7 @@
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
/obj/item/clothing/neck/cloak/chameleon
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/neck/cloak/chameleon)
|
||||
name = "black tie"
|
||||
desc = "A neosilk clip-on tie."
|
||||
icon = 'icons/obj/clothing/neck.dmi'
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
/datum/round_event/wormholes/start()
|
||||
for(var/turf/open/floor/T in world)
|
||||
if(is_station_level(T.z))
|
||||
var/area/A = get_area(T)
|
||||
if(A.outdoors)
|
||||
continue
|
||||
pick_turfs += T
|
||||
|
||||
for(var/i = 1, i <= number_of_wormholes, i++)
|
||||
|
||||
@@ -937,3 +937,20 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
spawners_menu = new(src)
|
||||
|
||||
spawners_menu.ui_interact(src)
|
||||
|
||||
/mob/dead/observer/verb/game_info()
|
||||
set name = "Game info"
|
||||
set desc = "Shows various info relating to the game mode, antagonists etc."
|
||||
set category = "Ghost"
|
||||
if(!started_as_observer && can_reenter_corpse)
|
||||
to_chat(src, "You cannot see this info unless you are an observer or you've chosen Do Not Resuscitate!")
|
||||
return
|
||||
var/list/stuff = list("[SSticker.mode.name]")
|
||||
stuff += "Antagonists:\n"
|
||||
for(var/datum/antagonist/A in GLOB.antagonists)
|
||||
if(A.owner)
|
||||
stuff += "[A.owner] the [A.name]"
|
||||
var/ghost_info = SSticker.mode.ghost_info()
|
||||
if(ghost_info)
|
||||
stuff += ghost_info
|
||||
to_chat(src,stuff.Join("\n"))
|
||||
|
||||
@@ -101,7 +101,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
|
||||
|
||||
/obj/item/organ/dwarfgland/on_life() //Primary loop to hook into to start delayed loops for other loops..
|
||||
. = ..()
|
||||
if(!owner || owner.stat == DEAD)
|
||||
if(owner && owner.stat != DEAD)
|
||||
dwarf_cycle_ticker()
|
||||
|
||||
//Handles the delayed tick cycle by just adding on increments per each on_life() tick
|
||||
|
||||
@@ -264,6 +264,9 @@
|
||||
if((last_newpatient_speak + 300) < world.time) //Don't spam these messages!
|
||||
var/list/messagevoice = list("Hey, [H.name]! Hold on, I'm coming." = 'sound/voice/medbot/coming.ogg',"Wait [H.name]! I want to help!" = 'sound/voice/medbot/help.ogg',"[H.name], you appear to be injured!" = 'sound/voice/medbot/injured.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
if(prob(1) && ISINRANGE_EX(H.getFireLoss(), 0, 20))
|
||||
message = "Notices your minor burns*OwO what's this?"
|
||||
messagevoice[message] = 'sound/voice/medbot/owo.ogg'
|
||||
speak(message)
|
||||
playsound(loc, messagevoice[message], 50, 0)
|
||||
last_newpatient_speak = world.time
|
||||
|
||||
@@ -97,6 +97,8 @@
|
||||
body_color = "brown"
|
||||
icon_state = "mouse_brown"
|
||||
|
||||
GLOBAL_VAR(tom_existed)
|
||||
|
||||
//TOM IS ALIVE! SQUEEEEEEEE~K :)
|
||||
/mob/living/simple_animal/mouse/brown/Tom
|
||||
name = "Tom"
|
||||
@@ -106,6 +108,10 @@
|
||||
response_harm = "splats"
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
|
||||
/mob/living/simple_animal/mouse/brown/Tom/Initialize()
|
||||
. = ..()
|
||||
GLOB.tom_existed = TRUE
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/deadmouse
|
||||
name = "dead mouse"
|
||||
desc = "It looks like somebody dropped the bass on it. A lizard's favorite meal."
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
throwforce = 10
|
||||
blocks_emissive = EMISSIVE_BLOCK_GENERIC
|
||||
|
||||
vis_flags = VIS_INHERIT_PLANE //when this be added to vis_contents of something it inherit something.plane, important for visualisation of mob in openspace.
|
||||
|
||||
var/lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
|
||||
var/datum/mind/mind
|
||||
var/list/datum/action/actions = list()
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
fire_sound = 'sound/weapons/ionrifle.ogg'
|
||||
|
||||
/obj/item/ammo_casing/energy/ion/hos
|
||||
projectile_type = /obj/item/projectile/ion/weak
|
||||
e_cost = 300
|
||||
projectile_type = /obj/item/projectile/ion
|
||||
e_cost = 200
|
||||
|
||||
/obj/item/ammo_casing/energy/declone
|
||||
projectile_type = /obj/item/projectile/energy/declone
|
||||
|
||||
@@ -74,3 +74,11 @@
|
||||
materials = list(/datum/material/glass = 20)
|
||||
build_path = /obj/item/stock_parts/cell/emergency_light
|
||||
category = list("initial", "Electronics")
|
||||
|
||||
/datum/design/electrochromatic_control
|
||||
name = "Electrochromatic Control Circuit"
|
||||
id = "electrochromatic_control_circuit"
|
||||
build_type = AUTOLATHE
|
||||
materials = list(/datum/material/iron = 100, /datum/material/glass = 100)
|
||||
build_path = /obj/item/assembly/control/electrochromatic
|
||||
category = list("initial", "Electronics")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/datum/design/autoylathe
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
|
||||
/datum/design/autoylathe/mech
|
||||
category = list("initial", "Figurines")
|
||||
@@ -558,7 +558,7 @@
|
||||
/datum/design/foam_x9
|
||||
name = "Foam Force X9 Rifle"
|
||||
id = "foam_x9"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
|
||||
build_path = /obj/item/gun/ballistic/automatic/x9/toy
|
||||
category = list("initial", "Rifles")
|
||||
@@ -566,7 +566,7 @@
|
||||
/datum/design/foam_dart
|
||||
name = "Box of Foam Darts"
|
||||
id = "foam_dart"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 500, /datum/material/iron = 100)
|
||||
build_path = /obj/item/ammo_box/foambox
|
||||
category = list("initial", "Misc")
|
||||
@@ -574,7 +574,7 @@
|
||||
/datum/design/foam_magpistol
|
||||
name = "Foam Force Magpistol"
|
||||
id = "magfoam_launcher"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 250)
|
||||
build_path = /obj/item/gun/ballistic/shotgun/toy/mag
|
||||
category = list("initial", "Pistols")
|
||||
@@ -582,7 +582,7 @@
|
||||
/datum/design/foam_magrifle
|
||||
name = "Foam Force MagRifle"
|
||||
id = "foam_magrifle"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
|
||||
build_path = /obj/item/gun/ballistic/automatic/toy/magrifle
|
||||
category = list("initial", "Rifles")
|
||||
@@ -590,7 +590,7 @@
|
||||
/datum/design/foam_hyperburst
|
||||
name = "MagTag Hyper Rifle"
|
||||
id = "foam_hyperburst"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 2000, /datum/material/glass = 1000)
|
||||
build_path = /obj/item/gun/energy/laser/practice/hyperburst
|
||||
category = list("initial", "Rifles")
|
||||
@@ -598,7 +598,7 @@
|
||||
/datum/design/foam_sp
|
||||
name = "Foam Force Stealth Pistol"
|
||||
id = "foam_sp"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 1000)
|
||||
build_path = /obj/item/gun/ballistic/automatic/toy/pistol/stealth
|
||||
category = list("initial", "Pistols")
|
||||
@@ -606,7 +606,7 @@
|
||||
/datum/design/toyray
|
||||
name = "RayTag Gun"
|
||||
id = "toyray"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 1000, /datum/material/glass = 1000)
|
||||
build_path = /obj/item/gun/energy/laser/practice/raygun
|
||||
category = list("initial", "Pistols")
|
||||
@@ -614,7 +614,7 @@
|
||||
/datum/design/am4c
|
||||
name = "Foam Force AM4-C Rifle"
|
||||
id = "foam_am4c"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
|
||||
build_path = /obj/item/gun/ballistic/automatic/AM4C
|
||||
category = list("initial", "Rifles")
|
||||
@@ -622,7 +622,7 @@
|
||||
/datum/design/foam_f3
|
||||
name = "Replica F3 Justicar"
|
||||
id = "foam_f3"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 250)
|
||||
build_path = /obj/item/toy/gun/justicar
|
||||
category = list("initial", "Pistols")
|
||||
@@ -630,7 +630,7 @@
|
||||
/datum/design/toy_blaster
|
||||
name = "pump-action plastic blaster"
|
||||
id = "toy_blaster"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 750, /datum/material/glass = 1000)
|
||||
build_path = /obj/item/gun/energy/pumpaction/toy
|
||||
category = list("initial", "Rifles")
|
||||
@@ -638,7 +638,7 @@
|
||||
/datum/design/capammo
|
||||
name = "Box of Caps"
|
||||
id = "capammo"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/iron = 10, /datum/material/glass = 10)
|
||||
build_path = /obj/item/toy/ammo/gun
|
||||
category = list("initial", "Misc")
|
||||
@@ -646,7 +646,7 @@
|
||||
/datum/design/foam_smg
|
||||
name = "Foam Force SMG"
|
||||
id = "foam_smg"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 250)
|
||||
build_path = /obj/item/gun/ballistic/automatic/toy/unrestricted
|
||||
category = list("initial", "Pistols")
|
||||
@@ -654,7 +654,7 @@
|
||||
/datum/design/foam_pistol
|
||||
name = "Foam Force Pistol"
|
||||
id = "foam_pistol"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 250)
|
||||
build_path = /obj/item/gun/ballistic/automatic/toy/pistol/unrestricted
|
||||
category = list("initial", "Pistols")
|
||||
@@ -662,7 +662,7 @@
|
||||
/datum/design/foam_shotgun
|
||||
name = "Foam Force Shotgun"
|
||||
id = "foam_shotgun"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
|
||||
build_path = /obj/item/gun/ballistic/shotgun/toy/unrestricted
|
||||
category = list("initial", "Rifles")
|
||||
@@ -670,7 +670,7 @@
|
||||
/datum/design/foam_dartred
|
||||
name = "Box of Lastag Red Foam Darts"
|
||||
id = "redfoam_dart"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 500, /datum/material/iron = 100)
|
||||
build_path = /obj/item/ammo_box/foambox/tag/red
|
||||
category = list("initial", "Misc")
|
||||
@@ -678,7 +678,7 @@
|
||||
/datum/design/foam_dartblue
|
||||
name = "Box of Lastag Blue Foam Darts"
|
||||
id = "bluefoam_dart"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 500, /datum/material/iron = 100)
|
||||
build_path = /obj/item/ammo_box/foambox/tag/blue
|
||||
category = list("initial", "Misc")
|
||||
@@ -686,7 +686,7 @@
|
||||
/datum/design/foam_bow
|
||||
name = "Foam Force Crossbow"
|
||||
id = "foam_bow"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 250)
|
||||
build_path = /obj/item/gun/ballistic/shotgun/toy/crossbow
|
||||
category = list("initial", "Pistols")
|
||||
@@ -694,7 +694,7 @@
|
||||
/datum/design/foam_c20
|
||||
name = "Donksoft C20R"
|
||||
id = "foam_c20"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
|
||||
build_path = /obj/item/gun/ballistic/automatic/c20r/toy/unrestricted
|
||||
category = list("hacked", "Rifles")
|
||||
@@ -702,7 +702,7 @@
|
||||
/datum/design/foam_l6
|
||||
name = "Donksoft LMG"
|
||||
id = "foam_LMG"
|
||||
build_type = AUTOYLATHE
|
||||
build_type = TOYLATHE
|
||||
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
|
||||
build_path = /obj/item/gun/ballistic/automatic/l6_saw/toy/unrestricted
|
||||
category = list("hacked", "Rifles")
|
||||
|
||||
@@ -111,6 +111,6 @@
|
||||
name = "Machine Design (Autoylathe)"
|
||||
desc = "The circuit board for an autoylathe."
|
||||
id = "autoylathe"
|
||||
build_path = /obj/item/circuitboard/machine/autoylathe
|
||||
build_path = /obj/item/circuitboard/machine/autolathe/toy
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ALL
|
||||
category = list("Misc. Machinery")
|
||||
|
||||
@@ -101,7 +101,7 @@ Note: Must be placed within 3 tiles of the R&D Console
|
||||
if(!istype(loaded_item) || !istype(linked_console))
|
||||
return FALSE
|
||||
|
||||
if (id && id != RESEARCH_MATERIAL_RECLAMATION_ID)
|
||||
if (id && id != RESEARCH_MATERIAL_RECLAMATION_ID && id != RESEARCH_DEEP_SCAN_ID)
|
||||
var/datum/techweb_node/TN = SSresearch.techweb_node_by_id(id)
|
||||
if(!istype(TN))
|
||||
return FALSE
|
||||
@@ -125,7 +125,7 @@ Note: Must be placed within 3 tiles of the R&D Console
|
||||
if(destroy_item(loaded_item))
|
||||
linked_console.stored_research.boost_with_path(SSresearch.techweb_node_by_id(TN.id), dpath)
|
||||
|
||||
else
|
||||
else if(id == RESEARCH_MATERIAL_RECLAMATION_ID)
|
||||
var/list/point_value = techweb_item_point_check(loaded_item)
|
||||
if(linked_console.stored_research.deconstructed_items[loaded_item.type])
|
||||
point_value = list()
|
||||
@@ -143,6 +143,15 @@ Note: Must be placed within 3 tiles of the R&D Console
|
||||
if(destroy_item(loaded_item))
|
||||
linked_console.stored_research.add_point_list(point_value)
|
||||
linked_console.stored_research.deconstructed_items[loaded_type] = point_value
|
||||
else if(id == RESEARCH_DEEP_SCAN_ID)
|
||||
var/list/return_list = list()
|
||||
. = SEND_SIGNAL(loaded_item, COMSIG_ITEM_DECONSTRUCTOR_DEEPSCAN, src, user, return_list)
|
||||
flick("d_analyzer_process", src)
|
||||
if(. & COMPONENT_DEEPSCAN_UNCOVERED_INFORMATION)
|
||||
say("New information uncovered from item deep scan[length(return_list)? ": [english_list(return_list)]" : ""].")
|
||||
else
|
||||
say("Item deep scan uncovered no new information.")
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/rnd/destructive_analyzer/proc/unload_item()
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
if(!host_mob.client) //less brainpower
|
||||
points *= 0.25
|
||||
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points))
|
||||
|
||||
|
||||
/datum/nanite_program/researchplus
|
||||
name = "Neural Network"
|
||||
desc = "The nanites link the host's brains together forming a neural research network, that becomes more efficient with the amount of total hosts."
|
||||
@@ -184,7 +184,7 @@
|
||||
SSnanites.neural_network_count--
|
||||
else
|
||||
SSnanites.neural_network_count -= 0.25
|
||||
|
||||
|
||||
/datum/nanite_program/researchplus/active_effect()
|
||||
if(!iscarbon(host_mob))
|
||||
return
|
||||
@@ -234,7 +234,7 @@
|
||||
var/spread_cooldown = 0
|
||||
|
||||
/datum/nanite_program/spreading/active_effect()
|
||||
if(spread_cooldown < world.time)
|
||||
if(world.time < spread_cooldown)
|
||||
return
|
||||
spread_cooldown = world.time + 50
|
||||
var/list/mob/living/target_hosts = list()
|
||||
|
||||
@@ -47,6 +47,9 @@ Nothing else in the console has ID requirements.
|
||||
|
||||
var/research_control = TRUE
|
||||
|
||||
/// Long action cooldown to prevent spam
|
||||
var/last_long_action = 0
|
||||
|
||||
/obj/machinery/computer/rdconsole/production
|
||||
circuit = /obj/item/circuitboard/computer/rdconsole/production
|
||||
research_control = FALSE
|
||||
@@ -583,10 +586,8 @@ Nothing else in the console has ID requirements.
|
||||
l += "<table><tr><td>[icon2html(linked_destroy.loaded_item, usr)]</td><td><b>[linked_destroy.loaded_item.name]</b> <A href='?src=[REF(src)];eject_item=1'>Eject</A></td></tr></table>[RDSCREEN_NOBREAK]"
|
||||
l += "Select a node to boost by deconstructing this item. This item can boost:"
|
||||
|
||||
var/anything = FALSE
|
||||
var/list/boostable_nodes = techweb_item_boost_check(linked_destroy.loaded_item)
|
||||
for(var/id in boostable_nodes)
|
||||
anything = TRUE
|
||||
var/list/worth = boostable_nodes[id]
|
||||
var/datum/techweb_node/N = SSresearch.techweb_node_by_id(id)
|
||||
|
||||
@@ -620,7 +621,6 @@ Nothing else in the console has ID requirements.
|
||||
// point deconstruction and material reclamation use the same ID to prevent accidentally missing the points
|
||||
var/list/point_values = techweb_item_point_check(linked_destroy.loaded_item)
|
||||
if(point_values)
|
||||
anything = TRUE
|
||||
l += "<div class='statusDisplay'>[RDSCREEN_NOBREAK]"
|
||||
if (stored_research.deconstructed_items[linked_destroy.loaded_item.type])
|
||||
l += "<span class='linkOff'>Point Deconstruction</span>"
|
||||
@@ -636,10 +636,8 @@ Nothing else in the console has ID requirements.
|
||||
for (var/M in materials)
|
||||
l += "* [CallMaterialName(M)] x [materials[M]]"
|
||||
l += "</div>[RDSCREEN_NOBREAK]"
|
||||
anything = TRUE
|
||||
|
||||
if (!anything)
|
||||
l += "Nothing!"
|
||||
l += "<div class='statusDisplay'><A href='?src=[REF(src)];deconstruct=[RESEARCH_DEEP_SCAN_ID]'>Nondestructive Deep Scan</A></div>"
|
||||
|
||||
l += "</div>"
|
||||
return l
|
||||
@@ -926,6 +924,9 @@ Nothing else in the console has ID requirements.
|
||||
screen = RDSCREEN_MENU
|
||||
say("Ejecting Technology Disk")
|
||||
if(ls["deconstruct"])
|
||||
if((last_long_action + 1 SECONDS) > world.time)
|
||||
return
|
||||
last_long_action = world.time
|
||||
if(QDELETED(linked_destroy))
|
||||
say("No Destructive Analyzer Linked!")
|
||||
return
|
||||
@@ -1037,7 +1038,7 @@ Nothing else in the console has ID requirements.
|
||||
autolathe_friendly = FALSE
|
||||
D.category -= "Imported"
|
||||
|
||||
if(D.build_type & (AUTOLATHE|PROTOLATHE|CRAFTLATHE)) // Specifically excludes circuit imprinter and mechfab
|
||||
if(D.build_type & (AUTOLATHE|PROTOLATHE|TOYLATHE)) // Specifically excludes circuit imprinter and mechfab
|
||||
D.build_type = autolathe_friendly ? (D.build_type | AUTOLATHE) : D.build_type
|
||||
D.category |= "Imported"
|
||||
d_disk.blueprints[slot] = D
|
||||
|
||||
@@ -344,6 +344,7 @@
|
||||
|
||||
/datum/techweb/specialized/autounlocking
|
||||
var/design_autounlock_buildtypes = NONE
|
||||
var/design_autounlock_skip_types = NONE
|
||||
var/design_autounlock_categories = list("initial") //if a design has a buildtype that matches the abovea and either has a category in this or this is null, unlock it.
|
||||
var/node_autounlock_ids = list() //autounlock nodes of this type.
|
||||
|
||||
@@ -356,7 +357,7 @@
|
||||
research_node_id(id, TRUE, FALSE)
|
||||
for(var/id in SSresearch.techweb_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(id)
|
||||
if(D.build_type & design_autounlock_buildtypes)
|
||||
if(D.build_type & (design_autounlock_buildtypes & allowed_buildtypes) && !(D.build_type & design_autounlock_skip_types))
|
||||
for(var/i in D.category)
|
||||
if(i in design_autounlock_categories)
|
||||
add_design_by_id(D.id)
|
||||
@@ -364,7 +365,16 @@
|
||||
|
||||
/datum/techweb/specialized/autounlocking/autolathe
|
||||
design_autounlock_buildtypes = AUTOLATHE
|
||||
allowed_buildtypes = AUTOLATHE
|
||||
allowed_buildtypes = AUTOLATHE|TOYLATHE
|
||||
|
||||
/datum/techweb/specialized/autounlocking/autolathe/public
|
||||
design_autounlock_skip_types = NO_PUBLIC_LATHE
|
||||
|
||||
/datum/techweb/specialized/autounlocking/autolathe/toy
|
||||
design_autounlock_buildtypes = TOYLATHE
|
||||
|
||||
/datum/techweb/specialized/autounlocking/autolathe/toy/public
|
||||
design_autounlock_skip_types = NO_PUBLIC_LATHE
|
||||
|
||||
/datum/techweb/specialized/autounlocking/limbgrower
|
||||
design_autounlock_buildtypes = LIMBGROWER
|
||||
@@ -381,10 +391,6 @@
|
||||
/datum/techweb/specialized/autounlocking/exofab
|
||||
allowed_buildtypes = MECHFAB
|
||||
|
||||
/datum/techweb/specialized/autounlocking/autoylathe
|
||||
design_autounlock_buildtypes = AUTOYLATHE
|
||||
allowed_buildtypes = AUTOYLATHE
|
||||
|
||||
/datum/techweb/specialized/autounlocking/autobottler
|
||||
design_autounlock_buildtypes = AUTOBOTTLER
|
||||
allowed_buildtypes = AUTOBOTTLER
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
/obj/item/organ/appendix/on_life()
|
||||
. = ..()
|
||||
if(.)
|
||||
if(. || !owner)
|
||||
return
|
||||
owner.adjustToxLoss(4, TRUE, TRUE) //forced to ensure people don't use it to gain tox as slime person
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
/obj/item/organ/liver/on_life()
|
||||
. = ..()
|
||||
if(!.)//can't process reagents with a failing liver
|
||||
if(!. || !owner)//can't process reagents with a failing liver
|
||||
return
|
||||
|
||||
if(filterToxins && !HAS_TRAIT(owner, TRAIT_TOXINLOVER))
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
var/datum/gas_mixture/enviro = T.return_air()
|
||||
local_temp = enviro.temperature
|
||||
|
||||
else if(istype(loc, /mob/) && !owner)
|
||||
else if(!owner && ismob(loc))
|
||||
var/mob/M = loc
|
||||
if(is_type_in_typecache(M.loc, GLOB.freezing_objects))
|
||||
if(!(organ_flags & ORGAN_FROZEN))
|
||||
@@ -137,9 +137,7 @@
|
||||
/obj/item/organ/proc/on_life() //repair organ damage if the organ is not failing or synthetic
|
||||
if(organ_flags & ORGAN_FAILING || !owner)
|
||||
return FALSE
|
||||
if(is_cold())
|
||||
return FALSE
|
||||
if(damage)
|
||||
if(!is_cold() && damage)
|
||||
///Damage decrements by a percent of its maxhealth
|
||||
var/healing_amount = -(maxHealth * healing_factor)
|
||||
///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's satiety
|
||||
|
||||
@@ -579,39 +579,36 @@ GLOBAL_LIST_EMPTY(vending_products)
|
||||
if(!R || !istype(R) || !R.product_path)
|
||||
vend_ready = TRUE
|
||||
return
|
||||
if(R.amount <= 0)
|
||||
to_chat(usr, "<span class='warning'>Sold out.</span>")
|
||||
vend_ready = TRUE
|
||||
return
|
||||
if(R in hidden_records)
|
||||
if(!extended_inventory)
|
||||
vend_ready = TRUE
|
||||
return
|
||||
else if(R in coin_records)
|
||||
if(!(coin))
|
||||
to_chat(usr, "<span class='warning'>You need to a coin to get this item!</span>")
|
||||
if(!coin)
|
||||
to_chat(usr, "<span class='warning'>You need to insert a coin to get this item!</span>")
|
||||
vend_ready = TRUE
|
||||
return
|
||||
if(coin && coin.string_attached)
|
||||
if(!prob(50))
|
||||
to_chat(usr, "<span class='warning'>You weren't able to pull [coin] out fast enough, the machine ate it, string and all!</span>")
|
||||
QDEL_NULL(coin)
|
||||
return
|
||||
if(!usr.CanReach(src))
|
||||
to_chat(usr, "<span class='notice'>You successfully pull [coin] out of [src] to the floor.</span>")
|
||||
coin = null
|
||||
if(!usr.put_in_hands(coin))
|
||||
if(prob(50))
|
||||
if(usr.put_in_hands(coin))
|
||||
to_chat(usr, "<span class='notice'>You successfully pull [coin] out before [src] could swallow it.</span>")
|
||||
coin = null
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You couldn't pull [coin] out because your hands are full!</span>")
|
||||
QDEL_NULL(coin)
|
||||
to_chat(usr, "<span class='notice'>You successfully pull [coin] out before [src] could swallow it.</span>")
|
||||
coin = null
|
||||
QDEL_NULL(coin)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You weren't able to pull [coin] out fast enough, the machine ate it, string and all!</span>")
|
||||
QDEL_NULL(coin)
|
||||
else
|
||||
QDEL_NULL(coin)
|
||||
else if(!(R in product_records))
|
||||
vend_ready = TRUE
|
||||
message_admins("Vending machine exploit attempted by [ADMIN_LOOKUPFLW(usr)]!")
|
||||
return
|
||||
if(R.amount <= 0)
|
||||
to_chat(usr, "<span class='warning'>Sold out.</span>")
|
||||
vend_ready = TRUE
|
||||
return
|
||||
else
|
||||
R.amount--
|
||||
if(((last_reply + 200) <= world.time) && vend_reply)
|
||||
speak(vend_reply)
|
||||
last_reply = world.time
|
||||
@@ -623,8 +620,7 @@ GLOBAL_LIST_EMPTY(vending_products)
|
||||
to_chat(usr, "<span class='notice'>You take [R.name] out of the slot.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>[capitalize(R.name)] falls onto the floor!</span>")
|
||||
|
||||
|
||||
R.amount--
|
||||
SSblackbox.record_feedback("nested tally", "vending_machine_usage", 1, list("[type]", "[R.product_path]"))
|
||||
vend_ready = TRUE
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user