Merge remote-tracking branch 'citadel/master' into combat_patches_1
This commit is contained in:
@@ -96,6 +96,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
|
||||
//Proc called when the datum is given to a mind.
|
||||
/datum/antagonist/proc/on_gain()
|
||||
set waitfor = FALSE
|
||||
if(!(owner?.current))
|
||||
return
|
||||
if(!silent)
|
||||
|
||||
@@ -225,18 +225,22 @@
|
||||
return ..()
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/process()
|
||||
var/power_drained = 0
|
||||
var/power_mod = 0.005
|
||||
for(var/t in spiral_range_turfs(SIGIL_ACCESS_RANGE, src))
|
||||
var/turf/T = t
|
||||
for(var/M in T)
|
||||
var/atom/movable/A = M
|
||||
power_drained += A.power_drain(TRUE)
|
||||
do_process()
|
||||
|
||||
CHECK_TICK
|
||||
/obj/effect/clockwork/sigil/transmission/proc/do_process()
|
||||
set waitfor = FALSE
|
||||
var/power_drained = 0
|
||||
var/power_mod = 0.005
|
||||
for(var/t in spiral_range_turfs(SIGIL_ACCESS_RANGE, src))
|
||||
var/turf/T = t
|
||||
for(var/M in T)
|
||||
var/atom/movable/A = M
|
||||
power_drained += A.power_drain(TRUE)
|
||||
|
||||
adjust_clockwork_power(power_drained * power_mod * 15)
|
||||
new /obj/effect/temp_visual/ratvar/sigil/transmission(loc, 1 + (power_drained * 0.0035))
|
||||
CHECK_TICK
|
||||
|
||||
adjust_clockwork_power(power_drained * power_mod * 15)
|
||||
new /obj/effect/temp_visual/ratvar/sigil/transmission(loc, 1 + (power_drained * 0.0035))
|
||||
|
||||
/obj/effect/clockwork/sigil/transmission/proc/charge_cyborg(mob/living/silicon/robot/cyborg)
|
||||
if(!cyborg_checks(cyborg))
|
||||
|
||||
+31
-27
@@ -246,6 +246,36 @@
|
||||
if(GATEWAY_RATVAR_COMING to INFINITY)
|
||||
. += "<span class='boldwarning'>The anomaly is stable! Something is coming through!</span>"
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/fulfill_purpose()
|
||||
set waitfor = FALSE
|
||||
countdown.stop()
|
||||
resistance_flags |= INDESTRUCTIBLE
|
||||
purpose_fulfilled = TRUE
|
||||
make_glow()
|
||||
animate(glow, transform = matrix() * 1.5, alpha = 255, time = 125)
|
||||
sound_to_playing_players(volume = 100, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/ratvar_rises.ogg')) //End the sounds
|
||||
sleep(125)
|
||||
make_glow()
|
||||
animate(glow, transform = matrix() * 3, alpha = 0, time = 5)
|
||||
QDEL_IN(src, 3)
|
||||
sleep(3)
|
||||
GLOB.clockwork_gateway_activated = TRUE
|
||||
var/turf/T = SSmapping.get_station_center()
|
||||
new /obj/structure/destructible/clockwork/massive/ratvar(T)
|
||||
var/x0 = T.x
|
||||
var/y0 = T.y
|
||||
for(var/I in spiral_range_turfs(255, T, tick_checked = TRUE))
|
||||
var/turf/T2 = I
|
||||
if(!T2)
|
||||
continue
|
||||
var/dist = cheap_hypotenuse(T2.x, T2.y, x0, y0)
|
||||
if(dist < 100)
|
||||
dist = TRUE
|
||||
else
|
||||
dist = FALSE
|
||||
T.ratvar_act(dist)
|
||||
CHECK_TICK
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/celestial_gateway/process()
|
||||
adjust_clockwork_power(2.5) //Provides weak power generation on its own
|
||||
if(seconds_until_activation)
|
||||
@@ -306,33 +336,7 @@
|
||||
glow.icon_state = "clockwork_gateway_closing"
|
||||
if(GATEWAY_RATVAR_ARRIVAL to INFINITY)
|
||||
if(!purpose_fulfilled)
|
||||
countdown.stop()
|
||||
resistance_flags |= INDESTRUCTIBLE
|
||||
purpose_fulfilled = TRUE
|
||||
make_glow()
|
||||
animate(glow, transform = matrix() * 1.5, alpha = 255, time = 125)
|
||||
sound_to_playing_players(volume = 100, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/ratvar_rises.ogg')) //End the sounds
|
||||
sleep(125)
|
||||
make_glow()
|
||||
animate(glow, transform = matrix() * 3, alpha = 0, time = 5)
|
||||
QDEL_IN(src, 3)
|
||||
sleep(3)
|
||||
GLOB.clockwork_gateway_activated = TRUE
|
||||
var/turf/T = SSmapping.get_station_center()
|
||||
new /obj/structure/destructible/clockwork/massive/ratvar(T)
|
||||
var/x0 = T.x
|
||||
var/y0 = T.y
|
||||
for(var/I in spiral_range_turfs(255, T, tick_checked = TRUE))
|
||||
var/turf/T2 = I
|
||||
if(!T2)
|
||||
continue
|
||||
var/dist = cheap_hypotenuse(T2.x, T2.y, x0, y0)
|
||||
if(dist < 100)
|
||||
dist = TRUE
|
||||
else
|
||||
dist = FALSE
|
||||
T.ratvar_act(dist)
|
||||
CHECK_TICK
|
||||
fulfill_purpose()
|
||||
|
||||
//Converts nearby turfs into their clockwork equivalent, with ever-increasing range the closer the ark is to summoning Ratvar
|
||||
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/conversion_pulse()
|
||||
|
||||
@@ -60,12 +60,8 @@
|
||||
delay_remaining += PRISM_DELAY_DURATION
|
||||
toggle(0, user)
|
||||
|
||||
/obj/structure/destructible/clockwork/powered/prolonging_prism/process()
|
||||
var/turf/own_turf = get_turf(src)
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_CALL || delay_remaining <= 0 || !own_turf || !is_station_level(own_turf.z))
|
||||
forced_disable(FALSE)
|
||||
return
|
||||
. = ..()
|
||||
/obj/structure/destructible/clockwork/powered/prolonging_prism/proc/do_process()
|
||||
set waitfor = FALSE
|
||||
var/delay_amount = 40
|
||||
delay_remaining -= delay_amount
|
||||
var/efficiency = get_efficiency_mod()
|
||||
@@ -114,6 +110,14 @@
|
||||
new /obj/effect/temp_visual/ratvar/prolonging_prism(T)
|
||||
CHECK_TICK //we may be going over a hell of a lot of turfs
|
||||
|
||||
/obj/structure/destructible/clockwork/powered/prolonging_prism/process()
|
||||
var/turf/own_turf = get_turf(src)
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_CALL || delay_remaining <= 0 || !own_turf || !is_station_level(own_turf.z))
|
||||
forced_disable(FALSE)
|
||||
return
|
||||
. = ..()
|
||||
do_process()
|
||||
|
||||
/obj/structure/destructible/clockwork/powered/prolonging_prism/proc/get_delay_cost()
|
||||
return FLOOR(delay_cost, MIN_CLOCKCULT_POWER)
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
|
||||
//Put me in Reebe, will you? Ratvar has found and is going to do a hecking murder on Nar'Sie
|
||||
/obj/structure/destructible/clockwork/massive/ratvar/proc/clash_of_the_titans(obj/singularity/narsie/narsie)
|
||||
set waitfor = FALSE
|
||||
var/winner = "Undeclared"
|
||||
var/base_victory_chance = 1
|
||||
while(src && narsie)
|
||||
|
||||
@@ -204,26 +204,31 @@
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
return ..()
|
||||
|
||||
/obj/structure/destructible/cult/pylon/proc/heal_friends()
|
||||
set waitfor = FALSE
|
||||
for(var/mob/living/L in range(5, src))
|
||||
if(iscultist(L) || isshade(L) || isconstruct(L))
|
||||
if(L.health != L.maxHealth)
|
||||
new /obj/effect/temp_visual/heal(get_turf(src), "#960000")
|
||||
if(ishuman(L))
|
||||
L.adjustBruteLoss(-1, 0, only_organic = FALSE)
|
||||
L.adjustFireLoss(-1, 0, only_organic = FALSE)
|
||||
L.updatehealth()
|
||||
if(isshade(L) || isconstruct(L))
|
||||
var/mob/living/simple_animal/M = L
|
||||
if(M.health < M.maxHealth)
|
||||
M.adjustHealth(-3)
|
||||
if(ishuman(L) && L.blood_volume < (BLOOD_VOLUME_NORMAL * L.blood_ratio))
|
||||
L.blood_volume += 1.0
|
||||
CHECK_TICK
|
||||
|
||||
|
||||
/obj/structure/destructible/cult/pylon/process()
|
||||
if(!anchored)
|
||||
return
|
||||
if(last_heal <= world.time)
|
||||
last_heal = world.time + heal_delay
|
||||
for(var/mob/living/L in range(5, src))
|
||||
if(iscultist(L) || isshade(L) || isconstruct(L))
|
||||
if(L.health != L.maxHealth)
|
||||
new /obj/effect/temp_visual/heal(get_turf(src), "#960000")
|
||||
if(ishuman(L))
|
||||
L.adjustBruteLoss(-1, 0, only_organic = FALSE)
|
||||
L.adjustFireLoss(-1, 0, only_organic = FALSE)
|
||||
L.updatehealth()
|
||||
if(isshade(L) || isconstruct(L))
|
||||
var/mob/living/simple_animal/M = L
|
||||
if(M.health < M.maxHealth)
|
||||
M.adjustHealth(-3)
|
||||
if(ishuman(L) && L.blood_volume < (BLOOD_VOLUME_NORMAL * L.blood_ratio))
|
||||
L.blood_volume += 1.0
|
||||
CHECK_TICK
|
||||
heal_friends()
|
||||
if(last_corrupt <= world.time)
|
||||
var/list/validturfs = list()
|
||||
var/list/cultturfs = list()
|
||||
|
||||
@@ -515,7 +515,6 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
|
||||
var/mob/living/silicon/robot_devil = owner.current
|
||||
var/laws = list("You may not use violence to coerce someone into selling their soul.", "You may not directly and knowingly physically harm a devil, other than yourself.", GLOB.lawlorify[LAW][ban], GLOB.lawlorify[LAW][obligation], "Accomplish your objectives at all costs.")
|
||||
robot_devil.set_law_sixsixsix(laws)
|
||||
sleep(10)
|
||||
if(owner.assigned_role == "Clown" && ishuman(owner.current))
|
||||
var/mob/living/carbon/human/S = owner.current
|
||||
to_chat(S, "<span class='notice'>Your infernal nature has allowed you to overcome your clownishness.</span>")
|
||||
|
||||
@@ -401,6 +401,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
next_announce += DOOMSDAY_ANNOUNCE_INTERVAL
|
||||
|
||||
/obj/machinery/doomsday_device/proc/detonate()
|
||||
set waitfor = FALSE
|
||||
sound_to_playing_players('sound/machines/alarm.ogg')
|
||||
sleep(100)
|
||||
for(var/i in GLOB.mob_living_list)
|
||||
|
||||
@@ -197,6 +197,7 @@
|
||||
|
||||
//Here's the main proc itself
|
||||
/mob/living/carbon/human/proc/mob_climax(forced_climax=FALSE,cause = "") //Forced is instead of the other proc, makes you cum if you have the tools for it, ignoring restraints
|
||||
set waitfor = FALSE
|
||||
if(mb_cd_timer > world.time)
|
||||
if(!forced_climax) //Don't spam the message to the victim if forced to come too fast
|
||||
to_chat(src, "<span class='warning'>You need to wait [DisplayTimeText((mb_cd_timer - world.time), TRUE)] before you can do that again!</span>")
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
return
|
||||
|
||||
/obj/item/assembly/infra/proc/refreshBeam()
|
||||
set waitfor = FALSE
|
||||
QDEL_LIST(beams)
|
||||
if(throwing || !on || !secured)
|
||||
return
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
if(!air)
|
||||
return
|
||||
|
||||
if (air.get_oxidation_power(exposed_temperature) < 0.5)
|
||||
if (air.get_oxidation_power(exposed_temperature) < 0.5 || air.get_moles(GAS_HYPERNOB) > 5)
|
||||
return
|
||||
var/has_fuel = air.get_moles(GAS_PLASMA) > 0.5 || air.get_moles(GAS_TRITIUM) > 0.5 || air.get_fuel_amount(exposed_temperature) > 0.5
|
||||
if(active_hotspot)
|
||||
@@ -152,7 +152,7 @@
|
||||
if((temperature < FIRE_MINIMUM_TEMPERATURE_TO_EXIST) || (volume <= 1))
|
||||
qdel(src)
|
||||
return
|
||||
if(!location.air || location.air.get_oxidation_power() < 0.5 || (INSUFFICIENT(GAS_PLASMA) && INSUFFICIENT(GAS_TRITIUM) && location.air.get_fuel_amount() < 0.5))
|
||||
if(!location.air || location.air.get_moles(GAS_HYPERNOB) > 5 || location.air.get_oxidation_power() < 0.5 || (INSUFFICIENT(GAS_PLASMA) && INSUFFICIENT(GAS_TRITIUM) && location.air.get_fuel_amount() < 0.5))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
|
||||
@@ -187,6 +187,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/vore_flags = 0
|
||||
var/list/belly_prefs = list()
|
||||
var/vore_taste = "nothing in particular"
|
||||
var/vore_smell = null
|
||||
var/toggleeatingnoise = TRUE
|
||||
var/toggledigestionnoise = TRUE
|
||||
var/hound_sleeper = TRUE
|
||||
@@ -1068,6 +1069,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<b>Voracious MediHound sleepers:</b> <a href='?_src_=prefs;preference=hound_sleeper'>[(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Hear Vore Sounds:</b> <a href='?_src_=prefs;preference=toggleeatingnoise'>[(cit_toggles & EATING_NOISES) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Hear Vore Digestion Sounds:</b> <a href='?_src_=prefs;preference=toggledigestionnoise'>[(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Allow trash forcefeeding (requires Trashcan quirk)</b> <a href='?_src_=prefs;preference=toggleforcefeedtrash'>[(cit_toggles & TRASH_FORCEFEED) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Forced Feminization:</b> <a href='?_src_=prefs;preference=feminization'>[(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
dat += "<b>Forced Masculinization:</b> <a href='?_src_=prefs;preference=masculinization'>[(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
dat += "<b>Lewd Hypno:</b> <a href='?_src_=prefs;preference=hypno'>[(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
@@ -2800,6 +2802,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("toggledigestionnoise")
|
||||
cit_toggles ^= DIGESTION_NOISES
|
||||
|
||||
if("toggleforcefeedtrash")
|
||||
cit_toggles ^= TRASH_FORCEFEED
|
||||
|
||||
if("breast_enlargement")
|
||||
cit_toggles ^= BREAST_ENLARGEMENT
|
||||
|
||||
|
||||
@@ -821,6 +821,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
S["vore_flags"] >> vore_flags
|
||||
S["vore_taste"] >> vore_taste
|
||||
S["vore_smell"] >> vore_smell
|
||||
var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json"
|
||||
if(fexists(char_vr_path))
|
||||
var/list/json_from_file = json_decode(file2text(char_vr_path))
|
||||
@@ -994,6 +995,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
vore_flags = sanitize_integer(vore_flags, 0, MAX_VORE_FLAG, 0)
|
||||
vore_taste = copytext(vore_taste, 1, MAX_TASTE_LEN)
|
||||
vore_smell = copytext(vore_smell, 1, MAX_TASTE_LEN)
|
||||
belly_prefs = SANITIZE_LIST(belly_prefs)
|
||||
|
||||
cit_character_pref_load(S)
|
||||
@@ -1147,6 +1149,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
WRITE_FILE(S["vore_flags"] , vore_flags)
|
||||
WRITE_FILE(S["vore_taste"] , vore_taste)
|
||||
WRITE_FILE(S["vore_smell"] , vore_smell)
|
||||
var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json"
|
||||
var/belly_prefs_json = safe_json_encode(list("belly_prefs" = belly_prefs))
|
||||
if(fexists(char_vr_path))
|
||||
|
||||
@@ -482,3 +482,9 @@
|
||||
icon_state = "kabuto"
|
||||
item_state = "kabuto"
|
||||
flags_inv = HIDEHAIR|HIDEEARS
|
||||
|
||||
/obj/item/clothing/head/human_leather
|
||||
name = "human skin hat"
|
||||
desc = "This will scare them. All will know my power."
|
||||
icon_state = "human_leather"
|
||||
item_state = "human_leather"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
weight = 8
|
||||
|
||||
/datum/round_event/cat_surgeon/announce(fake)
|
||||
priority_announce("One of our... ahem... 'special' cases has escaped. Our sensors now show their tracker implant on your station. On an unrelated note, has anyone seen our cats?",
|
||||
priority_announce("One of our... ahem... 'special' cases has escaped. As it happens their last known location before their tracker went dead is your station so keep an eye out for them. On an unrelated note, has anyone seen our cats?",
|
||||
sender_override = "Nanotrasen Psych Ward")
|
||||
|
||||
/datum/round_event/cat_surgeon/start()
|
||||
|
||||
@@ -56,7 +56,10 @@
|
||||
next_boss_spawn = startWhen + CEILING(2 * number_of_hostiles / number_of_bosses, 1)
|
||||
|
||||
/datum/round_event/portal_storm/announce(fake)
|
||||
set waitfor = 0
|
||||
do_announce()
|
||||
|
||||
/datum/round_event/portal_storm/proc/do_announce()
|
||||
set waitfor = FALSE
|
||||
sound_to_playing_players('sound/magic/lightning_chargeup.ogg')
|
||||
sleep(80)
|
||||
priority_announce("Massive bluespace anomaly detected en route to [station_name()]. Brace for impact.")
|
||||
|
||||
@@ -7,5 +7,4 @@
|
||||
|
||||
/datum/round_event/wizard/fake_explosion/start()
|
||||
sound_to_playing_players('sound/machines/alarm.ogg')
|
||||
sleep(100)
|
||||
Cinematic(CINEMATIC_NUKE_FAKE,world)
|
||||
addtimer(CALLBACK(GLOBAL_PROC,.proc/Cinematic, CINEMATIC_NUKE_FAKE, world), 100)
|
||||
|
||||
@@ -64,7 +64,8 @@
|
||||
pass = FALSE
|
||||
return pass
|
||||
|
||||
/datum/proximity_monitor/advanced/process()
|
||||
/datum/proximity_monitor/advanced/proc/lag_checked_process()
|
||||
set waitfor = FALSE
|
||||
if(process_inner_turfs)
|
||||
for(var/turf/T in field_turfs)
|
||||
process_inner_turf(T)
|
||||
@@ -72,7 +73,10 @@
|
||||
if(process_edge_turfs)
|
||||
for(var/turf/T in edge_turfs)
|
||||
process_edge_turf(T)
|
||||
CHECK_TICK //Same here.
|
||||
CHECK_TICK //Same here.
|
||||
|
||||
/datum/proximity_monitor/advanced/process()
|
||||
lag_checked_process()
|
||||
|
||||
/datum/proximity_monitor/advanced/proc/process_inner_turf(turf/T)
|
||||
|
||||
|
||||
@@ -73,3 +73,40 @@
|
||||
icon_state = "barrel_open"
|
||||
else
|
||||
icon_state = "barrel"
|
||||
|
||||
/obj/structure/custom_keg
|
||||
name = "Plasteel Keg"
|
||||
desc = "A large plasteel keg. You can use it to hold liquids. You may wanna label this, too."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "keg"
|
||||
density = TRUE
|
||||
anchored = FALSE
|
||||
pressure_resistance = 2 * ONE_ATMOSPHERE
|
||||
max_integrity = 300
|
||||
var/open = FALSE
|
||||
|
||||
/obj/structure/custom_keg/Initialize()
|
||||
create_reagents(1000, DRAINABLE | AMOUNT_VISIBLE)
|
||||
. = ..()
|
||||
|
||||
/obj/structure/custom_keg/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>It is currently [open?"open, letting you pour liquids in.":"closed, letting you draw liquids from the tap."]</span>"
|
||||
|
||||
/obj/structure/custom_keg/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
open = !open
|
||||
if(open)
|
||||
DISABLE_BITFIELD(reagents.reagents_holder_flags, DRAINABLE)
|
||||
ENABLE_BITFIELD(reagents.reagents_holder_flags, REFILLABLE)
|
||||
to_chat(user, "<span class='notice'>You open [src], letting you fill it.</span>")
|
||||
else
|
||||
DISABLE_BITFIELD(reagents.reagents_holder_flags, REFILLABLE)
|
||||
ENABLE_BITFIELD(reagents.reagents_holder_flags, DRAINABLE)
|
||||
to_chat(user, "<span class='notice'>You close [src], letting you draw from its tap.</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/structure/custom_keg/update_icon_state()
|
||||
if(open)
|
||||
icon_state = "keg_open"
|
||||
else
|
||||
icon_state = "keg"
|
||||
|
||||
@@ -391,6 +391,7 @@
|
||||
mutate(4, 10, 2, 4, 50, 4, 10, 3)
|
||||
|
||||
/obj/machinery/hydroponics/proc/mutatespecie() // Mutagent produced a new plant!
|
||||
set waitfor = FALSE
|
||||
if(!myseed || dead)
|
||||
return
|
||||
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS,
|
||||
ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
|
||||
ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_LAWYER,
|
||||
ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_VAULT, ACCESS_MINING_STATION,
|
||||
ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM)
|
||||
ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_VAULT,
|
||||
ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY)
|
||||
minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_COURT, ACCESS_WEAPONS,
|
||||
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS,
|
||||
ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
|
||||
ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_LAWYER,
|
||||
ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_VAULT, ACCESS_MINING_STATION,
|
||||
ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM)
|
||||
ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_VAULT,
|
||||
ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY)
|
||||
paycheck = PAYCHECK_COMMAND
|
||||
paycheck_department = ACCOUNT_SRV
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
minimal_access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_QM, ACCESS_MINING,
|
||||
ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_KEYCARD_AUTH, ACCESS_RC_ANNOUNCE,
|
||||
ACCESS_SEC_DOORS, ACCESS_HEADS)
|
||||
paycheck = PAYCHECK_HARD //They can already buy stuff using cargo budget, don't give em a command-level paycheck.
|
||||
paycheck = PAYCHECK_HARD //They can already buy stuff using cargo budget, don't give em a command-level paycheck. //alright i'll agree to that -qweq
|
||||
paycheck_department = ACCOUNT_CAR
|
||||
|
||||
display_order = JOB_DISPLAY_ORDER_QUARTERMASTER
|
||||
|
||||
@@ -89,6 +89,11 @@
|
||||
name = "large empty capsule"
|
||||
desc = "An extremly large capsule which requires power. Useful for projects all over."
|
||||
template_id = "shelter_delta"
|
||||
|
||||
/obj/item/survivalcapsule/luxury/penthouse
|
||||
name = "penthouse bluespace sheler capsule"
|
||||
desc = "The absolute pinnacle of luxury in terms of survival capsules. While exuberantly expensive it has everything needed to make a small home in lavaland."
|
||||
template_id = "shelter_epsilon"
|
||||
//Pod objects
|
||||
|
||||
//Window
|
||||
|
||||
@@ -61,37 +61,32 @@
|
||||
new /obj/item/guardiancreator(src)
|
||||
|
||||
/obj/structure/closet/crate/necropolis/tendril/weapon_armor/PopulateContents()
|
||||
var/loot = rand(1,11)
|
||||
var/loot = rand(1,10)
|
||||
switch(loot)
|
||||
if(1)
|
||||
new /obj/item/clothing/suit/space/hardsuit/cult(src)
|
||||
if(2)
|
||||
new /obj/item/katana/lavaland(src)
|
||||
if(3)
|
||||
if(prob(50))
|
||||
new /obj/item/disk/design_disk/modkit_disc/resonator_blast(src)
|
||||
else
|
||||
new /obj/item/disk/design_disk/modkit_disc/rapid_repeater(src)
|
||||
if(4)
|
||||
new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker/old(src)
|
||||
if(5)
|
||||
if(4)
|
||||
new /obj/item/nullrod/scythe/talking(src)
|
||||
if(6)
|
||||
if(5)
|
||||
new /obj/item/nullrod/armblade(src)
|
||||
if(7)
|
||||
if(6)
|
||||
new /obj/item/reagent_containers/food/drinks/bottle/holywater/hell(src)
|
||||
new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor/old(src)
|
||||
if(8)
|
||||
if(7)
|
||||
new /obj/item/grenade/clusterbuster/inferno(src)
|
||||
if(9)
|
||||
if(8)
|
||||
new /obj/item/gun/magic/wand/book/shock(src)
|
||||
if(10)
|
||||
if(9)
|
||||
new /obj/item/gun/magic/wand/book/page(src)
|
||||
if(11)
|
||||
if(10)
|
||||
new /obj/item/gun/magic/wand/book/spark(src)
|
||||
|
||||
/obj/structure/closet/crate/necropolis/tendril/misc/PopulateContents()
|
||||
var/loot = rand(1,14)
|
||||
var/loot = rand(1,12)
|
||||
switch(loot)
|
||||
if(1)
|
||||
new /obj/item/shared_storage/red(src)
|
||||
@@ -106,31 +101,21 @@
|
||||
if(6)
|
||||
new /obj/item/jacobs_ladder(src)
|
||||
if(7)
|
||||
if(prob(50))
|
||||
new /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe(src)
|
||||
else
|
||||
new /obj/item/disk/design_disk/modkit_disc/bounty(src)
|
||||
if(8)
|
||||
new /obj/item/wisp_lantern(src)
|
||||
if(9)
|
||||
if(8)
|
||||
new /obj/item/pickaxe/rosegold(src)
|
||||
if(10)
|
||||
if(9)
|
||||
new /obj/item/bedsheet/cosmos(src)
|
||||
new /obj/item/melee/skateboard/hoverboard(src)
|
||||
if(11)
|
||||
if(10)
|
||||
new /obj/item/disk/tech_disk/illegal(src)
|
||||
if(12)
|
||||
if(11)
|
||||
new /obj/item/clothing/suit/space/hardsuit/cult(src)
|
||||
if(13)
|
||||
if(12)
|
||||
new /obj/item/katana/lavaland(src)
|
||||
if(14)
|
||||
if(prob(50))
|
||||
new /obj/item/disk/design_disk/modkit_disc/resonator_blast(src)
|
||||
else
|
||||
new /obj/item/disk/design_disk/modkit_disc/rapid_repeater(src)
|
||||
|
||||
/obj/structure/closet/crate/necropolis/tendril/all/PopulateContents()
|
||||
var/loot = rand(1,29)
|
||||
var/loot = rand(1,28)
|
||||
switch(loot)
|
||||
if(1)
|
||||
new /obj/item/shared_storage/red(src)
|
||||
@@ -145,56 +130,51 @@
|
||||
if(6)
|
||||
new /obj/item/jacobs_ladder(src)
|
||||
if(7)
|
||||
if(prob(50))
|
||||
new /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe(src)
|
||||
else
|
||||
new /obj/item/disk/design_disk/modkit_disc/bounty(src)
|
||||
if(8)
|
||||
new /obj/item/wisp_lantern(src)
|
||||
if(9)
|
||||
if(8)
|
||||
new /obj/item/pickaxe/rosegold(src)
|
||||
if(10)
|
||||
if(9)
|
||||
new /obj/item/bedsheet/cosmos(src)
|
||||
new /obj/item/melee/skateboard/hoverboard(src)
|
||||
if(11)
|
||||
if(10)
|
||||
new /obj/item/disk/tech_disk/illegal(src)
|
||||
if(12)
|
||||
if(11)
|
||||
new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker/old(src)
|
||||
if(13)
|
||||
if(12)
|
||||
new /obj/item/nullrod/scythe/talking(src)
|
||||
if(14)
|
||||
if(13)
|
||||
new /obj/item/nullrod/armblade(src)
|
||||
if(15)
|
||||
if(14)
|
||||
new /obj/item/reagent_containers/food/drinks/bottle/holywater/hell(src)
|
||||
new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor/old(src)
|
||||
if(16)
|
||||
if(15)
|
||||
new /obj/item/grenade/clusterbuster/inferno(src)
|
||||
if(17)
|
||||
if(16)
|
||||
new /obj/item/gun/magic/wand/book/shock(src)
|
||||
if(18)
|
||||
if(17)
|
||||
new /obj/item/gun/magic/wand/book/page(src)
|
||||
if(19)
|
||||
if(18)
|
||||
new /obj/item/gun/magic/wand/book/spark(src)
|
||||
if(20)
|
||||
if(19)
|
||||
new /obj/item/soulstone/anybody(src)
|
||||
if(21)
|
||||
if(20)
|
||||
new /obj/item/rod_of_asclepius(src)
|
||||
if(22)
|
||||
if(21)
|
||||
new /obj/item/organ/heart/cursed/wizard(src)
|
||||
if(23)
|
||||
if(22)
|
||||
new /obj/item/book/granter/spell/summonitem(src)
|
||||
if(24)
|
||||
if(23)
|
||||
new /obj/item/borg/upgrade/modkit/lifesteal(src)
|
||||
new /obj/item/bedsheet/cult(src)
|
||||
if(25)
|
||||
if(24)
|
||||
new /obj/item/clothing/neck/necklace/memento_mori(src)
|
||||
if(26)
|
||||
if(25)
|
||||
new /obj/item/warp_cube/red(src)
|
||||
if(27)
|
||||
if(26)
|
||||
new /obj/item/immortality_talisman(src)
|
||||
if(28)
|
||||
if(27)
|
||||
new /obj/item/gun/magic/wand/book/healing(src)
|
||||
if(29)
|
||||
if(28)
|
||||
new /obj/item/guardiancreator(src)
|
||||
|
||||
//KA modkit design discs
|
||||
|
||||
@@ -145,8 +145,11 @@
|
||||
D.createmessage("Ore Redemption Machine", "New minerals available!", msg, 1, 0)
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/process()
|
||||
if(!materials.mat_container || panel_open || !powered())
|
||||
return
|
||||
if(materials.mat_container && !panel_open && powered())
|
||||
process_all_ores()
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/proc/process_all_ores()
|
||||
set waitfor = FALSE
|
||||
var/atom/input = get_step(src, input_dir)
|
||||
var/obj/structure/ore_box/OB = locate() in input
|
||||
if(OB)
|
||||
@@ -165,6 +168,7 @@
|
||||
else if(!message_sent)
|
||||
send_console_message()
|
||||
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/attackby(obj/item/W, mob/user, params)
|
||||
if(default_unfasten_wrench(user, W))
|
||||
return
|
||||
|
||||
@@ -10,22 +10,25 @@
|
||||
output_dir = EAST
|
||||
speed_process = TRUE
|
||||
|
||||
/obj/machinery/mineral/unloading_machine/process()
|
||||
var/turf/T = get_step(src,input_dir)
|
||||
if(T)
|
||||
var/limit
|
||||
for(var/obj/structure/ore_box/B in T)
|
||||
for (var/obj/item/stack/ore/O in B)
|
||||
B.contents -= O
|
||||
unload_mineral(O)
|
||||
limit++
|
||||
if (limit>=10)
|
||||
return
|
||||
CHECK_TICK
|
||||
CHECK_TICK
|
||||
for(var/obj/item/I in T)
|
||||
unload_mineral(I)
|
||||
/obj/machinery/mineral/unloading_machine/proc/horrible_quadratic_monster(var/turf/T)
|
||||
set waitfor = FALSE
|
||||
var/limit = 0
|
||||
for(var/obj/structure/ore_box/B in T)
|
||||
for (var/obj/item/stack/ore/O in B)
|
||||
B.contents -= O
|
||||
unload_mineral(O)
|
||||
limit++
|
||||
if (limit>=10)
|
||||
return
|
||||
CHECK_TICK
|
||||
for(var/obj/item/I in T)
|
||||
unload_mineral(I)
|
||||
limit++
|
||||
if (limit>=10)
|
||||
return
|
||||
CHECK_TICK
|
||||
|
||||
/obj/machinery/mineral/unloading_machine/process()
|
||||
var/turf/T = get_step(src,input_dir)
|
||||
if(T)
|
||||
horrible_quadratic_monster(T)
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
new /datum/data/mining_equipment("Luxury Shelter Capsule", /obj/item/survivalcapsule/luxury, 3000),
|
||||
new /datum/data/mining_equipment("Luxury Bar Capsule", /obj/item/survivalcapsule/luxury/elitebar, 10000),
|
||||
new /datum/data/mining_equipment("Empty Capsule", /obj/item/survivalcapsule/luxury/empty, 5000),
|
||||
new /datum/data/mining_equipment("Penthouse Capsule", /obj/item/survivalcapsule/luxury/penthouse, 15000),
|
||||
new /datum/data/mining_equipment("Nanotrasen Minebot", /mob/living/simple_animal/hostile/mining_drone, 800),
|
||||
new /datum/data/mining_equipment("Minebot Melee Upgrade", /obj/item/mine_bot_upgrade, 400),
|
||||
new /datum/data/mining_equipment("Minebot Armor Upgrade", /obj/item/mine_bot_upgrade/health, 400),
|
||||
|
||||
@@ -64,8 +64,6 @@
|
||||
if(materials.use_amount_mat(coin_mat, chosen))
|
||||
for(var/coin_to_make in 1 to 5)
|
||||
create_coins()
|
||||
produced_coins++
|
||||
CHECK_TICK
|
||||
else
|
||||
var/found_new = FALSE
|
||||
for(var/datum/material/inserted_material in materials.materials)
|
||||
@@ -131,6 +129,7 @@
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mineral/mint/proc/create_coins()
|
||||
set waitfor = FALSE
|
||||
var/turf/T = get_step(src,output_dir)
|
||||
var/temp_list = list()
|
||||
temp_list[chosen] = 400
|
||||
@@ -143,3 +142,5 @@
|
||||
O.forceMove(bag_to_use) //don't bother sending the signal, the new bag is empty and all that.
|
||||
|
||||
SSblackbox.record_feedback("amount", "coins_minted", 1)
|
||||
produced_coins++
|
||||
CHECK_TICK
|
||||
|
||||
@@ -85,3 +85,14 @@
|
||||
. = ..()
|
||||
whitelisted_turfs = typecacheof(/turf/closed/mineral)
|
||||
banned_objects = typecacheof(/obj/structure/stone_tile)
|
||||
|
||||
/datum/map_template/shelter/epsilon
|
||||
name = "Shelter Epsilon"
|
||||
shelter_id = "shelter_epsilon"
|
||||
description = "A small apartment in the palm of your hand."
|
||||
mappath = "_maps/templates/shelter_5.dmm"
|
||||
|
||||
/datum/map_template/shelter/epsilon/New()
|
||||
. = ..()
|
||||
whitelisted_turfs = typecacheof(/turf/closed/mineral)
|
||||
banned_objects = typecacheof(/obj/structure/stone_tile)
|
||||
|
||||
@@ -679,7 +679,7 @@
|
||||
icon_state = "crow"
|
||||
matrixed_sections = MATRIX_RED
|
||||
|
||||
/datum/sprite_accessory/tails/mam_tail/cow
|
||||
/datum/sprite_accessory/tails/mam_tails/cow
|
||||
name = "Cow"
|
||||
icon_state = "cow"
|
||||
matrixed_sections = MATRIX_RED
|
||||
|
||||
@@ -358,7 +358,7 @@
|
||||
return
|
||||
I.item_flags |= BEING_REMOVED
|
||||
breakouttime = I.breakouttime
|
||||
var/datum/cuffbreak_checker/cuffbreak_checker = new(get_turf(src))
|
||||
var/datum/cuffbreak_checker/cuffbreak_checker = new(get_turf(src), istype(I, /obj/item/restraints)? I : null)
|
||||
if(!cuff_break)
|
||||
visible_message("<span class='warning'>[src] attempts to remove [I]!</span>")
|
||||
to_chat(src, "<span class='notice'>You attempt to remove [I]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)</span>")
|
||||
@@ -384,16 +384,22 @@
|
||||
|
||||
/datum/cuffbreak_checker
|
||||
var/turf/last
|
||||
var/obj/item/restraints/cuffs
|
||||
|
||||
/datum/cuffbreak_checker/New(turf/initial_turf)
|
||||
/datum/cuffbreak_checker/New(turf/initial_turf, obj/item/restraints/R)
|
||||
last = initial_turf
|
||||
if(R)
|
||||
cuffs = R
|
||||
|
||||
/datum/cuffbreak_checker/proc/check_movement(atom/user, delay, atom/target, time_left, do_after_flags, required_mobility_flags, required_combat_flags, mob_redirect, stage, initially_held_item, tool, list/passed_in)
|
||||
if(get_turf(user) != last)
|
||||
last = get_turf(user)
|
||||
passed_in[1] = 0.5
|
||||
if(cuffs && !cuffs.allow_breakout_movement)
|
||||
return DO_AFTER_STOP
|
||||
else
|
||||
passed_in[1] = 1
|
||||
return DO_AFTER_CONTINUE
|
||||
|
||||
/mob/living/carbon/proc/uncuff()
|
||||
if (handcuffed)
|
||||
@@ -961,7 +967,9 @@
|
||||
/mob/living/carbon/ExtinguishMob()
|
||||
for(var/X in get_equipped_items())
|
||||
var/obj/item/I = X
|
||||
I.acid_level = 0 //washes off the acid on our clothes
|
||||
var/datum/component/acid/acid = I.GetComponent(/datum/component/acid)
|
||||
if(acid)
|
||||
acid.level = 0
|
||||
I.extinguish() //extinguishes our clothes
|
||||
..()
|
||||
|
||||
|
||||
@@ -1101,9 +1101,9 @@
|
||||
if(HAS_TRAIT(src, TRAIT_TOXINLOVER))
|
||||
return "<font color='#00ffff'>"
|
||||
if(isplasmaman(src))
|
||||
return "<font color='#800080'"
|
||||
return "<font color='#800080'>"
|
||||
if(isgolem(src))
|
||||
return "<font color='#8b4513'"
|
||||
return "<font color='#8b4513'>"
|
||||
return "<font color='#18d855'>"
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
block_parry_data = /datum/block_parry_data/unarmed/human
|
||||
default_block_parry_data = /datum/block_parry_data/unarmed/human
|
||||
causes_dirt_buildup_on_floor = TRUE
|
||||
|
||||
//Hair colour and style
|
||||
var/hair_color = "000"
|
||||
@@ -52,6 +51,9 @@
|
||||
var/obj/item/l_store = null
|
||||
var/obj/item/s_store = null
|
||||
|
||||
/// When an braindead player has their equipment fiddled with, we log that info here for when they come back so they know who took their ID while they were DC'd for 30 seconds
|
||||
var/list/afk_thefts
|
||||
|
||||
var/special_voice = "" // For changing our voice. Used by a symptom.
|
||||
|
||||
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
|
||||
|
||||
@@ -90,13 +90,31 @@
|
||||
//End bloody footprints
|
||||
|
||||
S.step_action()
|
||||
if(movement_type & GROUND)
|
||||
dirt_buildup()
|
||||
|
||||
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee.
|
||||
if(dna.species.space_move(src))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/dirt_buildup(strength)
|
||||
/mob/living/carbon/human/proc/dirt_buildup(strength = 1)
|
||||
if(!shoes || !(shoes.body_parts_covered & FEET))
|
||||
return // barefoot advantage
|
||||
return ..()
|
||||
var/turf/open/T = loc
|
||||
if(!istype(T) || !T.dirt_buildup_allowed)
|
||||
return
|
||||
var/area/A = T.loc
|
||||
if(!A.dirt_buildup_allowed)
|
||||
return
|
||||
var/multiplier = CONFIG_GET(number/turf_dirty_multiplier)
|
||||
strength *= multiplier
|
||||
var/obj/effect/decal/cleanable/dirt/D = locate() in T
|
||||
if(D)
|
||||
D.dirty(strength)
|
||||
else
|
||||
T.dirtyness += strength
|
||||
if(T.dirtyness >= (isnull(T.dirt_spawn_threshold)? CONFIG_GET(number/turf_dirt_threshold) : T.dirt_spawn_threshold))
|
||||
D = new /obj/effect/decal/cleanable/dirt(T)
|
||||
D.dirty(T.dirt_spawn_threshold - T.dirtyness)
|
||||
T.dirtyness = 0 // reset.
|
||||
|
||||
@@ -2,3 +2,33 @@
|
||||
..()
|
||||
if(dna?.species?.has_field_of_vision && CONFIG_GET(flag/use_field_of_vision))
|
||||
LoadComponent(/datum/component/field_of_vision, field_of_vision_type)
|
||||
|
||||
if(!LAZYLEN(afk_thefts))
|
||||
return
|
||||
|
||||
var/list/print_msg = list()
|
||||
print_msg += "<span class='info'>*---------*</span>"
|
||||
print_msg += "<span class='userdanger'>As you snap back to consciousness, you recall people messing with your stuff...</span>"
|
||||
|
||||
afk_thefts = reverseRange(afk_thefts)
|
||||
|
||||
for(var/list/iter_theft as anything in afk_thefts)
|
||||
if(!islist(iter_theft) || LAZYLEN(iter_theft) != AFK_THEFT_TIME)
|
||||
stack_trace("[src] ([ckey]) returned to their body and had a null/malformed afk_theft entry. Contents: [json_encode(iter_theft)]")
|
||||
continue
|
||||
|
||||
var/thief_name = iter_theft[AFK_THEFT_NAME]
|
||||
var/theft_message = iter_theft[AFK_THEFT_MESSAGE]
|
||||
var/time_since = world.time - iter_theft[AFK_THEFT_TIME]
|
||||
|
||||
if(time_since > AFK_THEFT_FORGET_DETAILS_TIME)
|
||||
print_msg += "\t<span class='danger'><b>Someone [theft_message], but it was at least [DisplayTimeText(AFK_THEFT_FORGET_DETAILS_TIME)] ago.</b></span>"
|
||||
else
|
||||
print_msg += "\t<span class='danger'><b>[thief_name] [theft_message] roughly [DisplayTimeText(time_since, 10)] ago.</b></span>"
|
||||
|
||||
if(LAZYLEN(afk_thefts) >= AFK_THEFT_MAX_MESSAGES)
|
||||
print_msg += "<span class='warning'>There may have been more, but that's all you can remember...</span>"
|
||||
print_msg += "<span class='info'>*---------*</span>"
|
||||
|
||||
to_chat(src, print_msg.Join("\n"))
|
||||
LAZYNULL(afk_thefts)
|
||||
|
||||
@@ -911,6 +911,12 @@
|
||||
"<span class='userdanger'>[src] tries to remove your [what.name].</span>", target = src,
|
||||
target_message = "<span class='danger'>You try to remove [who]'s [what.name].</span>")
|
||||
what.add_fingerprint(src)
|
||||
if(ishuman(who))
|
||||
var/mob/living/carbon/human/victim_human = who
|
||||
if(victim_human.key && !victim_human.client) // AKA braindead
|
||||
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
|
||||
var/list/new_entry = list(list(src.name, "tried unequipping your [what]", world.time))
|
||||
LAZYADD(victim_human.afk_thefts, new_entry)
|
||||
else
|
||||
to_chat(src,"<span class='notice'>You try to remove [who]'s [what.name].</span>")
|
||||
what.add_fingerprint(src)
|
||||
@@ -957,6 +963,13 @@
|
||||
to_chat(src, "<span class='warning'>\The [what.name] doesn't fit in that place!</span>")
|
||||
return
|
||||
|
||||
if(ishuman(who))
|
||||
var/mob/living/carbon/human/victim_human = who
|
||||
if(victim_human.key && !victim_human.client) // AKA braindead
|
||||
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
|
||||
var/list/new_entry = list(list(src.name, "tried equipping you with [what]", world.time))
|
||||
LAZYADD(victim_human.afk_thefts, new_entry)
|
||||
|
||||
who.visible_message("<span class='notice'>[src] tries to put [what] on [who].</span>",
|
||||
"<span class='notice'>[src] tries to put [what] on you.</span>", target = src,
|
||||
target_message = "<span class='notice'>You try to put [what] on [who].</span>")
|
||||
|
||||
@@ -67,8 +67,6 @@
|
||||
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
|
||||
var/incorporeal_move = FALSE //FALSE is off, INCORPOREAL_MOVE_BASIC is normal, INCORPOREAL_MOVE_SHADOW is for ninjas
|
||||
//and INCORPOREAL_MOVE_JAUNT is blocked by holy water/salt
|
||||
/// Do we make floors dirty as we move?
|
||||
var/causes_dirt_buildup_on_floor = FALSE
|
||||
|
||||
var/list/roundstart_quirks = list()
|
||||
|
||||
|
||||
@@ -102,31 +102,6 @@
|
||||
if(lying && !buckled && prob(getBruteLoss()*200/maxHealth))
|
||||
makeTrail(newloc, T, old_direction)
|
||||
|
||||
if(causes_dirt_buildup_on_floor && (movement_type & GROUND))
|
||||
dirt_buildup()
|
||||
|
||||
/**
|
||||
* Attempts to make the floor dirty.
|
||||
*/
|
||||
/mob/living/proc/dirt_buildup(strength = 1)
|
||||
var/turf/open/T = loc
|
||||
if(!istype(T) || !T.dirt_buildup_allowed)
|
||||
return
|
||||
var/area/A = T.loc
|
||||
if(!A.dirt_buildup_allowed)
|
||||
return
|
||||
var/multiplier = CONFIG_GET(number/turf_dirty_multiplier)
|
||||
strength *= multiplier
|
||||
var/obj/effect/decal/cleanable/dirt/D = locate() in T
|
||||
if(D)
|
||||
D.dirty(strength)
|
||||
else
|
||||
T.dirtyness += strength
|
||||
if(T.dirtyness >= (isnull(T.dirt_spawn_threshold)? CONFIG_GET(number/turf_dirt_threshold) : T.dirt_spawn_threshold))
|
||||
D = new /obj/effect/decal/cleanable/dirt(T)
|
||||
D.dirty(T.dirt_spawn_threshold - T.dirtyness)
|
||||
T.dirtyness = 0 // reset.
|
||||
|
||||
/mob/living/Move_Pulled(atom/A)
|
||||
. = ..()
|
||||
if(!. || !isliving(A))
|
||||
|
||||
@@ -182,6 +182,7 @@
|
||||
. = ..()
|
||||
|
||||
/mob/living/silicon/ai/proc/set_core_display_icon(input, client/C)
|
||||
set waitfor = FALSE
|
||||
if(client && !C)
|
||||
C = client
|
||||
if(!input && !C?.prefs?.preferred_ai_core_display)
|
||||
|
||||
@@ -133,6 +133,10 @@
|
||||
chance_to_hold_onto_points = highest_cost*0.5
|
||||
if(points != max_points && prob(chance_to_hold_onto_points))
|
||||
return //Let's save our points for a better ability (unless we're at max points, in which case we can't save anymore!)
|
||||
do_ability()
|
||||
|
||||
/datum/boss_active_timed_battle/proc/do_ability()
|
||||
set waitfor = FALSE
|
||||
if(!boss.client)
|
||||
abilities = shuffle(abilities)
|
||||
for(var/ab in abilities)
|
||||
|
||||
@@ -364,11 +364,10 @@
|
||||
/mob/living/simple_animal/hostile/proc/AttackingTarget()
|
||||
SEND_SIGNAL(src, COMSIG_HOSTILE_ATTACKINGTARGET, target)
|
||||
in_melee = TRUE
|
||||
/* sorry for the simplemob vore fans
|
||||
if(vore_active)
|
||||
if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
if(!client && L.Adjacent(src) && CHECK_BITFIELD(L.vore_flags,DEVOURABLE)) // aggressive check to ensure vore attacks can be made
|
||||
if(!client && L.Adjacent(src) && CHECK_BITFIELD(L.vore_flags, DEVOURABLE) && CHECK_BITFIELD(L.vore_flags, MOBVORE)) // aggressive check to ensure vore attacks can be made
|
||||
if(prob(voracious_chance))
|
||||
vore_attack(src,L,src)
|
||||
else
|
||||
@@ -379,7 +378,6 @@
|
||||
return target.attack_animal(src)
|
||||
else
|
||||
return target.attack_animal(src)
|
||||
*/
|
||||
return target.attack_animal(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/proc/Aggro()
|
||||
|
||||
@@ -40,8 +40,10 @@ Difficulty: Medium
|
||||
ranged = 1
|
||||
ranged_cooldown_time = 16
|
||||
pixel_x = -16
|
||||
crusher_loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator/premiumka, /obj/item/crusher_trophy/miner_eye)
|
||||
loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator/premiumka)
|
||||
crusher_loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator/premiumka, /obj/item/crusher_trophy/miner_eye, /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe,
|
||||
/obj/item/disk/design_disk/modkit_disc/bounty,/obj/item/disk/design_disk/modkit_disc/resonator_blast,/obj/item/disk/design_disk/modkit_disc/rapid_repeater)
|
||||
loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator/premiumka,/obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe,
|
||||
/obj/item/disk/design_disk/modkit_disc/bounty,/obj/item/disk/design_disk/modkit_disc/resonator_blast,/obj/item/disk/design_disk/modkit_disc/rapid_repeater)
|
||||
wander = FALSE
|
||||
del_on_death = TRUE
|
||||
blood_volume = BLOOD_VOLUME_NORMAL
|
||||
|
||||
@@ -26,8 +26,10 @@ Difficulty: Extremely Hard
|
||||
speed = 20
|
||||
move_to_delay = 20
|
||||
ranged = TRUE
|
||||
crusher_loot = list(/obj/effect/decal/remains/plasma, /obj/item/crusher_trophy/ice_block_talisman)
|
||||
loot = list(/obj/effect/decal/remains/plasma)
|
||||
crusher_loot = list(/obj/effect/decal/remains/plasma, /obj/item/crusher_trophy/ice_block_talisman, ,/obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe,
|
||||
/obj/item/disk/design_disk/modkit_disc/bounty,/obj/item/disk/design_disk/modkit_disc/resonator_blast,/obj/item/disk/design_disk/modkit_disc/rapid_repeater)
|
||||
loot = list(/obj/effect/decal/remains/plasma, ,/obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe,
|
||||
/obj/item/disk/design_disk/modkit_disc/bounty,/obj/item/disk/design_disk/modkit_disc/resonator_blast,/obj/item/disk/design_disk/modkit_disc/rapid_repeater)
|
||||
wander = FALSE
|
||||
del_on_death = TRUE
|
||||
blood_volume = BLOOD_VOLUME_NORMAL
|
||||
|
||||
@@ -102,23 +102,13 @@
|
||||
consume_bait()
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/proc/consume_bait()
|
||||
var/list/L = list()
|
||||
for(var/obj/O in view(src, 9))
|
||||
L += O
|
||||
var/obj/item/stack/ore/diamond/diamonds = locate(/obj/item/stack/ore/diamond) in L
|
||||
if(diamonds)
|
||||
var/distanced = 0
|
||||
distanced = get_dist(loc,diamonds.loc)
|
||||
if(distanced <= 1 && diamonds)
|
||||
qdel(diamonds)
|
||||
src.visible_message("<span class='notice'>[src] consumes [diamonds], and it disappears! ...At least, you think.</span>")
|
||||
var/obj/item/pen/survival/bait = locate(/obj/item/pen/survival) in L
|
||||
if(bait)
|
||||
var/distanceb = 0
|
||||
distanceb = get_dist(loc,bait.loc)
|
||||
if(distanceb <= 1 && bait)
|
||||
qdel(bait)
|
||||
visible_message("<span class='notice'>[src] examines [bait] closer, and telekinetically shatters the pen.</span>")
|
||||
for(var/obj/O in view(1, src))
|
||||
if(istype(O, /obj/item/stack/ore/diamond))
|
||||
qdel(O)
|
||||
src.visible_message("<span class='notice'>[src] consumes [O], and it disappears! ...At least, you think.</span>")
|
||||
else if(istype(O, /obj/item/pen/survival))
|
||||
qdel(O)
|
||||
src.visible_message("<span class='notice'>[src] examines [O] closer, and telekinetically shatters the pen.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
. = ..()
|
||||
|
||||
if((direction & (direction - 1)) && mob.loc == n) //moved diagonally successfully
|
||||
add_delay *= 2
|
||||
add_delay *= SQRT_2
|
||||
mob.set_glide_size(DELAY_TO_GLIDE_SIZE(add_delay), FALSE)
|
||||
move_delay += add_delay
|
||||
if(.) // If mob is null here, we deserve the runtime
|
||||
|
||||
@@ -349,6 +349,7 @@
|
||||
|
||||
// Relays kill program request to currently active program. Use this to quit current program.
|
||||
/obj/item/modular_computer/proc/kill_program(forced = FALSE)
|
||||
set waitfor = FALSE
|
||||
if(active_program)
|
||||
active_program.kill_program(forced)
|
||||
active_program = null
|
||||
|
||||
@@ -287,7 +287,9 @@
|
||||
|
||||
/datum/reagent/water/reaction_obj(obj/O, reac_volume)
|
||||
O.extinguish()
|
||||
O.acid_level = 0
|
||||
var/datum/component/acid/acid = O.GetComponent(/datum/component/acid)
|
||||
if(acid)
|
||||
acid.level = 0
|
||||
// cubes
|
||||
if(istype(O, /obj/item/reagent_containers/food/snacks/cube))
|
||||
var/obj/item/reagent_containers/food/snacks/cube/cube = O
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
|
||||
/datum/chemical_reaction/proc/on_reaction(datum/reagents/holder, multiplier, specialreact)
|
||||
set waitfor = FALSE
|
||||
return
|
||||
//I recommend you set the result amount to the total volume of all components.
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
var/stream_mode = 0 //whether we use the more focused mode
|
||||
var/current_range = 3 //the range of tiles the sprayer will reach.
|
||||
var/spray_range = 3 //the range of tiles the sprayer will reach when in spray mode.
|
||||
var/stream_range = 1 //the range of tiles the sprayer will reach when in stream mode.
|
||||
var/stream_range = 3 //the range of tiles the sprayer will reach when in stream mode.
|
||||
var/stream_amount = 10 //the amount of reagents transfered when in stream mode.
|
||||
/// Amount of time it takes for a spray to completely travel.
|
||||
var/spray_delay = 8
|
||||
@@ -74,19 +74,18 @@
|
||||
return
|
||||
var/range = clamp(get_dist(src, A), 1, current_range)
|
||||
var/wait_step = CEILING(spray_delay * INVERSE(range), world.tick_lag)
|
||||
var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src), stream_mode, wait_step, range, stream_mode? 1 : range)
|
||||
var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src), stream_mode, wait_step, range, stream_mode? 1 : range, amount_per_transfer_from_this)
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
return
|
||||
log_reagent("SPRAY: [key_name(usr)] fired [src] ([REF(src)]) [COORD(T)] at [A] ([REF(A)]) [COORD(A)] (chempuff: [D.reagents.log_list()])")
|
||||
D.create_reagents(amount_per_transfer_from_this, NONE, NO_REAGENTS_VALUE)
|
||||
if(stream_mode)
|
||||
reagents.trans_to(D, amount_per_transfer_from_this)
|
||||
else
|
||||
reagents.trans_to(D, amount_per_transfer_from_this, 1/range)
|
||||
D.color = mix_color_from_reagents(D.reagents.reagent_list)
|
||||
D.add_atom_colour(mix_color_from_reagents(D.reagents.reagent_list), TEMPORARY_COLOUR_PRIORITY)
|
||||
last_spray = world.time
|
||||
D.run_puff(A)
|
||||
INVOKE_ASYNC(D, /obj/effect/decal/chempuff/proc/run_puff, A)
|
||||
|
||||
/obj/item/reagent_containers/spray/attack_self(mob/user)
|
||||
stream_mode = !stream_mode
|
||||
|
||||
@@ -268,16 +268,19 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
|
||||
// timed process
|
||||
// if the switch changed, update the linked conveyors
|
||||
|
||||
/obj/machinery/conveyor_switch/process()
|
||||
if(!operated)
|
||||
return
|
||||
operated = 0
|
||||
|
||||
/obj/machinery/conveyor_switch/proc/do_process()
|
||||
set waitfor = FALSE
|
||||
for(var/obj/machinery/conveyor/C in GLOB.conveyors_by_id[id])
|
||||
C.operating = position
|
||||
C.update_move_direction()
|
||||
CHECK_TICK
|
||||
|
||||
/obj/machinery/conveyor_switch/process()
|
||||
if(!operated)
|
||||
return
|
||||
operated = 0
|
||||
do_process()
|
||||
|
||||
// attack with hand, switch position
|
||||
/obj/machinery/conveyor_switch/interact(mob/user)
|
||||
add_fingerprint(user)
|
||||
|
||||
@@ -622,7 +622,9 @@
|
||||
var/obj/O = owner.get_active_held_item()
|
||||
if(O)
|
||||
O.extinguish() //All shamelessly copied from water's reaction_obj, since I didn't seem to be able to get it here for some reason.
|
||||
O.acid_level = 0
|
||||
var/datum/component/acid/acid = O.GetComponent(/datum/component/acid)
|
||||
if(acid)
|
||||
acid.level = 0
|
||||
// Monkey cube
|
||||
if(istype(O, /obj/item/reagent_containers/food/snacks/cube))
|
||||
to_chat(owner, "<span class='warning'>[linked_extract] kept your hands wet! It makes [O] expand!</span>")
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
//caravan ambush
|
||||
|
||||
/obj/item/wrench/caravan
|
||||
color = "#ff0000"
|
||||
icon_state = "wrench_caravan"
|
||||
desc = "A prototype of a new wrench design, allegedly the red color scheme makes it go faster."
|
||||
name = "experimental wrench"
|
||||
toolspeed = 0.3
|
||||
|
||||
/obj/item/screwdriver/caravan
|
||||
color = "#ff0000"
|
||||
icon_state = "screwdriver_caravan"
|
||||
desc = "A prototype of a new screwdriver design, allegedly the red color scheme makes it go faster."
|
||||
name = "experimental screwdriver"
|
||||
toolspeed = 0.3
|
||||
random_color = FALSE
|
||||
|
||||
/obj/item/wirecutters/caravan
|
||||
color = "#ff0000"
|
||||
icon_state = "cutters_caravan"
|
||||
desc = "A prototype of a new wirecutter design, allegedly the red color scheme makes it go faster."
|
||||
name = "experimental wirecutters"
|
||||
toolspeed = 0.3
|
||||
random_color = FALSE
|
||||
|
||||
/obj/item/crowbar/red/caravan
|
||||
color = "#ff0000"
|
||||
icon_state = "crowbar_caravan"
|
||||
desc = "A prototype of a new crowbar design, allegedly the red color scheme makes it go faster."
|
||||
name = "experimental crowbar"
|
||||
toolspeed = 0.3
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* tgui state: vorepanel_state
|
||||
*
|
||||
* Only checks that the user and src_object are the same.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(ui_vorepanel_state, /datum/ui_state/vorepanel_state, new)
|
||||
|
||||
/datum/ui_state/vorepanel_state/can_use_topic(src_object, mob/user)
|
||||
if(src_object != user)
|
||||
// Note, in order to allow others to look at others vore panels, change this to
|
||||
// UI_UPDATE
|
||||
return UI_CLOSE
|
||||
if(!user.client)
|
||||
return UI_CLOSE
|
||||
if(user.stat == DEAD)
|
||||
return UI_DISABLED
|
||||
return UI_INTERACTIVE
|
||||
@@ -9,7 +9,7 @@
|
||||
* * buttons - The options that can be chosen by the user, each string is assigned a button on the UI.
|
||||
* * timeout - The timeout of the alert, after which the modal will close and qdel itself. Set to zero for no timeout.
|
||||
*/
|
||||
/proc/tgui_alert(mob/user, message, title, list/buttons, timeout = 60 SECONDS)
|
||||
/proc/tgui_alert(mob/user, message = null, title = null, list/buttons = list("Ok"), timeout = 0)
|
||||
if (!user)
|
||||
user = usr
|
||||
if (!istype(user))
|
||||
@@ -35,9 +35,9 @@
|
||||
* * title - The of the alert modal, shown on the top of the TGUI window.
|
||||
* * buttons - The options that can be chosen by the user, each string is assigned a button on the UI.
|
||||
* * callback - The callback to be invoked when a choice is made.
|
||||
* * timeout - The timeout of the alert, after which the modal will close and qdel itself. Set to zero for no timeout.
|
||||
* * timeout - The timeout of the alert, after which the modal will close and qdel itself. Disabled by default, can be set to seconds otherwise.
|
||||
*/
|
||||
/proc/tgui_alert_async(mob/user, message, title, list/buttons, datum/callback/callback, timeout = 60 SECONDS)
|
||||
/proc/tgui_alert_async(mob/user, message = null, title = null, list/buttons = list("Ok"), datum/callback/callback, timeout = 0)
|
||||
if (!user)
|
||||
user = usr
|
||||
if (!istype(user))
|
||||
@@ -90,7 +90,7 @@
|
||||
* the window was closed by the user.
|
||||
*/
|
||||
/datum/tgui_modal/proc/wait()
|
||||
while (!choice && !closed)
|
||||
while (!choice && !closed && !QDELETED(src))
|
||||
stoplag(1)
|
||||
|
||||
/datum/tgui_modal/ui_interact(mob/user, datum/tgui/ui)
|
||||
@@ -124,10 +124,13 @@
|
||||
if("choose")
|
||||
if (!(params["choice"] in buttons))
|
||||
return
|
||||
choice = params["choice"]
|
||||
set_choice(params["choice"])
|
||||
SStgui.close_uis(src)
|
||||
return TRUE
|
||||
|
||||
/datum/tgui_modal/proc/set_choice(choice)
|
||||
src.choice = choice
|
||||
|
||||
/**
|
||||
* # async tgui_modal
|
||||
*
|
||||
@@ -138,23 +141,17 @@
|
||||
var/datum/callback/callback
|
||||
|
||||
/datum/tgui_modal/async/New(mob/user, message, title, list/buttons, callback, timeout)
|
||||
..(user, title, message, buttons, timeout)
|
||||
..(user, message, title, buttons, timeout)
|
||||
src.callback = callback
|
||||
|
||||
/datum/tgui_modal/async/Destroy(force, ...)
|
||||
QDEL_NULL(callback)
|
||||
. = ..()
|
||||
|
||||
/datum/tgui_modal/async/ui_close(mob/user)
|
||||
/datum/tgui_modal/async/set_choice(choice)
|
||||
. = ..()
|
||||
qdel(src)
|
||||
|
||||
/datum/tgui_modal/async/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if (!. || choice == null)
|
||||
return
|
||||
callback.InvokeAsync(choice)
|
||||
qdel(src)
|
||||
if(!isnull(src.choice))
|
||||
callback?.InvokeAsync(src.choice)
|
||||
|
||||
/datum/tgui_modal/async/wait()
|
||||
return
|
||||
|
||||
@@ -138,12 +138,10 @@ Notes:
|
||||
. = ..()
|
||||
if(tooltips)
|
||||
if(!QDELETED(src))
|
||||
var/list/examine_list = examine(src)
|
||||
var/get_tooltip_data = get_tooltip_data()
|
||||
if(length(get_tooltip_data))
|
||||
examine_list = get_tooltip_data
|
||||
var/examine_data = examine_list.Join("<br />")
|
||||
openToolTip(usr, src, params, title = name, content = examine_data)
|
||||
var/list/tooltip_data = get_tooltip_data()
|
||||
if(length(tooltip_data))
|
||||
var/examine_data = tooltip_data.Join("<br />")
|
||||
openToolTip(usr, src, params, title = name, content = examine_data)
|
||||
|
||||
/atom/movable/MouseExited(location, control, params)
|
||||
. = ..()
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/obj/vehicle/ridden/wheelchair/motorized
|
||||
name = "Hoverchair"
|
||||
desc = "A chair with thrusters. It seems to have a motor in it."
|
||||
icon = 'icons/obj/vehicles.dmi'
|
||||
icon_state = "wheelchair_motorized"
|
||||
max_integrity = 150
|
||||
var/speed = 2
|
||||
var/power_efficiency = 1
|
||||
var/power_usage = 25
|
||||
var/panel_open = FALSE
|
||||
var/list/required_parts = list(/obj/item/stock_parts/manipulator,
|
||||
/obj/item/stock_parts/manipulator,
|
||||
/obj/item/stock_parts/capacitor)
|
||||
var/obj/item/stock_parts/cell/power_cell
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/motorized/CheckParts(list/parts_list)
|
||||
..()
|
||||
refresh_parts()
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/motorized/proc/refresh_parts()
|
||||
speed = 1 // Should never be under 1
|
||||
for(var/obj/item/stock_parts/manipulator/M in contents)
|
||||
speed += M.rating
|
||||
for(var/obj/item/stock_parts/capacitor/C in contents)
|
||||
power_efficiency = C.rating
|
||||
var/datum/component/riding/D = GetComponent(/datum/component/riding)
|
||||
D.vehicle_move_delay = round((CONFIG_GET(number/movedelay/run_delay) * 2) / speed, world.tick_lag)
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/motorized/obj_destruction(damage_flag)
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/atom/movable/A in contents)
|
||||
A.forceMove(T)
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
L.update_mobility()
|
||||
..()
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/motorized/driver_move(mob/living/user, direction)
|
||||
if(istype(user))
|
||||
if(!canmove)
|
||||
return FALSE
|
||||
if(!power_cell)
|
||||
to_chat(user, "<span class='warning'>There seems to be no cell installed in [src].</span>")
|
||||
canmove = FALSE
|
||||
addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
|
||||
return FALSE
|
||||
if(power_cell.charge < power_usage / max(power_efficiency, 1))
|
||||
to_chat(user, "<span class='warning'>The display on [src] blinks 'Out of Power'.</span>")
|
||||
canmove = FALSE
|
||||
addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
|
||||
return FALSE
|
||||
if(user.get_num_arms() < arms_required)
|
||||
to_chat(user, "<span class='warning'>You don't have enough arms to operate the motor controller!</span>")
|
||||
canmove = FALSE
|
||||
addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
|
||||
return FALSE
|
||||
power_cell.use(power_usage / max(power_efficiency, 1))
|
||||
return ..()
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/motorized/post_buckle_mob(mob/living/user)
|
||||
. = ..()
|
||||
density = TRUE
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/motorized/post_unbuckle_mob()
|
||||
. = ..()
|
||||
density = FALSE
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/motorized/attack_hand(mob/living/user)
|
||||
if(power_cell && panel_open)
|
||||
power_cell.update_icon()
|
||||
user.put_in_hands(power_cell)
|
||||
power_cell = null
|
||||
to_chat(user, "<span class='notice'>You remove the power cell from [src].</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/motorized/attackby(obj/item/I, mob/user, params)
|
||||
if(I.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
I.play_tool_sound(src)
|
||||
panel_open = !panel_open
|
||||
user.visible_message("<span class='notice'>[user] [panel_open ? "opens" : "closes"] the maintenance panel on [src].</span>", "<span class='notice'>You [panel_open ? "open" : "close"] the maintenance panel.</span>")
|
||||
return
|
||||
if(panel_open)
|
||||
if(istype(I, /obj/item/stock_parts/cell))
|
||||
if(power_cell)
|
||||
to_chat(user, "<span class='warning'>There is a power cell already installed.</span>")
|
||||
else
|
||||
I.forceMove(src)
|
||||
power_cell = I
|
||||
to_chat(user, "<span class='notice'>You install the [I].</span>")
|
||||
refresh_parts()
|
||||
return
|
||||
if(istype(I, /obj/item/stock_parts))
|
||||
var/obj/item/stock_parts/B = I
|
||||
var/P
|
||||
for(var/obj/item/stock_parts/A in contents)
|
||||
for(var/D in required_parts)
|
||||
if(ispath(A.type, D))
|
||||
P = D
|
||||
break
|
||||
if(istype(B, P) && istype(A, P))
|
||||
if(B.get_part_rating() > A.get_part_rating())
|
||||
B.forceMove(src)
|
||||
user.put_in_hands(A)
|
||||
user.visible_message("<span class='notice'>[user] replaces [A] with [B] in [src].</span>", "<span class='notice'>You replace [A] with [B].</span>")
|
||||
break
|
||||
refresh_parts()
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/motorized/wrench_act(mob/living/user, obj/item/I)
|
||||
to_chat(user, "<span class='notice'>You begin to detach the thrusters...</span>")
|
||||
if(I.use_tool(src, user, 40, volume=50))
|
||||
to_chat(user, "<span class='notice'>You detach the thrusters and deconstruct the chair.</span>")
|
||||
new /obj/item/stack/rods(drop_location(), 8)
|
||||
new /obj/item/stack/sheet/plasteel(drop_location(), 10)
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/atom/movable/A in contents)
|
||||
A.forceMove(T)
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
L.update_mobility()
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/motorized/examine(mob/user)
|
||||
. = ..()
|
||||
if(panel_open)
|
||||
. += "There is a small screen on it, [(in_range(user, src) || isobserver(user)) ? "[power_cell ? "it reads:" : "but it is dark."]" : "but you can't see it from here."]"
|
||||
if(!power_cell || (!in_range(user, src) && !isobserver(user)))
|
||||
return
|
||||
. += "Speed: [speed]"
|
||||
. += "Energy efficiency: [power_efficiency]"
|
||||
. += "Power: [power_cell.charge] out of [power_cell.maxcharge]"
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/motorized/Bump(atom/movable/M)
|
||||
. = ..()
|
||||
// If the speed is higher than delay_multiplier throw the person on the wheelchair away
|
||||
if(M.density && speed > 2 && has_buckled_mobs())
|
||||
var/mob/living/H = buckled_mobs[1]
|
||||
var/atom/throw_target = get_edge_target_turf(H, pick(GLOB.cardinals))
|
||||
unbuckle_mob(H)
|
||||
H.throw_at(throw_target, 2, 3)
|
||||
H.Knockdown(100)
|
||||
H.adjustStaminaLoss(40)
|
||||
if(isliving(M))
|
||||
var/mob/living/D = M
|
||||
throw_target = get_edge_target_turf(D, pick(GLOB.cardinals))
|
||||
D.throw_at(throw_target, 2, 3)
|
||||
D.Knockdown(80)
|
||||
D.adjustStaminaLoss(35)
|
||||
visible_message("<span class='danger'>[src] crashes into [M], sending [H] and [D] flying!</span>")
|
||||
else
|
||||
visible_message("<span class='danger'>[src] crashes into [M], sending [H] flying!</span>")
|
||||
playsound(src, 'sound/effects/bang.ogg', 50, 1)
|
||||
@@ -26,8 +26,8 @@
|
||||
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE, CALLBACK(src, .proc/can_user_rotate),CALLBACK(src, .proc/can_be_rotated),null)
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/obj_destruction(damage_flag)
|
||||
new /obj/item/stack/rods(drop_location(), 1)
|
||||
new /obj/item/stack/sheet/metal(drop_location(), 1)
|
||||
new /obj/item/stack/rods(drop_location(), 8)
|
||||
new /obj/item/stack/sheet/metal(drop_location(), 2)
|
||||
..()
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/Destroy()
|
||||
@@ -53,7 +53,10 @@
|
||||
/obj/vehicle/ridden/wheelchair/Moved()
|
||||
. = ..()
|
||||
cut_overlays()
|
||||
playsound(src, 'sound/effects/roll.ogg', 75, 1)
|
||||
if(istype(src, /obj/vehicle/ridden/wheelchair/motorized))
|
||||
playsound(src, 'sound/effects/chairwhoosh.ogg', 75, 1)
|
||||
else
|
||||
playsound(src, 'sound/effects/roll.ogg', 75, 1)
|
||||
if(has_buckled_mobs())
|
||||
handle_rotation_overlayed()
|
||||
|
||||
@@ -88,8 +91,12 @@
|
||||
|
||||
/obj/vehicle/ridden/wheelchair/proc/handle_rotation_overlayed()
|
||||
cut_overlays()
|
||||
var/image/V = image(icon = icon, icon_state = "wheelchair_overlay", layer = FLY_LAYER, dir = src.dir)
|
||||
add_overlay(V)
|
||||
if(istype(src, /obj/vehicle/ridden/wheelchair/motorized))
|
||||
var/image/V = image(icon = icon, icon_state = "wheelchair_noverlay", layer = FLY_LAYER, dir = src.dir)
|
||||
add_overlay(V)
|
||||
else
|
||||
var/image/V = image(icon = icon, icon_state = "wheelchair_overlay", layer = FLY_LAYER, dir = src.dir)
|
||||
add_overlay(V)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
SEND_SOUND(M,prey_digest)
|
||||
play_sound = pick(pred_digest)
|
||||
|
||||
if(M.vore_flags & ABSORBED)
|
||||
if(M.vore_flags & ABSORBED || !(M.vore_flags & ABSORBABLE)) //Negative.
|
||||
continue
|
||||
|
||||
if(M.nutrition >= 100) //Drain them until there's no nutrients left. Slowly "absorb" them.
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
///////////////////// Mob Living /////////////////////
|
||||
/mob/living
|
||||
var/vore_flags = 0
|
||||
var/showvoreprefs = TRUE // Determines if the mechanical vore preferences button will be displayed on the mob or not.
|
||||
var/obj/belly/vore_selected // Default to no vore capability.
|
||||
var/list/vore_organs = list() // List of vore containers inside a mob
|
||||
var/vore_taste = null // What the character tastes like
|
||||
// Determines if the mechanical vore preferences button will be displayed on the mob or not.
|
||||
var/showvoreprefs = TRUE
|
||||
/// Default to no vore capability.
|
||||
var/obj/belly/vore_selected
|
||||
/// List of vore containers inside a mob
|
||||
var/list/vore_organs = list()
|
||||
/// What the character tastes like
|
||||
var/vore_taste = null
|
||||
/// What the character smells like
|
||||
var/vore_smell = null
|
||||
/// Next time vore sounds get played for the prey, do not change manually as it is intended to be set automatically
|
||||
var/next_preyloop
|
||||
|
||||
//
|
||||
// Hook for generic creation of stuff on new creatures
|
||||
//
|
||||
/hook/living_new/proc/vore_setup(mob/living/M)
|
||||
add_verb(M, list(/mob/living/proc/preyloop_refresh, /mob/living/proc/lick, /mob/living/proc/escapeOOC))
|
||||
add_verb(M, list(/mob/living/proc/preyloop_refresh, /mob/living/proc/lick, /mob/living/proc/smell, /mob/living/proc/escapeOOC))
|
||||
|
||||
if(M.vore_flags & NO_VORE) //If the mob isn't supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach.
|
||||
return TRUE
|
||||
@@ -59,13 +66,14 @@
|
||||
// Critical adjustments due to TG grab changes - Poojawa
|
||||
|
||||
/mob/living/proc/vore_attack(var/mob/living/user, var/mob/living/prey, var/mob/living/pred)
|
||||
lazy_init_belly()
|
||||
set waitfor = FALSE
|
||||
if(!user || !prey || !pred)
|
||||
return
|
||||
|
||||
if(!isliving(pred)) //no badmin, you can't feed people to ghosts or objects.
|
||||
return
|
||||
|
||||
lazy_init_belly()
|
||||
if(pred == prey) //you click your target
|
||||
if(!CHECK_BITFIELD(pred.vore_flags,FEEDING))
|
||||
to_chat(user, "<span class='notice'>They aren't able to be fed.</span>")
|
||||
@@ -255,6 +263,7 @@
|
||||
|
||||
client.prefs.vore_flags = vore_flags // there's garbage data in here, but it doesn't matter
|
||||
client.prefs.vore_taste = vore_taste
|
||||
client.prefs.vore_smell = vore_smell
|
||||
|
||||
var/list/serialized = list()
|
||||
for(var/belly in vore_organs)
|
||||
@@ -263,6 +272,8 @@
|
||||
|
||||
client.prefs.belly_prefs = serialized
|
||||
|
||||
client.prefs.save_character()
|
||||
|
||||
return TRUE
|
||||
|
||||
//
|
||||
@@ -273,8 +284,9 @@
|
||||
to_chat(src,"<span class='warning'>You attempted to apply your vore prefs but somehow you're in this character without a client.prefs variable. Tell a dev.</span>")
|
||||
return FALSE
|
||||
ENABLE_BITFIELD(vore_flags,VOREPREF_INIT)
|
||||
COPY_SPECIFIC_BITFIELDS(vore_flags,client.prefs.vore_flags,DIGESTABLE | DEVOURABLE | FEEDING | LICKABLE)
|
||||
COPY_SPECIFIC_BITFIELDS(vore_flags, client.prefs.vore_flags, DIGESTABLE | DEVOURABLE | FEEDING | LICKABLE | SMELLABLE | ABSORBABLE | MOBVORE)
|
||||
vore_taste = client.prefs.vore_taste
|
||||
vore_smell = client.prefs.vore_smell
|
||||
|
||||
release_vore_contents(silent = TRUE)
|
||||
QDEL_LIST(vore_organs)
|
||||
@@ -378,6 +390,56 @@
|
||||
else
|
||||
taste_message += "a plain old normal [src]"
|
||||
return taste_message
|
||||
|
||||
//
|
||||
// Equally important as the above
|
||||
//
|
||||
/mob/living/proc/smell()
|
||||
set name = "Smell Someone"
|
||||
set category = "Vore"
|
||||
set desc = "Smell someone nearby!"
|
||||
|
||||
if(incapacitated(ignore_restraints = TRUE))
|
||||
to_chat(src, "<span class='warning'>You can't do that while incapacitated.</span>")
|
||||
return
|
||||
if(!CheckActionCooldown())
|
||||
to_chat(src, "<span class='warning'>You can't do that so fast, slow down.</span>")
|
||||
return
|
||||
|
||||
DelayNextAction(CLICK_CD_MELEE, flush = TRUE)
|
||||
|
||||
var/list/smellable = list()
|
||||
for(var/mob/living/L in view(1))
|
||||
if(L != src && (!L.ckey || L.client?.prefs.vore_flags & SMELLABLE) && Adjacent(L))
|
||||
LAZYADD(smellable, L)
|
||||
for(var/mob/living/listed in smellable)
|
||||
smellable[listed] = new /mutable_appearance(listed)
|
||||
|
||||
if(!smellable)
|
||||
return
|
||||
|
||||
var/mob/living/sniffed = show_radial_menu(src, src, smellable, radius = 40, require_near = TRUE)
|
||||
|
||||
if(QDELETED(sniffed) || (sniffed.ckey && !(sniffed.client?.prefs.vore_flags & SMELLABLE)) || !Adjacent(sniffed) || incapacitated(ignore_restraints = TRUE))
|
||||
return
|
||||
|
||||
visible_message("<span class='warning'>[src] smells [sniffed]!</span>","<span class='notice'>You smell [sniffed]. They smell like [sniffed.get_smell_message()].</span>","<b>Sniff!</b>")
|
||||
|
||||
/mob/living/proc/get_smell_message(allow_generic = TRUE, datum/species/mrace)
|
||||
if(!vore_smell && !allow_generic)
|
||||
return FALSE
|
||||
|
||||
var/smell_message = ""
|
||||
if(vore_smell && (vore_smell != ""))
|
||||
smell_message += "[vore_smell]"
|
||||
else
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/H = src
|
||||
smell_message += "a normal [H.custom_species ? H.custom_species : H.dna.species]"
|
||||
else
|
||||
smell_message += "a plain old normal [src]"
|
||||
return smell_message
|
||||
|
||||
// Check if an object is capable of eating things, based on vore_organs
|
||||
//
|
||||
/proc/has_vore_belly(var/mob/living/O)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -45,7 +45,7 @@
|
||||
if(!owner)
|
||||
return
|
||||
if(!(src in owner.internal_organs))
|
||||
Remove(owner)
|
||||
INVOKE_ASYNC(src,.proc/Remove,owner)
|
||||
if(owner.mob_biotypes & MOB_MINERAL)//does not process in inorganic things
|
||||
return
|
||||
if (causes_damage && !iszombie(owner) && owner.stat != DEAD)
|
||||
|
||||
Reference in New Issue
Block a user