Merge remote-tracking branch 'citadel/master' into combat_patches_1

This commit is contained in:
silicons
2021-07-18 15:12:52 -07:00
159 changed files with 132112 additions and 130447 deletions
@@ -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))
@@ -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()
-1
View File
@@ -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)
+1
View File
@@ -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>")
+1
View File
@@ -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
+5
View File
@@ -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))
+6
View File
@@ -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"
+1 -1
View File
@@ -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()
+4 -1
View File
@@ -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.")
+1 -2
View File
@@ -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)
+6 -2
View File
@@ -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"
+1
View File
@@ -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
+1 -1
View File
@@ -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
+6 -2
View File
@@ -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
+18 -15
View File
@@ -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)
+1
View File
@@ -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),
+3 -2
View File
@@ -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
+11
View File
@@ -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
+11 -3
View File
@@ -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)
+13
View File
@@ -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))
+1
View File
@@ -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()
. = ..()
+1 -1
View File
@@ -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
+8 -5
View File
@@ -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
+18
View File
@@ -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
+12 -15
View File
@@ -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
+4 -6
View File
@@ -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)
+12 -5
View File
@@ -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)
+1 -1
View File
@@ -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.
+69 -7
View File
@@ -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
+1 -1
View File
@@ -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)