diff --git a/code/game/machinery/quantum_pad.dm b/code/game/machinery/quantum_pad.dm index 4ba387850ed..011681a99bb 100644 --- a/code/game/machinery/quantum_pad.dm +++ b/code/game/machinery/quantum_pad.dm @@ -137,53 +137,51 @@ ghost.forceMove(get_turf(linked_pad)) /obj/machinery/quantumpad/proc/doteleport(mob/user = null, obj/machinery/quantumpad/target_pad = linked_pad) - if(target_pad) - playsound(get_turf(src), 'sound/weapons/flash.ogg', 25, TRUE) - teleporting = TRUE + if(!target_pad) + return + playsound(get_turf(src), 'sound/weapons/flash.ogg', 25, TRUE) + teleporting = TRUE - spawn(teleport_speed) - if(!src || QDELETED(src)) - teleporting = FALSE - return - if(machine_stat & NOPOWER) - if(user) - to_chat(user, span_warning("[src] is unpowered!")) - teleporting = FALSE - return - if(!target_pad || QDELETED(target_pad) || target_pad.machine_stat & NOPOWER) - if(user) - to_chat(user, span_warning("Linked pad is not responding to ping. Teleport aborted.")) - teleporting = FALSE - return + addtimer(CALLBACK(src, .proc/teleport_contents, user, target_pad), teleport_speed) - teleporting = FALSE - last_teleport = world.time +/obj/machinery/quantumpad/proc/teleport_contents(mob/user, obj/machinery/quantumpad/target_pad) + teleporting = FALSE + if(machine_stat & NOPOWER) + if(user) + to_chat(user, span_warning("[src] is unpowered!")) + return + if(QDELETED(target_pad) || target_pad.machine_stat & NOPOWER) + if(user) + to_chat(user, span_warning("Linked pad is not responding to ping. Teleport aborted.")) + return - // use a lot of power - use_power(10000 / power_efficiency) - sparks() - target_pad.sparks() + last_teleport = world.time - flick("qpad-beam", src) - playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 25, TRUE) - flick("qpad-beam", target_pad) - playsound(get_turf(target_pad), 'sound/weapons/emitter2.ogg', 25, TRUE) - for(var/atom/movable/ROI in get_turf(src)) - if(QDELETED(ROI)) - continue //sleeps in CHECK_TICK + // use a lot of power + use_power(10000 / power_efficiency) + sparks() + target_pad.sparks() - // if is anchored, don't let through - if(ROI.anchored) - continue + flick("qpad-beam", src) + playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 25, TRUE) + flick("qpad-beam", target_pad) + playsound(get_turf(target_pad), 'sound/weapons/emitter2.ogg', 25, TRUE) + for(var/atom/movable/ROI in get_turf(src)) + if(QDELETED(ROI)) + continue //sleeps in CHECK_TICK - if(isliving(ROI)) - var/mob/living/living_subject = ROI - //only TP living mobs buckled to non anchored items - if(living_subject.buckled && living_subject.buckled.anchored) - continue + // if is anchored, don't let through + if(ROI.anchored) + continue - do_teleport(ROI, get_turf(target_pad), no_effects = TRUE, channel = TELEPORT_CHANNEL_QUANTUM) - CHECK_TICK + if(isliving(ROI)) + var/mob/living/living_subject = ROI + //only TP living mobs buckled to non anchored items + if(living_subject.buckled && living_subject.buckled.anchored) + continue + + do_teleport(ROI, get_turf(target_pad), no_effects = TRUE, channel = TELEPORT_CHANNEL_QUANTUM) + CHECK_TICK /obj/machinery/quantumpad/proc/initMappedLink() . = FALSE diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm index 3fb71484f58..51d536cbc2e 100644 --- a/code/game/objects/items/devices/camera_bug.dm +++ b/code/game/objects/items/devices/camera_bug.dm @@ -259,19 +259,21 @@ to_chat(usr, span_warning("Something's wrong with that camera! You can't get a feed.")) return current = camera - spawn(6) - if(src.check_eye(usr)) - usr.reset_perspective(camera) - interact() - else - usr.unset_machine() - usr << browse(null, "window=camerabug") + addtimer(CALLBACK(src, .proc/view_camera, usr, camera), 0.6 SECONDS) return else usr.unset_machine() interact() +/obj/item/camera_bug/proc/view_camera(mob/show, obj/machinery/camera/camera) + if(check_eye(show)) + show.reset_perspective(camera) + interact() + else + show.unset_machine() + show << browse(null, "window=camerabug") + /obj/item/camera_bug/process() if(track_mode == BUGMODE_LIST || (world.time < (last_tracked + refresh_interval))) return diff --git a/code/modules/chatter/chatter.dm b/code/modules/chatter/chatter.dm index 669b282192d..c6be322429f 100644 --- a/code/modules/chatter/chatter.dm +++ b/code/modules/chatter/chatter.dm @@ -1,4 +1,4 @@ -/proc/chatter(message, phomeme, atom/A) +/proc/chatter(message, phomeme, atom/speaker) // We want to transform any message into a list of numbers // and punctuation marks // For example: @@ -7,7 +7,6 @@ // -> [4, 6, 7, ',', 4, 5, ',', '2', 7, 2, '!'] // "fuck,thissentenceissquashed" -> [4, ',', 21] - var/list/punctuation = list(",",":",";",".","?","!","\'","-") var/regex/R = regex("(\[\\l\\d]*)(\[^\\l\\d\\s])?", "g") var/list/letter_count = list() while(R.Find(message) != 0) @@ -15,42 +14,58 @@ letter_count += length(R.group[1]) if(R.group[2]) letter_count += R.group[2] + chatter_speak(speaker, letter_count, phomeme) - spawn(0) - for(var/item in letter_count) - if (item in punctuation) - // simulate pausing in talking - // ignore semi-colons because of their use in HTML escaping - if (item in list(",", ":")) - sleep(3) - if (item in list("!", "?", ".")) - sleep(6) - continue +/// We're going to take a list that dictates the pace of speech, and a sentence fragment to say +/// Then say() that fragment at that pace +/// You can pass in a starting delay to wait before speaking the next sound +/proc/chatter_speak(atom/speaker, list/letter_count, phomeme, extra_delay = 0) + var/static/list/punctuation = list(",",":",";",".","?","!","\'","-") + var/delay = extra_delay + for(var/i in 1 to length(letter_count)) + var/item = letter_count[i] + if (item in punctuation) + // simulate pausing in talking + // ignore semi-colons because of their use in HTML escaping + if (item in list(",", ":")) + delay += 0.3 SECONDS + if (item in list("!", "?", ".")) + delay += 0.6 SECONDS + continue - if(isnum(item)) - var/length = min(item, 10) - if (length == 0) - // "verbalise" long spaces - sleep(1) - chatter_speak_word(A.loc, phomeme, length) + if(!isnum(item)) + continue + letter_count.Cut(1, i + 1) + var/list/current_context = letter_count -/proc/chatter_speak_word(loc, phomeme, length) + var/length = min(item, 10) + if (length == 0) + // "verbalise" long spaces + delay += 0.1 SECONDS + + if(delay) + addtimer(CALLBACK(GLOBAL_PROC, /proc/chatter_speak_word, speaker, letter_count, phomeme, length), delay, flags = TIMER_CLIENT_TIME) + else + chatter_speak_word(speaker, current_context, phomeme, length) + break //We use the loop as a handy way of dealing with punctuation, the actual looping operation here happens in timers that call timers + +/proc/chatter_speak_word(atom/speaker, list/letter_count, phomeme, length) var/path = "sound/runtime/chatter/[phomeme]_[length].ogg" - + var/loc = speaker.loc playsound(loc, path, vol = 40, vary = 0, extrarange = 3) - sleep((length + 1) * chatter_get_sleep_multiplier(phomeme)) + var/delay = (length + 1) * chatter_get_delay_multiplier(phomeme) + chatter_speak(speaker, letter_count, phomeme, delay) -/proc/chatter_get_sleep_multiplier(phomeme) - // These values are tenths of seconds, so 0.5 == 0.05seconds - . = 1 +/proc/chatter_get_delay_multiplier(phomeme) + . = 0.1 SECONDS switch(phomeme) if("papyrus") - . = 0.5 + . = 0.05 SECONDS if("griffin") - . = 0.5 + . = 0.05 SECONDS if("sans") - . = 0.7 + . = 0.07 SECONDS if("owl") - . = 0.7 + . = 0.07 SECONDS diff --git a/code/modules/mob/dead/observer/logout.dm b/code/modules/mob/dead/observer/logout.dm index 89acca32f3a..4ba701c0ae0 100644 --- a/code/modules/mob/dead/observer/logout.dm +++ b/code/modules/mob/dead/observer/logout.dm @@ -6,6 +6,10 @@ if(observetarget && ismob(observetarget)) cleanup_observe() ..() + // This is one of very few spawn()s left in our codebase + // Yes it needs to be like this + // No, you're not allowed to use spawn() yourself, unless you're making something that needs to work outside timers + // Don't be a dumbass, I will always be watching spawn(0) if(src && !key) //we've transferred to another mob. This ghost should be deleted. qdel(src) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 7ef8340b9fb..8f9fa8f0b00 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -429,38 +429,37 @@ All effects don't start immediately, but rather get worse over time; the rate is //Dizziness if(dizziness) - var/client/C = client - var/pixel_x_diff = 0 - var/pixel_y_diff = 0 - var/temp - var/saved_dizz = dizziness - if(C) - var/oldsrc = src - var/amplitude = dizziness*(sin(dizziness * world.time) + 1) // This shit is annoying at high strength - src = null - spawn(0) // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - if(C) - temp = amplitude * sin(saved_dizz * world.time) - pixel_x_diff += temp - C.pixel_x += temp - temp = amplitude * cos(saved_dizz * world.time) - pixel_y_diff += temp - C.pixel_y += temp - sleep(3) - if(C) - temp = amplitude * sin(saved_dizz * world.time) - pixel_x_diff += temp - C.pixel_x += temp - temp = amplitude * cos(saved_dizz * world.time) - pixel_y_diff += temp - C.pixel_y += temp - sleep(3) - if(C) - C.pixel_x -= pixel_x_diff - C.pixel_y -= pixel_y_diff - src = oldsrc + var/old_dizzy = dizziness dizziness = max(dizziness - (restingpwr * delta_time), 0) + if(client) + //Want to be able to offset things by the time the animation should be "playing" at + var/time = world.time + var/delay = 0 + var/pixel_x_diff = 0 + var/pixel_y_diff = 0 + + var/amplitude = old_dizzy*(sin(old_dizzy * (time)) + 1) // This shit is annoying at high strengthvar/pixel_x_diff = 0 + var/x_diff = amplitude * sin(old_dizzy * time) + var/y_diff = amplitude * cos(old_dizzy * time) + pixel_x_diff += x_diff + pixel_y_diff += y_diff + // Brief explanation. We're basically snapping between different pixel_x/ys instantly, with delays between + // Doing this with relative changes. This way we don't override any existing pixel_x/y values + // We use EASE_OUT here for similar reasons, we want to act at the end of the delay, not at its start + // Relative animations are weird, so we do actually need this + animate(client, pixel_x = x_diff, pixel_y = y_diff, 3, easing = JUMP_EASING | EASE_OUT, flags = ANIMATION_RELATIVE) + delay += 0.3 SECONDS // This counts as a 0.3 second wait, so we need to shift the sine wave by that much + + x_diff = amplitude * sin(dizziness * (time + delay)) + y_diff = amplitude * cos(dizziness * (time + delay)) + pixel_x_diff += x_diff + pixel_y_diff += y_diff + animate(pixel_x = x_diff, pixel_y = y_diff, 3, easing = JUMP_EASING | EASE_OUT, flags = ANIMATION_RELATIVE) + + // Now we reset back to our old pixel_x/y, since these animates are relative + animate(pixel_x = -pixel_x_diff, pixel_y = -pixel_y_diff, 3, easing = JUMP_EASING | EASE_OUT, flags = ANIMATION_RELATIVE) + if(drowsyness) adjust_drowsyness(-1 * restingpwr * delta_time) blur_eyes(1 * delta_time)