diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index 671bf0540b8..9a7cd21ce3f 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -13,7 +13,8 @@ // Otherwise jump else - loc = get_turf(A) + following = null + forceMove(get_turf(A)) /mob/dead/observer/ClickOn(var/atom/A, var/params) if(client.buildmode) @@ -33,28 +34,6 @@ // Not all of them require checking, see below A.attack_ghost(src) - -// This is the ghost's follow verb with an argument -/mob/dead/observer/proc/ManualFollow(var/atom/target) - following = target - if(target) - src << "\blue Now following [target]" - spawn(0) - var/turf/pos = get_turf(src) - while(loc == pos && target && following == target) - - var/turf/T = get_turf(target) - if(!T) - break - if(following != target) - break - if(!client) - break - loc = T - pos = loc - sleep(15) - following = null - // We don't need a fucking toggle. /mob/dead/observer/ShiftClickOn(var/atom/A) A.examine() @@ -71,33 +50,20 @@ if(S) var/obj/machinery/computer/teleporter/com = S.teleporter_console if(com && com.target) - user.loc = get_turf(com.target) + user.forceMove(get_turf(com.target)) /obj/effect/portal/attack_ghost(mob/user as mob) if(target) - user.loc = get_turf(target) + user.forceMove(get_turf(target)) /obj/machinery/gateway/centerstation/attack_ghost(mob/user as mob) if(awaygate) - user.loc = awaygate.loc + user.forceMove(awaygate.loc) else user << "[src] has no destination." /obj/machinery/gateway/centeraway/attack_ghost(mob/user as mob) if(stationgate) - user.loc = stationgate.loc + user.forceMove(stationgate.loc) else user << "[src] has no destination." - -// ------------------------------------------- -// This was supposed to be used by adminghosts -// I think it is a *terrible* idea -// but I'm leaving it here anyway -// commented out, of course. - -/atom/proc/attack_admin(mob/user as mob) - if(!user || !user.client || !user.client.holder) - return - attack_hand(user) - - diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm index ca47ab1afc7..e7c77f639f3 100644 --- a/code/modules/awaymissions/gateway.dm +++ b/code/modules/awaymissions/gateway.dm @@ -125,13 +125,13 @@ obj/machinery/gateway/centerstation/process() if(!awaygate) return if(awaygate.calibrated) - M.loc = get_step(awaygate.loc, SOUTH) + M.forceMove(get_step(awaygate.loc, SOUTH)) M.dir = SOUTH return else var/obj/effect/landmark/dest = pick(awaydestinations) if(dest) - M.loc = dest.loc + M.forceMove(dest.loc) M.dir = SOUTH use_power(5000) return @@ -230,7 +230,7 @@ obj/machinery/gateway/centerstation/process() if(E.imp_in == M)//Checking that it's actually implanted vs just in their pocket M << "\black The station gate has detected your exile implant and is blocking your entry." return - M.loc = get_step(stationgate.loc, SOUTH) + M.forceMove(get_step(stationgate.loc, SOUTH)) M.dir = SOUTH @@ -242,4 +242,5 @@ obj/machinery/gateway/centerstation/process() else user << "Recalibration successful!: \black This gate's systems have been fine tuned. Travel to this gate will now be on target." calibrated = 1 - return \ No newline at end of file + return + \ No newline at end of file diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 6a2722470b2..3c61d7c2f6e 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -79,7 +79,7 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi mind = body.mind //we don't transfer the mind but we keep a reference to it. if(!T) T = pick(latejoin) //Safety in case we cannot find the body's position - loc = T + forceMove(T) if(!name) //To prevent nameless ghosts name = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names)) @@ -96,12 +96,12 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi /mob/dead/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) return 1 + + /* Transfer_mind is there to check if mob is being deleted/not going to have a body. Works together with spawning an observer, noted above. */ - - /mob/dead/observer/Life() ..() if(!loc) return @@ -200,10 +200,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return -/mob/dead/observer/Move(NewLoc, direct) +/mob/dead/observer/Move(NewLoc, direct) + following = null dir = direct if(NewLoc) - loc = NewLoc + forceMove(NewLoc) for(var/obj/effect/step_trigger/S in NewLoc) S.Crossed(src) @@ -212,7 +213,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp A.Entered(src) return - loc = get_turf(src) //Get out of closets and such as a ghost + forceMove(get_turf(src)) //Get out of closets and such as a ghost if((direct & NORTH) && y < world.maxy) y++ else if((direct & SOUTH) && y > 1) @@ -228,6 +229,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/area/A = get_area_master(src) if(A) A.Entered(src) + + ..() /mob/dead/observer/experience_pressure_difference() return 0 @@ -326,7 +329,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp M.antagHUD = 1 src << "\blue AntagHUD Enabled" -/mob/dead/observer/proc/dead_tele() +/mob/dead/observer/proc/dead_tele(A in ghostteleportlocs) set category = "Ghost" set name = "Teleport" set desc= "Teleport to a location" @@ -338,73 +341,107 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp usr.verbs -= /mob/dead/observer/proc/dead_tele spawn(30) usr.verbs += /mob/dead/observer/proc/dead_tele - var/A - A = input("Area to jump to", "BOOYEA", A) as null|anything in ghostteleportlocs + var/area/thearea = ghostteleportlocs[A] if(!thearea) return var/list/L = list() for(var/turf/T in get_area_turfs(thearea.type)) - L+=T + L += T if(!L || !L.len) - usr << "No area available." + usr << "No area available." usr.forceMove(pick(L)) + following = null -/mob/dead/observer/verb/follow() +/mob/dead/observer/verb/follow(input in getmobs()) set category = "Ghost" set name = "Follow" // "Haunt" set desc = "Follow and haunt a mob." - if(istype(usr, /mob/dead/observer)) - var/list/mobs = getmobs() - var/input = input("Please, select a mob!", "Haunt", null, null) as null|anything in mobs - var/mob/target = mobs[input] - if(target && target != usr) - following = target - spawn(0) - var/turf/pos = get_turf(src) - while(src.loc == pos) + var/target = getmobs()[input] + if(!target) return + ManualFollow(target) +// This is the ghost's follow verb with an argument +/mob/dead/observer/proc/ManualFollow(var/atom/movable/target) + if(!target) + return + + if(target != src) + if(following && following == target) + return + following = target + src << "Now following [target]" + if(ismob(target)) + forceMove(get_turf(target)) + var/mob/M = target + M.following_mobs += src + else + spawn(0) + while(target && following == target && client) var/turf/T = get_turf(target) if(!T) break - if(following != target) - break - if(!client) - break - src.loc = T - pos = src.loc + // To stop the ghost flickering. + if(loc != T) + forceMove(T) sleep(15) - following = null +/mob/proc/update_following() + . = get_turf(src) + for(var/mob/dead/observer/M in following_mobs) + if(M.following != src) + following_mobs -= M + else + if(M.loc != .) + M.forceMove(.) -/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak +/mob + var/list/following_mobs = list() + +/mob/Destroy() + for(var/mob/dead/observer/M in following_mobs) + M.following = null + following_mobs = null + return ..() + +/mob/dead/observer/Destroy() + if(ismob(following)) + var/mob/M = following + M.following_mobs -= src + following = null + return ..() + +/mob/Move() + . = ..() + if(.) + update_following() + +/mob/Life() + // to catch teleports etc which directly set loc + update_following() + return ..() + +/mob/dead/observer/verb/jumptomob(target in getmobs()) //Moves the ghost instead of just changing the ghosts's eye -Nodrak set category = "Ghost" set name = "Jump to Mob" set desc = "Teleport to a mob" if(istype(usr, /mob/dead/observer)) //Make sure they're an observer! - - var/list/dest = list() //List of possible destinations (mobs) - var/target = null //Chosen target. - - dest += getmobs() //Fill list, prompt user with list - target = input("Please, select a player!", "Jump to Mob", null, null) as null|anything in dest - if (!target)//Make sure we actually have a target return else - var/mob/M = dest[target] //Destination mob - var/mob/A = src //Source mob + var/mob/M = getmobs()[target] //Destination mob var/turf/T = get_turf(M) //Turf of the destination mob if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination. - A.loc = T + forceMove(T) + following = null else - A << "This mob is not located in the game world." + src << "This mob is not located in the game world." /* Now a spell. See spells.dm @@ -548,7 +585,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return if(!client) return - loc = T + forceMove(T) following = null ..() //END TELEPORT HREF CODE diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 65864f5d912..fa834fa581b 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -526,7 +526,7 @@ src << "You wriggle out of [M]'s grip!" else if(istype(H.loc,/obj/item)) src << "You struggle free of [H.loc]." - H.loc = get_turf(H) + H.forceMove(get_turf(H)) if(istype(M)) for(var/atom/A in M.contents)