THE POSSESSENING

This commit is contained in:
SamCroswell
2016-05-21 01:44:25 -04:00
parent d9aef9034c
commit 6bae6337fb
5 changed files with 386 additions and 23 deletions

View File

@@ -0,0 +1,203 @@
/*
* A file intended to store various animation procs for re-use.
* A fair majority of these are copy-pasted from Goon and may not function as expected without tweaking.
* The spin from being thrown will interrupt most of these animations as will grabs, account for that accordingly.
*/
/proc/animate_fade_grayscale(var/atom/A, var/time=5)
if (!istype(A) && !istype(A, /client))
return
A.color = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1)
animate(A, color=list(0.33, 0.33, 0.33, 0, 0.33, 0.33, 0.33, 0, 0.33, 0.33, 0.33, 0, 0, 0, 0, 1), time=time, easing=SINE_EASING)
return
/proc/animate_melt_pixel(var/atom/A)
if (!istype(A))
return
//A.alpha = 200
animate(A, pixel_y = 0, time = 50 - A.pixel_y, alpha = 175, easing = BOUNCE_EASING)
animate(alpha = 0, easing = LINEAR_EASING)
return
/proc/animate_explode_pixel(var/atom/A)
if (!istype(A))
return
var/floatdegrees = rand(5, 20)
var/side = 1
side = pick(-1, 1)
animate(A, pixel_x = rand(-64, 64), pixel_y = rand(-64, 64), transform = matrix(floatdegrees * (side == 1 ? 1:-1), MATRIX_ROTATE), time = 10, alpha = 0, easing = SINE_EASING)
return
/proc/animate_float(var/atom/A, var/loopnum = -1, floatspeed = 20, random_side = 1)
if (!istype(A))
return
var/floatdegrees = rand(5, 20)
var/side = 1
if(random_side) side = pick(-1, 1)
spawn(rand(1,10))
animate(A, pixel_y = 32, transform = matrix(floatdegrees * (side == 1 ? 1:-1), MATRIX_ROTATE), time = floatspeed, loop = loopnum, easing = SINE_EASING)
animate(pixel_y = 0, transform = matrix(floatdegrees * (side == 1 ? -1:1), MATRIX_ROTATE), time = floatspeed, loop = loopnum, easing = SINE_EASING)
return
/proc/animate_levitate(var/atom/A, var/loopnum = -1, floatspeed = 20, random_side = 1)
if (!istype(A))
return
var/floatdegrees = rand(5, 20)
var/side = 1
if(random_side) side = pick(-1, 1)
spawn(rand(1,10))
animate(A, pixel_y = 8, transform = matrix(floatdegrees * (side == 1 ? 1:-1), MATRIX_ROTATE), time = floatspeed, loop = loopnum, easing = SINE_EASING)
animate(pixel_y = 0, transform = null, time = floatspeed, loop = loopnum, easing = SINE_EASING)
return
/proc/animate_ghostly_presence(var/atom/A, var/loopnum = -1, floatspeed = 20, random_side = 1)
if (!istype(A))
return
var/floatdegrees = rand(5, 20)
var/side = 1
if(random_side) side = pick(-1, 1)
spawn(rand(1,10))
animate(A, pixel_y = 8, transform = matrix(floatdegrees * (side == 1 ? 1:-1), MATRIX_ROTATE), time = floatspeed, loop = loopnum, easing = SINE_EASING)
animate(pixel_y = 0, transform = matrix(floatdegrees * (side == 1 ? -1:1), MATRIX_ROTATE), time = floatspeed, loop = loopnum, easing = SINE_EASING)
return
/proc/animate_fading_leap_up(var/atom/A)
if (!istype(A))
return
var/matrix/M = matrix()
var/do_loops = 15
while (do_loops > 0)
do_loops--
animate(A, transform = M, pixel_z = A.pixel_z + 12, alpha = A.alpha - 17, time = 1, loop = 1, easing = LINEAR_EASING)
M.Scale(1.2,1.2)
sleep(1)
A.alpha = 0
/proc/animate_fading_leap_down(var/atom/A)
if (!istype(A))
return
var/matrix/M = matrix()
var/do_loops = 15
M.Scale(18,18)
while (do_loops > 0)
do_loops--
animate(A, transform = M, pixel_z = A.pixel_z - 12, alpha = A.alpha + 17, time = 1, loop = 1, easing = LINEAR_EASING)
M.Scale(0.8,0.8)
sleep(1)
animate(A, transform = M, pixel_z = 0, alpha = 255, time = 1, loop = 1, easing = LINEAR_EASING)
/proc/animate_shake(var/atom/A,var/amount = 5,var/x_severity = 2,var/y_severity = 2)
// Wiggles the sprite around on its tile then returns it to normal
if (!istype(A))
return
if (!isnum(amount) || !isnum(x_severity) || !isnum(y_severity))
return
amount = max(1,min(amount,50))
x_severity = max(-32,min(x_severity,32))
y_severity = max(-32,min(y_severity,32))
var/x_severity_inverse = 0 - x_severity
var/y_severity_inverse = 0 - y_severity
animate(A, transform = null, pixel_y = rand(y_severity_inverse,y_severity), pixel_x = rand(x_severity_inverse,x_severity),time = 1,loop = amount, easing = ELASTIC_EASING)
spawn(amount)
animate(A, transform = null, pixel_y = 0, pixel_x = 0,time = 1,loop = 1, easing = LINEAR_EASING)
return
/proc/animate_teleport(var/atom/A)
if (!istype(A))
return
var/matrix/M = matrix(1, 3, MATRIX_SCALE)
animate(A, transform = M, pixel_y = 32, time = 10, alpha = 50, easing = CIRCULAR_EASING)
M.Scale(0,4)
animate(transform = M, time = 5, color = "#1111ff", alpha = 0, easing = CIRCULAR_EASING)
animate(transform = null, time = 5, color = "#ffffff", alpha = 255, pixel_y = 0, easing = ELASTIC_EASING)
return
/proc/animate_teleport_wiz(var/atom/A)
if (!istype(A))
return
var/matrix/M = matrix(0, 4, MATRIX_SCALE)
animate(A, color = "#ddddff", time = 20, alpha = 70, easing = LINEAR_EASING)
animate(transform = M, pixel_y = 32, time = 20, color = "#2222ff", alpha = 0, easing = CIRCULAR_EASING)
animate(time = 8, transform = M, alpha = 5) //Do nothing, essentially
animate(transform = null, time = 5, color = "#ffffff", alpha = 255, pixel_y = 0, easing = ELASTIC_EASING)
return
/proc/animate_rainbow_glow_old(var/atom/A)
if (!istype(A))
return
animate(A, color = "#FF0000", time = rand(5,10), loop = -1, easing = LINEAR_EASING)
animate(color = "#00FF00", time = rand(5,10), loop = -1, easing = LINEAR_EASING)
animate(color = "#0000FF", time = rand(5,10), loop = -1, easing = LINEAR_EASING)
return
/proc/animate_rainbow_glow(var/atom/A)
if (!istype(A))
return
animate(A, color = "#FF0000", time = rand(5,10), loop = -1, easing = LINEAR_EASING)
animate(color = "#FFFF00", time = rand(5,10), loop = -1, easing = LINEAR_EASING)
animate(color = "#00FF00", time = rand(5,10), loop = -1, easing = LINEAR_EASING)
animate(color = "#00FFFF", time = rand(5,10), loop = -1, easing = LINEAR_EASING)
animate(color = "#0000FF", time = rand(5,10), loop = -1, easing = LINEAR_EASING)
animate(color = "#FF00FF", time = rand(5,10), loop = -1, easing = LINEAR_EASING)
return
/proc/animate_fade_to_color_fill(var/atom/A,var/the_color,var/time)
if (!istype(A) || !the_color || !time)
return
animate(A, color = the_color, time = time, easing = LINEAR_EASING)
/proc/animate_flash_color_fill(var/atom/A,var/the_color,var/loops,var/time)
if (!istype(A) || !the_color || !time || !loops)
return
animate(A, color = the_color, time = time, easing = LINEAR_EASING)
animate(color = "#FFFFFF", time = 5, loop = loops, easing = LINEAR_EASING)
/proc/animate_flash_color_fill_inherit(var/atom/A,var/the_color,var/loops,var/time)
if (!istype(A) || !the_color || !time || !loops)
return
var/color_old = A.color
animate(A, color = the_color, time = time, loop = loops, easing = LINEAR_EASING)
animate(A, color = color_old, time = time, loop = loops, easing = LINEAR_EASING)
/proc/animate_clownspell(var/atom/A)
if (!istype(A))
return
animate(A, transform = matrix(1.3, MATRIX_SCALE), time = 5, color = "#00ff00", easing = BACK_EASING)
animate(transform = null, time = 5, color = "#ffffff", easing = ELASTIC_EASING)
return
/proc/animate_wiggle_then_reset(var/atom/A, var/loops = 5, var/speed = 5, var/x_var = 3, var/y_var = 3)
if (!istype(A) || !loops || !speed)
return
animate(A, pixel_x = rand(-x_var, x_var), pixel_y = rand(-y_var, y_var), time = speed * 2,loop = loops, easing = rand(2,7))
animate(pixel_x = 0, pixel_y = 0, time = speed, easing = rand(2,7))
/proc/animate_spin(var/atom/A, var/dir = "L", var/T = 1, var/looping = -1)
if (!istype(A))
return
var/matrix/M = A.transform
var/turn = -90
if (dir == "R")
turn = 90
animate(A, transform = matrix(M, turn, MATRIX_ROTATE | MATRIX_MODIFY), time = T, loop = looping)
animate(transform = matrix(M, turn, MATRIX_ROTATE | MATRIX_MODIFY), time = T, loop = looping)
animate(transform = matrix(M, turn, MATRIX_ROTATE | MATRIX_MODIFY), time = T, loop = looping)
animate(transform = matrix(M, turn, MATRIX_ROTATE | MATRIX_MODIFY), time = T, loop = looping)
return
/proc/animate_shockwave(var/atom/A)
if (!istype(A))
return
var/punchstr = rand(10, 20)
var/original_y = A.pixel_y
animate(A, transform = matrix(punchstr, MATRIX_ROTATE), pixel_y = 16, time = 2, color = "#eeeeee", easing = BOUNCE_EASING)
animate(transform = matrix(-punchstr, MATRIX_ROTATE), pixel_y = original_y, time = 2, color = "#ffffff", easing = BOUNCE_EASING)
animate(transform = null, time = 3, easing = BOUNCE_EASING)
return

