mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
[READY] The Portal Update - Linked portals, momentum conservation, and more! (#28055)
* THE PORTAL UPDATE * portal gun checks * damn functions * o_range(s) * Atmos Portals (#12) * Rod Form's damage now scales with how much it's upgraded * buffs chem grenades * Fix getrev runtime * Automatic changelog generation for PR #27948 [ci skip] * Automatic changelog generation for PR #27951 [ci skip] * Fixes admiral recall (#27861) * the man with the 2 shotguns that blasted me to the end of the world with dualwielding. nerf (#27978) * Beam rifles now slowdown while scoped (#27898) * Update beam_rifle.dm * Update beam_rifle.dm * Update beam_rifle.dm * Fixes a very silly clockwork false wall trick (#27996) * Fixes #27979 (#28002) * Automatic changelog generation for PR #28002 [ci skip] * Fixes #27989 : Riot suits no longer hide jumpsuits (#28003) * Fixes #27989 * remove tag * Automatic changelog generation for PR #28003 [ci skip] * Refactors a cooldown var to not require a spawn or sleep (#28011) * wat (#28012) * Remove spawns in favour of stacktrace calls, which don't stop the called (#28013) proc * Refactor another spawned cooldown var (#28014) * Come on, pathetic (#28015) * Refactor another spawn cooldown (#28016) * Goodbye spawn (#28017) * Another spawn timer (#28018) * Remove a commented out function (#28019) * Gotta go with the fro2.0 (#28010) * This doesn't do anything (#28020) * refactor another spawn cooldown (#28022) * Refactors another spawn cooldown var (#28023) * Refactor another spawn (#28024) * Refactor another spawn var (#28027) * woops * woops2 * atmos links! * unused * wew * ffs! * Forced updates * update * Update portals.dm * adjacent/atmospass checks * Create portals.dm * Update portals.dm * Update other_tools.dm * stuff * crossed * documentation * reee * no portal stacking! * woops
This commit is contained in:
@@ -1242,9 +1242,15 @@ proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
|
||||
#define QDEL_IN(item, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, item), time, TIMER_STOPPABLE)
|
||||
#define QDEL_NULL(item) qdel(item); item = null
|
||||
#define QDEL_LIST(L) if(L) { for(var/I in L) qdel(I); L.Cut(); }
|
||||
#define QDEL_LIST_IN(L, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/______qdel_list_wrapper, L), time, TIMER_STOPPABLE)
|
||||
#define QDEL_LIST_ASSOC(L) if(L) { for(var/I in L) { qdel(L[I]); qdel(I); } L.Cut(); }
|
||||
#define QDEL_LIST_ASSOC_VAL(L) if(L) { for(var/I in L) qel(L[I]); L.Cut(); }
|
||||
|
||||
/proc/______qdel_list_wrapper(list/L) //the underscores are to encourage people not to use this directly.
|
||||
QDEL_LIST(L)
|
||||
|
||||
|
||||
|
||||
/proc/random_nukecode()
|
||||
var/val = rand(0, 99999)
|
||||
var/str = "[val]"
|
||||
|
||||
@@ -67,8 +67,8 @@
|
||||
user.forceMove(get_turf(com.locked))
|
||||
|
||||
/obj/effect/portal/attack_ghost(mob/user)
|
||||
if(target)
|
||||
user.forceMove(get_turf(target))
|
||||
if(linked)
|
||||
user.forceMove(get_turf(linked))
|
||||
|
||||
/obj/machinery/gateway/centerstation/attack_ghost(mob/user)
|
||||
if(awaygate)
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
var/soundout //soundfile to play after teleportation
|
||||
var/force_teleport = 1 //if false, teleport will use Move() proc (dense objects will prevent teleportation)
|
||||
|
||||
|
||||
/datum/teleport/proc/start(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null)
|
||||
if(!initTeleport(arglist(args)))
|
||||
return 0
|
||||
@@ -100,21 +99,7 @@
|
||||
|
||||
var/turf/destturf
|
||||
var/turf/curturf = get_turf(teleatom)
|
||||
if(precision)
|
||||
var/list/posturfs = list()
|
||||
var/center = get_turf(destination)
|
||||
if(!center)
|
||||
center = destination
|
||||
for(var/turf/T in range(precision,center))
|
||||
if(T.is_transition_turf())
|
||||
continue // Avoid picking these.
|
||||
var/area/A = T.loc
|
||||
if(!A.noteleport)
|
||||
posturfs.Add(T)
|
||||
|
||||
destturf = safepick(posturfs)
|
||||
else
|
||||
destturf = get_turf(destination)
|
||||
destturf = get_teleport_turf(get_turf(destination), precision)
|
||||
|
||||
if(!destturf || !curturf || destturf.is_transition_turf())
|
||||
return 0
|
||||
@@ -124,13 +109,16 @@
|
||||
return 0
|
||||
|
||||
playSpecials(curturf,effectin,soundin)
|
||||
|
||||
if(force_teleport)
|
||||
teleatom.forceMove(destturf)
|
||||
if(ismegafauna(teleatom))
|
||||
message_admins("[teleatom] [ADMIN_FLW(teleatom)] has teleported from [ADMIN_COORDJMP(curturf)] to [ADMIN_COORDJMP(destturf)].")
|
||||
playSpecials(destturf,effectout,soundout)
|
||||
else
|
||||
if(teleatom.Move(destturf))
|
||||
playSpecials(destturf,effectout,soundout)
|
||||
if(ismegafauna(teleatom))
|
||||
message_admins("[teleatom] [ADMIN_FLW(teleatom)] has teleported from [ADMIN_COORDJMP(curturf)] to [ADMIN_COORDJMP(destturf)].")
|
||||
return 1
|
||||
|
||||
/datum/teleport/proc/teleport()
|
||||
@@ -225,3 +213,18 @@
|
||||
|
||||
// DING! You have passed the gauntlet, and are "probably" safe.
|
||||
return F
|
||||
|
||||
/proc/get_teleport_turfs(turf/center, precision = 0)
|
||||
if(!precision)
|
||||
return list(center)
|
||||
var/list/posturfs = list()
|
||||
for(var/turf/T in range(precision,center))
|
||||
if(T.is_transition_turf())
|
||||
continue // Avoid picking these.
|
||||
var/area/A = T.loc
|
||||
if(!A.noteleport)
|
||||
posturfs.Add(T)
|
||||
return posturfs
|
||||
|
||||
/proc/get_teleport_turf(turf/center, precision = 0)
|
||||
return safepick(get_teleport_turfs(center, precision))
|
||||
|
||||
@@ -213,7 +213,8 @@
|
||||
|
||||
// Previously known as HasEntered()
|
||||
// This is automatically called when something enters your square
|
||||
/atom/movable/Crossed(atom/movable/AM)
|
||||
//oldloc = old location on atom, inserted when forceMove is called and ONLY when forceMove is called!
|
||||
/atom/movable/Crossed(atom/movable/AM, oldloc)
|
||||
return
|
||||
|
||||
/atom/movable/Bump(atom/A, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump().
|
||||
@@ -249,7 +250,7 @@
|
||||
for(var/atom/movable/AM in destination)
|
||||
if(AM == src)
|
||||
continue
|
||||
AM.Crossed(src)
|
||||
AM.Crossed(src, oldloc)
|
||||
|
||||
Moved(oldloc, 0)
|
||||
return 1
|
||||
|
||||
@@ -57,18 +57,12 @@
|
||||
var/turf/target_turf = pick(L)
|
||||
if(!target_turf)
|
||||
return
|
||||
var/obj/effect/portal/P = new /obj/effect/portal(get_turf(target))
|
||||
P.target = target_turf
|
||||
P.creator = null
|
||||
P.icon = 'icons/obj/objects.dmi'
|
||||
P.icon_state = "anom"
|
||||
P.name = "wormhole"
|
||||
P.mech_sized = TRUE
|
||||
var/list/obj/effect/portal/created = create_portal_pair(get_turf(src), target_turf, src, 300, 1, /obj/effect/portal/anom)
|
||||
var/turf/T = get_turf(target)
|
||||
message_admins("[ADMIN_LOOKUPFLW(chassis.occupant)] used a Wormhole Generator in [ADMIN_COORDJMP(T)]",0,1)
|
||||
log_game("[key_name(chassis.occupant)] used a Wormhole Generator in [COORD(T)]")
|
||||
src = null
|
||||
QDEL_IN(P, rand(150,300))
|
||||
QDEL_LIST_IN(created, rand(150,300))
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +1,42 @@
|
||||
|
||||
/proc/create_portal_pair(turf/source, turf/destination, _creator = null, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal)
|
||||
if(!istype(source) || !istype(destination))
|
||||
return
|
||||
var/turf/actual_destination = get_teleport_turf(destination, accuracy)
|
||||
var/obj/effect/portal/P1 = new newtype(source, _creator, _lifespan, null, FALSE)
|
||||
var/obj/effect/portal/P2 = new newtype(actual_destination, _creator, _lifespan, P1, TRUE)
|
||||
if(!istype(P1)||!istype(P2))
|
||||
return
|
||||
P1.link_portal(P2)
|
||||
P1.hardlinked = TRUE
|
||||
return list(P1, P2)
|
||||
|
||||
/obj/effect/portal
|
||||
name = "portal"
|
||||
desc = "Looks unstable. Best to test it with the clown."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "portal"
|
||||
density = 1
|
||||
var/obj/item/target = null
|
||||
var/creator = null
|
||||
anchored = 1
|
||||
var/precision = 1 // how close to the portal you will teleport. 0 = on the portal, 1 = adjacent
|
||||
anchored = TRUE
|
||||
var/mech_sized = FALSE
|
||||
var/obj/effect/portal/linked
|
||||
var/hardlinked = TRUE //Requires a linked portal at all times. Destroy if there's no linked portal, if there is destroy it when this one is deleted.
|
||||
var/creator
|
||||
var/turf/hard_target //For when a portal needs a hard target and isn't to be linked.
|
||||
var/atmos_link = FALSE //Link source/destination atmos.
|
||||
var/turf/open/atmos_source //Atmos link source
|
||||
var/turf/open/atmos_destination //Atmos link destination
|
||||
|
||||
/obj/effect/portal/Bumped(mob/M as mob|obj)
|
||||
teleport(M)
|
||||
/obj/effect/portal/anom
|
||||
name = "wormhole"
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "anom"
|
||||
mech_sized = TRUE
|
||||
|
||||
/obj/effect/portal/attack_tk(mob/user)
|
||||
return
|
||||
|
||||
/obj/effect/portal/attack_hand(mob/user)
|
||||
if(Adjacent(user))
|
||||
teleport(user)
|
||||
/obj/effect/portal/Move(newloc)
|
||||
for(var/T in newloc)
|
||||
if(istype(T, /obj/effect/portal))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/effect/portal/attackby(obj/item/weapon/W, mob/user, params)
|
||||
if(user && Adjacent(user))
|
||||
@@ -28,42 +45,113 @@
|
||||
/obj/effect/portal/make_frozen_visual()
|
||||
return
|
||||
|
||||
/obj/effect/portal/New(loc, turf/target, creator=null, lifespan=300)
|
||||
..()
|
||||
GLOB.portals += src
|
||||
src.target = target
|
||||
src.creator = creator
|
||||
|
||||
var/area/A = get_area(target)
|
||||
if(A && A.noteleport) // No point in persisting if the target is unreachable.
|
||||
qdel(src)
|
||||
return
|
||||
if(lifespan > 0)
|
||||
QDEL_IN(src, lifespan)
|
||||
|
||||
/obj/effect/portal/Destroy()
|
||||
GLOB.portals -= src
|
||||
if(istype(creator, /obj/item/weapon/hand_tele))
|
||||
var/obj/item/weapon/hand_tele/O = creator
|
||||
O.active_portals--
|
||||
else if(istype(creator, /obj/item/weapon/gun/energy/wormhole_projector))
|
||||
var/obj/item/weapon/gun/energy/wormhole_projector/P = creator
|
||||
P.portal_destroyed(src)
|
||||
creator = null
|
||||
/obj/effect/portal/Crossed(atom/movable/AM, oldloc)
|
||||
if(get_turf(oldloc) == get_turf(linked))
|
||||
return ..()
|
||||
if(!teleport(AM))
|
||||
return ..()
|
||||
|
||||
/obj/effect/portal/proc/teleport(atom/movable/M as mob|obj)
|
||||
if(istype(M, /obj/effect)) //sparks don't teleport
|
||||
/obj/effect/portal/attack_tk(mob/user)
|
||||
return
|
||||
if(M.anchored)
|
||||
if(!(istype(M, /obj/mecha) && mech_sized))
|
||||
|
||||
/obj/effect/portal/attack_hand(mob/user)
|
||||
if(Adjacent(user))
|
||||
teleport(user)
|
||||
|
||||
/obj/effect/portal/Initialize(mapload, _creator, _lifespan = 300, obj/effect/portal/_linked, automatic_link = TRUE, hard_target_override, atmos_link_override)
|
||||
. = ..()
|
||||
GLOB.portals += src
|
||||
if(!istype(_linked) && automatic_link)
|
||||
. = INITIALIZE_HINT_QDEL
|
||||
CRASH("Somebody fucked up.")
|
||||
if(_lifespan > 0)
|
||||
QDEL_IN(src, _lifespan)
|
||||
if(!isnull(atmos_link_override))
|
||||
atmos_link = atmos_link_override
|
||||
link_portal(_linked)
|
||||
hardlinked = automatic_link
|
||||
creator = _creator
|
||||
|
||||
/obj/effect/portal/proc/link_portal(obj/effect/portal/newlink)
|
||||
linked = newlink
|
||||
if(atmos_link)
|
||||
link_atmos()
|
||||
|
||||
/obj/effect/portal/proc/link_atmos()
|
||||
if(atmos_source || atmos_destination)
|
||||
unlink_atmos()
|
||||
if(!isopenturf(get_turf(src)))
|
||||
return FALSE
|
||||
if(linked)
|
||||
if(isopenturf(get_turf(linked)))
|
||||
atmos_source = get_turf(src)
|
||||
atmos_destination = get_turf(linked)
|
||||
else if(hard_target)
|
||||
if(isopenturf(hard_target))
|
||||
atmos_source = get_turf(src)
|
||||
atmos_destination = hard_target
|
||||
else
|
||||
return FALSE
|
||||
if(!istype(atmos_source) || !istype(atmos_destination))
|
||||
return FALSE
|
||||
LAZYINITLIST(atmos_source.atmos_adjacent_turfs)
|
||||
LAZYINITLIST(atmos_destination.atmos_adjacent_turfs)
|
||||
if(atmos_source.atmos_adjacent_turfs[atmos_destination] || atmos_destination.atmos_adjacent_turfs[atmos_source]) //Already linked!
|
||||
return FALSE
|
||||
atmos_source.atmos_adjacent_turfs[atmos_destination] = TRUE
|
||||
atmos_destination.atmos_adjacent_turfs[atmos_source] = TRUE
|
||||
atmos_source.air_update_turf(FALSE)
|
||||
atmos_destination.air_update_turf(FALSE)
|
||||
|
||||
/obj/effect/portal/proc/unlink_atmos()
|
||||
if(istype(atmos_source))
|
||||
if(istype(atmos_destination) && !atmos_source.Adjacent(atmos_destination) && !CANATMOSPASS(atmos_destination, atmos_source))
|
||||
LAZYREMOVE(atmos_source.atmos_adjacent_turfs, atmos_destination)
|
||||
atmos_source = null
|
||||
if(istype(atmos_destination))
|
||||
if(istype(atmos_source) && !atmos_destination.Adjacent(atmos_source) && !CANATMOSPASS(atmos_source, atmos_destination))
|
||||
LAZYREMOVE(atmos_destination.atmos_adjacent_turfs, atmos_source)
|
||||
atmos_destination = null
|
||||
|
||||
/obj/effect/portal/Destroy() //Calls on_portal_destroy(destroyed portal, location of destroyed portal) on creator if creator has such call.
|
||||
if(creator && hascall(creator, "on_portal_destroy"))
|
||||
call(creator, "on_portal_destroy")(src, src.loc)
|
||||
creator = null
|
||||
GLOB.portals -= src
|
||||
unlink_atmos()
|
||||
if(hardlinked && !QDELETED(linked))
|
||||
QDEL_NULL(linked)
|
||||
else
|
||||
linked = null
|
||||
return ..()
|
||||
|
||||
/obj/effect/portal/proc/teleport(atom/movable/M)
|
||||
if(!istype(M) || istype(M, /obj/effect) || (istype(M, /obj/mecha) && !mech_sized) || (!isobj(M) && !ismob(M))) //Things that shouldn't teleport.
|
||||
return
|
||||
if (!( target ))
|
||||
qdel(src)
|
||||
return
|
||||
if (istype(M, /atom/movable))
|
||||
var/turf/real_target = get_link_target_turf()
|
||||
if(!istype(real_target))
|
||||
return FALSE
|
||||
if(ismegafauna(M))
|
||||
message_admins("[M] [ADMIN_FLW(M)] has teleported through [src].")
|
||||
do_teleport(M, target, precision) ///You will appear adjacent to the beacon
|
||||
message_admins("[M] has used a portal at [ADMIN_COORDJMP(src)] made by [usr].")
|
||||
if(do_teleport(M, real_target, 0))
|
||||
if(istype(M, /obj/item/projectile))
|
||||
var/obj/item/projectile/P = M
|
||||
P.ignore_source_check = TRUE
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/effect/portal/proc/get_link_target_turf()
|
||||
var/turf/real_target
|
||||
if(!istype(linked) || QDELETED(linked))
|
||||
if(hardlinked)
|
||||
qdel(src)
|
||||
if(!istype(hard_target) || QDELETED(hard_target))
|
||||
hard_target = null
|
||||
return
|
||||
else
|
||||
real_target = hard_target
|
||||
linked = null
|
||||
else
|
||||
real_target = get_turf(linked)
|
||||
return real_target
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
|
||||
#define SOURCE_PORTAL 1
|
||||
#define DESTINATION_PORTAL 2
|
||||
|
||||
/* Teleportation devices.
|
||||
* Contains:
|
||||
* Locator
|
||||
@@ -136,7 +140,19 @@ Frequency:
|
||||
origin_tech = "magnets=3;bluespace=4"
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 30, bio = 0, rad = 0, fire = 100, acid = 100)
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
var/active_portals = 0
|
||||
var/list/active_portal_pairs
|
||||
var/max_portal_pairs = 3
|
||||
|
||||
/obj/item/weapon/hand_tele/Initialize()
|
||||
. = ..()
|
||||
active_portal_pairs = list()
|
||||
|
||||
/obj/item/weapon/hand_tele/afterattack(atom/target, mob/user, proximity, params)
|
||||
if(is_parent_of_portal(target))
|
||||
qdel(target)
|
||||
to_chat(user, "<span class='notice'>You dispel [target] remotely with \the [src]!</span>")
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/weapon/hand_tele/attack_self(mob/user)
|
||||
var/turf/current_location = get_turf(user)//What turf is the user on?
|
||||
@@ -169,7 +185,7 @@ Frequency:
|
||||
var/t1 = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") as null|anything in L
|
||||
if (!t1 || user.get_active_held_item() != src || user.incapacitated())
|
||||
return
|
||||
if(active_portals >= 3)
|
||||
if(active_portal_pairs.len >= max_portal_pairs)
|
||||
user.show_message("<span class='notice'>\The [src] is recharging!</span>")
|
||||
return
|
||||
var/atom/T = L[t1]
|
||||
@@ -178,7 +194,22 @@ Frequency:
|
||||
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
|
||||
return
|
||||
user.show_message("<span class='notice'>Locked In.</span>", 2)
|
||||
var/obj/effect/portal/P = new /obj/effect/portal(get_turf(src), T, src)
|
||||
try_move_adjacent(P)
|
||||
active_portals++
|
||||
var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), src, 300, 1)
|
||||
if(!(LAZYLEN(created) == 2))
|
||||
return
|
||||
try_move_adjacent(created[1])
|
||||
active_portal_pairs[created[1]] = created[2]
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/item/weapon/hand_tele/proc/on_portal_destroy(obj/effect/portal/P)
|
||||
active_portal_pairs -= P //If this portal pair is made by us it'll be erased along with the other portal by the portal.
|
||||
|
||||
/obj/item/weapon/hand_tele/proc/is_parent_of_portal(obj/effect/portal/P)
|
||||
if(!istype(P))
|
||||
return FALSE
|
||||
if(active_portal_pairs[P])
|
||||
return SOURCE_PORTAL
|
||||
for(var/i in active_portal_pairs)
|
||||
if(active_portal_pairs[i] == P)
|
||||
return DESTINATION_PORTAL
|
||||
return FALSE
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
for(var/i = 1, i <= number_of_wormholes, i++)
|
||||
var/turf/T = pick(pick_turfs)
|
||||
wormholes += new /obj/effect/portal/wormhole(T, null, null, -1)
|
||||
wormholes += new /obj/effect/portal/wormhole(T, null, 300, null, FALSE)
|
||||
|
||||
/datum/round_event/wormholes/announce()
|
||||
priority_announce("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert", 'sound/ai/spanomalies.ogg')
|
||||
@@ -36,14 +36,10 @@
|
||||
for(var/obj/effect/portal/wormhole/O in wormholes)
|
||||
var/turf/T = pick(pick_turfs)
|
||||
if(T)
|
||||
O.loc = T
|
||||
O.forceMove(T)
|
||||
|
||||
/datum/round_event/wormholes/end()
|
||||
GLOB.portals.Remove(wormholes)
|
||||
for(var/obj/effect/portal/wormhole/O in wormholes)
|
||||
O.loc = null
|
||||
wormholes.Cut()
|
||||
|
||||
QDEL_LIST(wormholes)
|
||||
|
||||
/obj/effect/portal/wormhole
|
||||
name = "wormhole"
|
||||
@@ -70,7 +66,7 @@
|
||||
if(GLOB.portals.len)
|
||||
var/obj/effect/portal/P = pick(GLOB.portals)
|
||||
if(P && isturf(P.loc))
|
||||
target = P.loc
|
||||
hard_target = P.loc
|
||||
if(!target)
|
||||
return
|
||||
do_teleport(M, target, 1, 1, 0, 0) ///You will appear adjacent to the beacon
|
||||
do_teleport(M, hard_target, 1, 1, 0, 0) ///You will appear adjacent to the beacon
|
||||
@@ -53,8 +53,7 @@
|
||||
to_chat(user, "<span class='notice'>The [src.name] found no beacons in the world to anchor a wormhole to.</span>")
|
||||
return
|
||||
var/chosen_beacon = pick(L)
|
||||
var/obj/effect/portal/wormhole/jaunt_tunnel/J = new /obj/effect/portal/wormhole/jaunt_tunnel(get_turf(src), chosen_beacon, lifespan=100)
|
||||
J.target = chosen_beacon
|
||||
var/obj/effect/portal/wormhole/jaunt_tunnel/J = new /obj/effect/portal/wormhole/jaunt_tunnel(get_turf(src), src, lifespan=100, null, FALSE, get_turf(chosen_beacon))
|
||||
try_move_adjacent(J)
|
||||
playsound(src,'sound/effects/sparks4.ogg',50,1)
|
||||
qdel(src)
|
||||
@@ -98,7 +97,7 @@
|
||||
return
|
||||
|
||||
if(istype(M, /atom/movable))
|
||||
if(do_teleport(M, target, 6))
|
||||
if(do_teleport(M, hard_target, 6))
|
||||
// KERPLUNK
|
||||
playsound(M,'sound/weapons/resonator_blast.ogg',50,1)
|
||||
if(iscarbon(M))
|
||||
|
||||
@@ -172,8 +172,8 @@
|
||||
item_state = null
|
||||
icon_state = "wormhole_projector"
|
||||
origin_tech = "combat=4;bluespace=6;plasmatech=4;engineering=4"
|
||||
var/obj/effect/portal/blue
|
||||
var/obj/effect/portal/orange
|
||||
var/obj/effect/portal/p_blue
|
||||
var/obj/effect/portal/p_orange
|
||||
|
||||
/obj/item/weapon/gun/energy/wormhole_projector/update_icon()
|
||||
icon_state = "[initial(icon_state)][select]"
|
||||
@@ -184,30 +184,44 @@
|
||||
..()
|
||||
select_fire()
|
||||
|
||||
/obj/item/weapon/gun/energy/wormhole_projector/proc/portal_destroyed(obj/effect/portal/P)
|
||||
if(P.icon_state == "portal")
|
||||
blue = null
|
||||
if(orange)
|
||||
orange.target = null
|
||||
else
|
||||
orange = null
|
||||
if(blue)
|
||||
blue.target = null
|
||||
/obj/item/weapon/gun/energy/wormhole_projector/proc/on_portal_destroy(obj/effect/portal/P)
|
||||
if(P == p_blue)
|
||||
p_blue = null
|
||||
else if(P == p_orange)
|
||||
p_orange = null
|
||||
|
||||
/obj/item/weapon/gun/energy/wormhole_projector/proc/create_portal(obj/item/projectile/beam/wormhole/W)
|
||||
var/obj/effect/portal/P = new /obj/effect/portal(get_turf(W), null, src)
|
||||
P.precision = 0
|
||||
if(W.name == "bluespace beam")
|
||||
qdel(blue)
|
||||
blue = P
|
||||
else
|
||||
qdel(orange)
|
||||
/obj/item/weapon/gun/energy/wormhole_projector/proc/has_blue_portal()
|
||||
if(istype(p_blue) && !QDELETED(p_blue))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/weapon/gun/energy/wormhole_projector/proc/has_orange_portal()
|
||||
if(istype(p_orange) && !QDELETED(p_orange))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/weapon/gun/energy/wormhole_projector/proc/crosslink()
|
||||
if(!has_blue_portal() && !has_orange_portal())
|
||||
return
|
||||
if(!has_blue_portal() && has_orange_portal())
|
||||
p_orange.link_portal(null)
|
||||
return
|
||||
if(!has_orange_portal() && has_blue_portal())
|
||||
p_blue.link_portal(null)
|
||||
return
|
||||
p_orange.link_portal(p_blue)
|
||||
p_blue.link_portal(p_orange)
|
||||
|
||||
/obj/item/weapon/gun/energy/wormhole_projector/proc/create_portal(obj/item/projectile/beam/wormhole/W, turf/target)
|
||||
var/obj/effect/portal/P = new /obj/effect/portal(target, src, 300, null, FALSE, null)
|
||||
if(istype(W, /obj/item/projectile/beam/wormhole/orange))
|
||||
qdel(p_orange)
|
||||
p_orange = P
|
||||
P.icon_state = "portal1"
|
||||
orange = P
|
||||
if(orange && blue)
|
||||
blue.target = get_turf(orange)
|
||||
orange.target = get_turf(blue)
|
||||
|
||||
else
|
||||
qdel(p_blue)
|
||||
p_blue = P
|
||||
crosslink()
|
||||
|
||||
/* 3d printer 'pseudo guns' for borgs */
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
var/ricochets = 0
|
||||
var/ricochets_max = 2
|
||||
var/ricochet_chance = 30
|
||||
var/ignore_source_check = FALSE
|
||||
|
||||
var/damage = 10
|
||||
var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here
|
||||
@@ -138,8 +139,9 @@
|
||||
if(check_ricochet() && check_ricochet_flag(A) && ricochets < ricochets_max)
|
||||
ricochets++
|
||||
if(A.handle_ricochet(src))
|
||||
ignore_source_check = TRUE
|
||||
return FALSE
|
||||
if(firer && !ricochets)
|
||||
if(firer && !ignore_source_check)
|
||||
if(A == firer || (A == firer.loc && istype(A, /obj/mecha))) //cannot shoot yourself or your mech
|
||||
loc = A.loc
|
||||
return FALSE
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
return ..()
|
||||
if(!gun)
|
||||
qdel(src)
|
||||
gun.create_portal(src)
|
||||
gun.create_portal(src, get_turf(src))
|
||||
|
||||
/obj/item/projectile/bullet/frag12
|
||||
name ="explosive slug"
|
||||
|
||||
Reference in New Issue
Block a user