diff --git a/_maps/shuttles/emergency_narnar.dmm b/_maps/shuttles/emergency_narnar.dmm index 84973d621d3..3295aee638a 100644 --- a/_maps/shuttles/emergency_narnar.dmm +++ b/_maps/shuttles/emergency_narnar.dmm @@ -181,6 +181,10 @@ /area/shuttle/escape) "I" = ( /obj/effect/rune/narsie, +/obj/effect/fun_balloon/sentience/emergency_shuttle{ + effect_range = 5; + group_name = "horrible monsters on Shuttle 667" + }, /turf/open/floor/plasteel/cult, /area/shuttle/escape) "J" = ( diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index 12c96a5643a..5b93b43d669 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -17,7 +17,7 @@ /obj/effect/overlay/beam/New() ..() - spawn(10) qdel(src) + QDEL_IN(src, 10) /obj/effect/overlay/temp icon_state = "nothing" @@ -35,8 +35,7 @@ if(randomdir) setDir(pick(cardinal)) flick("[icon_state]", src) //Because we might be pulling it from a pool, flick whatever icon it uses so it starts at the start of the icon's animation. - spawn(duration) - qdel(src) + QDEL_IN(src, duration) /obj/effect/overlay/temp/bloodsplatter icon = 'icons/effects/blood.dmi' @@ -273,8 +272,8 @@ duration = 15 /obj/effect/overlay/temp/gib_animation/New(loc, gib_icon) - icon_state = gib_icon ..() + icon_state = gib_icon /obj/effect/overlay/temp/gib_animation/ex_act(severity) return //so the overlay isn't deleted by the explosion that gibbed the mob. @@ -287,8 +286,28 @@ duration = 15 /obj/effect/overlay/temp/dust_animation/New(loc, dust_icon) - icon_state = dust_icon ..() + icon_state = dust_icon + +/obj/effect/overlay/temp/sparkle + icon = 'icons/effects/effects.dmi' + icon_state = "shieldsparkles" + mouse_opacity = 0 + density = 0 + duration = 10 + var/atom/movable/attached_to + +/obj/effect/overlay/temp/sparkle/New(atom/movable/AM) + ..() + attached_to = AM + attached_to.overlays += src + +/obj/effect/overlay/temp/sparkle/Destroy() + attached_to.overlays -= src + . = ..() + +/obj/effect/overlay/temp/sparkle/tailsweep + icon_state = "tailsweep" /obj/effect/overlay/palmtree_r name = "Palm tree" @@ -309,4 +328,4 @@ /obj/effect/overlay/coconut name = "Coconuts" icon = 'icons/misc/beach.dmi' - icon_state = "coconuts" \ No newline at end of file + icon_state = "coconuts" diff --git a/code/modules/admin/fun_balloon.dm b/code/modules/admin/fun_balloon.dm new file mode 100644 index 00000000000..64d0a762731 --- /dev/null +++ b/code/modules/admin/fun_balloon.dm @@ -0,0 +1,85 @@ +/obj/effect/fun_balloon + name = "fun balloon" + desc = "This is going to be a laugh riot." + icon = 'icons/obj/weapons.dmi' + icon_state = "syndballoon" + anchored = TRUE + var/popped = FALSE + +/obj/effect/fun_balloon/New() + . = ..() + SSobj.processing |= src + +/obj/effect/fun_balloon/Destroy() + SSobj.processing -= src + . = ..() + +/obj/effect/fun_balloon/process() + if(!popped && check() && !qdeleted(src)) + popped = TRUE + effect() + pop() + +/obj/effect/fun_balloon/proc/check() + return FALSE + +/obj/effect/fun_balloon/proc/effect() + return + +/obj/effect/fun_balloon/proc/pop() + visible_message("[src] pops!") + playsound(get_turf(src), 'sound/items/party_horn.ogg', 50, 1, -1) + qdel(src) + +/obj/effect/fun_balloon/attack_ghost(mob/user) + if(!user.client || !user.client.holder || popped) + return + switch(alert("Pop [src]?","Fun Balloon","Yes","No")) + if("Yes") + effect() + pop() + +/obj/effect/fun_balloon/sentience + name = "sentience fun balloon" + desc = "When this pops, things are gonna get more aware around here." + var/effect_range = 3 + var/group_name = "a bunch of giant spiders" + +/obj/effect/fun_balloon/sentience/effect() + var/list/bodies = list() + for(var/mob/living/M in range(effect_range, get_turf(src))) + bodies += M + + var/question = "Would you like to be [group_name]?" + var/list/candidates = pollCandidates(question, "pAI", null, FALSE, 100) + while(candidates.len && bodies.len) + var/mob/dead/observer/ghost = pick_n_take(candidates) + var/mob/living/body = pick_n_take(bodies) + + body << "Your mob has been taken over by a ghost!" + message_admins("[key_name_admin(ghost)] has taken control \ + of ([key_name_admin(body)])") + body.ghostize(0) + body.key = ghost.key + PoolOrNew(/obj/effect/overlay/temp/sparkle, body) + +/obj/effect/fun_balloon/sentience/emergency_shuttle + name = "shuttle sentience fun balloon" + var/trigger_time = 60 + +/obj/effect/fun_balloon/sentience/emergency_shuttle/check() + . = FALSE + if(SSshuttle.emergency && (SSshuttle.emergency.timeLeft() <= trigger_time) && (SSshuttle.emergency.mode == SHUTTLE_CALL)) + . = TRUE + +/obj/effect/fun_balloon/scatter + name = "scatter fun balloon" + desc = "When this pops, you're not going to be around here anymore." + var/effect_range = 5 + +/obj/effect/fun_balloon/scatter/effect() + for(var/mob/living/M in range(effect_range, get_turf(src))) + var/turf/T = find_safe_turf() + PoolOrNew(/obj/effect/overlay/temp/sparkle, M) + M.forceMove(T) + M << "Pop!" diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm index ef5c7d5ad19..979c3c60f94 100644 --- a/code/modules/spells/spell_types/wizard.dm +++ b/code/modules/spells/spell_types/wizard.dm @@ -298,7 +298,7 @@ selection_type = "view" sound = 'sound/magic/Repulse.ogg' var/maxthrow = 5 - var/animation = "shieldsparkles" + var/sparkle_path = /obj/effect/overlay/sparkle action_icon_state = "repulse" @@ -314,12 +314,10 @@ for(var/atom/movable/AM in thrownatoms) if(AM == user || AM.anchored) continue - var/obj/effect/overlay/targeteffect = new /obj/effect/overlay{icon='icons/effects/effects.dmi'; icon_state="shieldsparkles"; mouse_opacity=0; density = 0}() - targeteffect.icon_state = animation - AM.add_overlay(targeteffect) + // created sparkles will disappear on their own + PoolOrNew(sparkle_path, AM) throwtarget = get_edge_target_turf(user, get_dir(user, get_step_away(AM, user))) distfromcaster = get_dist(user, AM) - addtimer(src, "remove_sparkles", 10, FALSE, AM, targeteffect) if(distfromcaster == 0) if(istype(AM, /mob/living)) var/mob/living/M = AM @@ -333,10 +331,6 @@ M << "You're thrown back by [user]!" AM.throw_at_fast(throwtarget, ((Clamp((maxthrow - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time. -/obj/effect/proc_holder/spell/aoe_turf/repulse/proc/remove_sparkles(atom/movable/AM, obj/effect/overlay/targeteffect) - AM.overlays -= targeteffect - qdel(targeteffect) - /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno //i fixed conflicts only to find out that this is in the WIZARD file instead of the xeno file?! name = "Tail Sweep" desc = "Throw back attackers with a sweep of your tail." @@ -346,7 +340,7 @@ range = 2 cooldown_min = 150 invocation_type = "none" - animation = "tailsweep" + sparkle_path = /obj/effect/overlay/sparkle/tailsweep action_icon_state = "tailsweep" action_background_icon_state = "bg_alien" diff --git a/sound/items/party_horn.ogg b/sound/items/party_horn.ogg new file mode 100644 index 00000000000..ffdd49b1e72 Binary files /dev/null and b/sound/items/party_horn.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 32d0712ff07..8aa2f8dae4e 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -837,6 +837,7 @@ #include "code\modules\admin\create_object.dm" #include "code\modules\admin\create_poll.dm" #include "code\modules\admin\create_turf.dm" +#include "code\modules\admin\fun_balloon.dm" #include "code\modules\admin\holder2.dm" #include "code\modules\admin\ipintel.dm" #include "code\modules\admin\IsBanned.dm"