View File

@@ -950,7 +950,7 @@ var/gamma_ship_location = 1 // 0 = station , 1 = space
//returns 1 to let the dragdrop code know we are trapping this event
//returns 0 if we don't plan to trap the event
/datum/admins/proc/cmd_ghost_drag(var/mob/dead/observer/frommob, var/mob/living/tomob)
/datum/admins/proc/cmd_ghost_drag(var/mob/dead/observer/frommob, var/tothing)
if(!istype(frommob))
return //extra sanity check to make sure only observers are shoved into things
@@ -962,26 +962,49 @@ var/gamma_ship_location = 1 // 0 = station , 1 = space
if (!frommob.ckey)
return 0
var/question = ""
if (tomob.ckey)
question = "This mob already has a user ([tomob.key]) in control of it! "
question += "Are you sure you want to place [frommob.name]([frommob.key]) in control of [tomob.name]?"
if(istype(tothing, /obj/item))
var/mob/living/toitem = tothing
var/ask = alert("Are you sure you want to allow [frommob.name]([frommob.key]) to possess [toitem.name]?", "Place ghost in control of item?", "Yes", "No")
if (ask != "Yes")
return 1
if(!frommob || !toitem) //make sure the mobs don't go away while we waited for a response
return 1
var/mob/living/simple_animal/possessed_object/tomob = new(toitem)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has put [frommob.ckey] in control of [tomob.name].</span>")
log_admin("[key_name(usr)] stuffed [frommob.ckey] into [tomob.name].")
feedback_add_details("admin_verb","CGD")
tomob.ckey = frommob.ckey
qdel(frommob)
if(istype(tothing, /mob/living))
var/mob/living/tomob = tothing
var/question = ""
if (tomob.ckey)
question = "This mob already has a user ([tomob.key]) in control of it! "
question += "Are you sure you want to place [frommob.name]([frommob.key]) in control of [tomob.name]?"
var/ask = alert(question, "Place ghost in control of mob?", "Yes", "No")
if (ask != "Yes")
return 1
if(!frommob || !tomob) //make sure the mobs don't go away while we waited for a response
return 1
if(tomob.client) //no need to ghostize if there is no client
tomob.ghostize(0)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has put [frommob.ckey] in control of [tomob.name].</span>")
log_admin("[key_name(usr)] stuffed [frommob.ckey] into [tomob.name].")
feedback_add_details("admin_verb","CGD")
tomob.ckey = frommob.ckey
qdel(frommob)
var/ask = alert(question, "Place ghost in control of mob?", "Yes", "No")
if (ask != "Yes")
return 1
if(!frommob || !tomob) //make sure the mobs don't go away while we waited for a response
return 1
if(tomob.client) //no need to ghostize if there is no client
tomob.ghostize(0)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has put [frommob.ckey] in control of [tomob.name].</span>")
log_admin("[key_name(usr)] stuffed [frommob.ckey] into [tomob.name].")
feedback_add_details("admin_verb","CGD")
tomob.ckey = frommob.ckey
qdel(frommob)
return 1

View File

@@ -517,7 +517,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
//this is called when a ghost is drag clicked to something.
/mob/dead/observer/MouseDrop(atom/over)
if(!usr || !over) return
if (isobserver(usr) && usr.client && usr.client.holder && isliving(over))
if (isobserver(usr) && usr.client && usr.client.holder)
if (usr.client.holder.cmd_ghost_drag(src,over))
return

View File

@@ -0,0 +1,135 @@
/mob/living/simple_animal/possessed_object
name = "possessed doodad"
health = 50
maxHealth = 50
pass_flags = PASSTABLE // Floating past tables is pretty damn spooky.
status_flags = null // No canpush to prevent grabs ...
density = 0 // ... But a density of 0 means we won't be blocking anyone's way.
healable = 0 // Animated with SPACE NECROMANCY, mere mortal medicines cannot heal such an object.
wander = 0 // These things probably ought to never be AI controlled, but in the event they are probably shouldn't wander.
universal_speak = 1 // Tell the humans spooky things about the afterlife
speak_emote = list("mumbles", "moans", "whispers", "laments", "screeches")
allow_spin = 0 // No spinning. Spinning breaks our floating animation and broken floating animations make ghosts SUPER ANGRY.
no_spin_thrown = 1
var/obj/item/possessed_item
/mob/living/simple_animal/possessed_object/examine()
..()
if(health > (maxHealth / 30))
to_chat(usr, "<span class='warning'>[src] appears to be floating without any support!</span>"
else
to_chat(usr, "<span class='warning'>[src] appears to be having trouble staying afloat!</span>"
/mob/living/simple_animal/possessed_object/do_attack_animation(atom/A)
..()
animate_ghostly_presence(src, -1, 20, 1) // Restart the floating animation after the attack animation, as it will be cancelled.
/mob/living/simple_animal/possessed_object/start_pulling(var/atom/movable/AM) // Silly motherfuckers think they can pull things.
to_chat(src, "<span class='warning'>You are unable to pull [AM]!</span>")
return
/mob/living/simple_animal/possessed_object/ghost() // Ghosting will return the object to normal, and will not disqualify the ghoster from various mid-round antag positions.
var/response = alert(src, "End your possession of this object? (It will not stop you from respawning later)","Are you sure you want to ghost?","Ghost","Stay in body")
if(response != "Ghost") return
resting = 1
var/mob/dead/observer/ghost = ghostize(1)
ghost.timeofdeath = world.time
death(0) // Turn back into a regular object.
/mob/living/simple_animal/possessed_object/death(gibbed)
if(gibbed) // Leave no trace.
qdel(src)
return
..()
possessed_item.forceMove(src.loc) // Put the normal item back once the EVIL SPIRIT has been vanquished from it.
qdel(src)
/mob/living/simple_animal/possessed_object/New(var/atom/loc as obj)
..()
if (!istype(loc, /obj/item)) // Some silly motherfucker spawned us directly via the game panel.
message_admins("<span class='adminnotice'>Posessed object improperly spawned, deleting.</span>") // So silly admins with debug off will see the message too and not spam these things.
log_debug("[src] spawned manually, no object to assign attributes to.")
qdel()
if(!istype(get_turf(loc), /turf)) // Will this ever happen? Who goddamn knows.
message_admins("<span class='adminnotice'>Posessed object could not find turf, deleting.</span>") // So silly admins with debug off will see the message too and not spam these things.
log_debug("[src] attempted to find a turf to spawn on, and could not.")
qdel()
possessed_item = loc
forceMove(get_turf(possessed_item))
possessed_item.forceMove(src) // We'll keep the actual item inside of us until we die.
zone_sel = new /obj/screen/zone_sel(src) // Create a new zone selection item so the human attacks have something to reference.
name = possessed_item.name // Take on all the attributes of the item we've possessed.
real_name = src.name
desc = possessed_item.desc
icon = possessed_item.icon
icon_living = possessed_item.icon_state
icon_state = possessed_item.icon_state
dir = possessed_item.dir
color = possessed_item.color
overlays = possessed_item.overlays
opacity = possessed_item.opacity
attacktext = "has [possessed_item.attack_verb.len ? pick(possessed_item.attack_verb) : "attacked"]"
src.visible_message("<span class='warning'>[src] rises into the air and begins to float!</span>") // Inform those around us that shit's gettin' spooky.
animate_ghostly_presence(src, -1, 20, 1)
/mob/living/simple_animal/possessed_object/get_active_hand() // So that our attacks count as attacking with the item we've possessed.
return possessed_item
/mob/living/simple_animal/possessed_object/IsAdvancedToolUser() // So we can shoot guns (Mostly ourselves), among other things.
return 1
/mob/living/simple_animal/possessed_object/get_access() // If we've possessed an ID card we've got access to lots of fun things!
if(istype(possessed_item, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/possessed_id = possessed_item
return possessed_id.access
return 0
/mob/living/simple_animal/possessed_object/ClickOn(var/atom/A, var/params)
if(client.click_intercept)
client.click_intercept.InterceptClickOn(src, params, A)
return
if(!istype(loc, /turf)) // If we're inside a card machine or something similar then you're stuck.
return
if(A == src) // If we're clicking ourself we should not attack ourself.
possessed_item.attack_self(src)
else
..()
if(possessed_item.loc != src) // If we've, say, placed the possessed item on the table move onto the table ourselves instead and put it back inside of us.
src.forceMove(possessed_item.loc)
possessed_item.forceMove(src)
name = possessed_item.name // Update our status
real_name = src.name
desc = possessed_item.desc
icon = possessed_item.icon
icon_living = possessed_item.icon_state
icon_state = possessed_item.icon_state
dir = possessed_item.dir
color = possessed_item.color
overlays = possessed_item.overlays
opacity = possessed_item.opacity
attacktext = "has [possessed_item.attack_verb.len ? pick(possessed_item.attack_verb) : "attacked"]"

View File

@@ -43,6 +43,7 @@
#include "code\__DEFINES\stat.dm"
#include "code\__DEFINES\tick.dm"
#include "code\__HELPERS\_string_lists.dm"
#include "code\__HELPERS\AnimationLibrary.dm"
#include "code\__HELPERS\constants.dm"
#include "code\__HELPERS\experimental.dm"
#include "code\__HELPERS\files.dm"
@@ -1574,6 +1575,7 @@
#include "code\modules\mob\living\simple_animal\corpse.dm"
#include "code\modules\mob\living\simple_animal\parrot.dm"
#include "code\modules\mob\living\simple_animal\pony.dm"
#include "code\modules\mob\living\simple_animal\posessed_object.dm"
#include "code\modules\mob\living\simple_animal\powers.dm"
#include "code\modules\mob\living\simple_animal\shade.dm"
#include "code\modules\mob\living\simple_animal\simple_animal.dm"