mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
[MIRROR] Add locking into portals with right click on hand tele, refactor hand tele code, add pre_attack_secondary (#3242)
* Add locking into portals with right click on hand tele, refactor hand tele code, add pre_attack_secondary (#56700) Refactors hand tele code with better variable names, splitting procs, fixing C&P code, etc. Adds pre_attack_secondary, the right click version of pre_attack. Adds a new alternate function to hand teles, which will reopen the last location you opened. Works based off locations, not turfs. For example, right clicking after locking in "None (Dangerous)" will not teleport you to the same place. * Add locking into portals with right click on hand tele, refactor hand tele code, add pre_attack_secondary Co-authored-by: Mothblocks <35135081+Jared-Fogle@users.noreply.github.com>
This commit is contained in:
@@ -554,6 +554,10 @@
|
||||
///from /obj/machinery/set_occupant(atom/movable/O): (new_occupant)
|
||||
#define COMSIG_MACHINERY_SET_OCCUPANT "machinery_set_occupant"
|
||||
|
||||
// /obj/machinery/computer/teleporter
|
||||
/// from /obj/machinery/computer/teleporter/proc/set_target(target, old_target)
|
||||
#define COMSIG_TELEPORTER_NEW_TARGET "teleporter_new_target"
|
||||
|
||||
// /obj/machinery/power/supermatter_crystal signals
|
||||
/// from /obj/machinery/power/supermatter_crystal/process_atmos(); when the SM delam reaches the point of sounding alarms
|
||||
#define COMSIG_SUPERMATTER_DELAM_START_ALARM "sm_delam_start_alarm"
|
||||
|
||||
2
code/__HELPERS/weakref.dm
Normal file
2
code/__HELPERS/weakref.dm
Normal file
@@ -0,0 +1,2 @@
|
||||
/// Checks if potential_weakref is a weakref of thing.
|
||||
#define IS_WEAKREF_OF(thing, potential_weakref) (istype(thing, /datum) && !isnull(potential_weakref) && thing.weak_reference == potential_weakref)
|
||||
@@ -13,7 +13,21 @@
|
||||
if(tool_behaviour && target.tool_act(user, src, tool_behaviour))
|
||||
return TRUE
|
||||
|
||||
if(pre_attack(target, user, params))
|
||||
var/pre_attack_result
|
||||
if (is_right_clicking)
|
||||
switch (pre_attack_secondary(target, user, params))
|
||||
if (SECONDARY_ATTACK_CALL_NORMAL)
|
||||
pre_attack_result = pre_attack(src, user, params)
|
||||
if (SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
|
||||
return TRUE
|
||||
if (SECONDARY_ATTACK_CONTINUE_CHAIN)
|
||||
// Normal behavior
|
||||
else
|
||||
CRASH("pre_attack_secondary must return an SECONDARY_ATTACK_* define, please consult code/__DEFINES/combat.dm")
|
||||
else
|
||||
pre_attack_result = pre_attack(src, user, params)
|
||||
|
||||
if(pre_attack_result)
|
||||
return TRUE
|
||||
|
||||
var/attackby_result
|
||||
@@ -24,7 +38,9 @@
|
||||
attackby_result = target.attackby(src, user, params)
|
||||
if (SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
|
||||
return TRUE
|
||||
if (null)
|
||||
if (SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
|
||||
// Normal behavior
|
||||
else
|
||||
CRASH("attackby_secondary must return an SECONDARY_ATTACK_* define, please consult code/__DEFINES/combat.dm")
|
||||
else
|
||||
attackby_result = target.attackby(src, user, params)
|
||||
@@ -66,6 +82,19 @@
|
||||
return TRUE
|
||||
return FALSE //return TRUE to avoid calling attackby after this proc does stuff
|
||||
|
||||
/**
|
||||
* Called on the item before it hits something, when right clicking.
|
||||
*
|
||||
* Arguments:
|
||||
* * atom/target - The atom about to be hit
|
||||
* * mob/living/user - The mob doing the htting
|
||||
* * params - click params such as alt/shift etc
|
||||
*
|
||||
* See: [/obj/item/proc/melee_attack_chain]
|
||||
*/
|
||||
/obj/item/proc/pre_attack_secondary(atom/target, mob/living/user, params)
|
||||
return SECONDARY_ATTACK_CALL_NORMAL
|
||||
|
||||
/**
|
||||
* Called on an object being hit by an item
|
||||
*
|
||||
|
||||
@@ -28,4 +28,3 @@
|
||||
/datum/weakref/proc/resolve()
|
||||
var/datum/D = locate(reference)
|
||||
return (!QDELETED(D) && D.weak_reference == src) ? D : null
|
||||
|
||||
|
||||
@@ -98,6 +98,12 @@
|
||||
addtimer(CALLBACK(src, .proc/finish_calibration), 50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/computer/teleporter/proc/set_teleport_target(new_target)
|
||||
if (target == new_target)
|
||||
return
|
||||
SEND_SIGNAL(src, COMSIG_TELEPORTER_NEW_TARGET, new_target)
|
||||
target = new_target
|
||||
|
||||
/obj/machinery/computer/teleporter/proc/finish_calibration()
|
||||
calibrating = FALSE
|
||||
if(check_hub_connection())
|
||||
@@ -115,7 +121,7 @@
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/teleporter/proc/reset_regime()
|
||||
target = null
|
||||
set_teleport_target(null)
|
||||
if(regime_set == "Teleporter")
|
||||
regime_set = "Gate"
|
||||
else
|
||||
@@ -145,7 +151,7 @@
|
||||
L[avoid_assoc_duplicate_keys("[M.real_name] ([get_area(M)])", areaindex)] = I
|
||||
|
||||
var/desc = input("Please select a location to lock in.", "Locking Computer") as null|anything in sortList(L)
|
||||
target = L[desc]
|
||||
set_teleport_target(L[desc])
|
||||
var/turf/T = get_turf(target)
|
||||
log_game("[key_name(user)] has set the teleporter target to [target] at [AREACOORD(T)]")
|
||||
|
||||
@@ -164,7 +170,7 @@
|
||||
return
|
||||
var/turf/T = get_turf(target_station)
|
||||
log_game("[key_name(user)] has set the teleporter target to [target_station] at [AREACOORD(T)]")
|
||||
target = target_station.teleporter_hub
|
||||
set_teleport_target(target_station.teleporter_hub)
|
||||
target_station.linked_stations |= power_station
|
||||
target_station.set_machine_stat(target_station.machine_stat & ~NOPOWER)
|
||||
if(target_station.teleporter_hub)
|
||||
|
||||
@@ -91,12 +91,15 @@
|
||||
data["trackimplants"] = track_implants
|
||||
return data
|
||||
|
||||
#define PORTAL_LOCATION_DANGEROUS "portal_location_dangerous"
|
||||
#define PORTAL_DANGEROUS_EDGE_LIMIT 8
|
||||
|
||||
/*
|
||||
* Hand-tele
|
||||
*/
|
||||
/obj/item/hand_tele
|
||||
name = "hand tele"
|
||||
desc = "A portable item using blue-space technology."
|
||||
desc = "A portable item using blue-space technology. One of the buttons opens a portal, the other re-opens your last destination."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "hand_tele"
|
||||
inhand_icon_state = "electronic"
|
||||
@@ -114,6 +117,15 @@
|
||||
var/max_portal_pairs = 3
|
||||
var/atmos_link_override
|
||||
|
||||
/**
|
||||
* Represents the last place we teleported to, for making quick portals.
|
||||
* Can be in the following states:
|
||||
* - null, meaning either this hand tele hasn't been used yet, or the last place it was portalled to was removed.
|
||||
* - PORTAL_LOCATION_DANGEROUS, meaning the last place it teleported to was the "None (Dangerous)" location.
|
||||
* - A weakref to a /obj/machinery/computer/teleporter, meaning the last place it teleported to was a pre-setup location.
|
||||
*/
|
||||
var/last_portal_location
|
||||
|
||||
/obj/item/hand_tele/Initialize()
|
||||
. = ..()
|
||||
active_portal_pairs = list()
|
||||
@@ -134,63 +146,134 @@
|
||||
try_dispel_portal(target, user)
|
||||
. = ..()
|
||||
|
||||
/obj/item/hand_tele/pre_attack_secondary(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
var/portal_location = last_portal_location
|
||||
|
||||
if (isweakref(portal_location))
|
||||
var/datum/weakref/last_portal_location_ref = last_portal_location
|
||||
portal_location = last_portal_location_ref.resolve()
|
||||
|
||||
if (isnull(portal_location))
|
||||
to_chat(user, "<span class='warning'>[src] flashes briefly. No target is locked in.</span>")
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
|
||||
try_create_portal_to(user, portal_location)
|
||||
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
|
||||
/obj/item/hand_tele/attack_self(mob/user)
|
||||
var/turf/current_location = get_turf(user)//What turf is the user on?
|
||||
var/area/current_area = current_location.loc
|
||||
if(!current_location || (current_area.area_flags & NOTELEPORT) || is_away_level(current_location.z) || !isturf(user.loc))//If turf was not found or they're on z level 2 or >7 which does not currently exist. or if user is not located on a turf
|
||||
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
|
||||
if (!can_teleport_notifies(user))
|
||||
return
|
||||
var/list/L = list()
|
||||
for(var/obj/machinery/computer/teleporter/com in GLOB.machines)
|
||||
if(com.target)
|
||||
var/area/A = get_area(com.target)
|
||||
if(!A || (A.area_flags & NOTELEPORT))
|
||||
|
||||
var/list/locations = list()
|
||||
for(var/obj/machinery/computer/teleporter/computer in GLOB.machines)
|
||||
if(!computer.target)
|
||||
continue
|
||||
if(com.power_station && com.power_station.teleporter_hub && com.power_station.engaged)
|
||||
L["[get_area(com.target)] (Active)"] = com.target
|
||||
var/area/computer_area = get_area(computer.target)
|
||||
if(!computer_area || (computer_area.area_flags & NOTELEPORT))
|
||||
continue
|
||||
if(computer.power_station?.teleporter_hub && computer.power_station.engaged)
|
||||
locations["[get_area(computer.target)] (Active)"] = computer
|
||||
else
|
||||
L["[get_area(com.target)] (Inactive)"] = com.target
|
||||
var/list/turfs = list()
|
||||
for(var/turf/T in urange(10, orange=1))
|
||||
if(T.x>world.maxx-8 || T.x<8)
|
||||
locations["[get_area(computer.target)] (Inactive)"] = computer
|
||||
|
||||
locations["None (Dangerous)"] = PORTAL_LOCATION_DANGEROUS
|
||||
|
||||
var/teleport_location_key = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") as null|anything in locations
|
||||
if (!teleport_location_key || user.get_active_held_item() != src || user.incapacitated())
|
||||
return
|
||||
|
||||
// Not always a datum, but needed for IS_WEAKREF_OF to cast properly.
|
||||
var/datum/teleport_location = locations[teleport_location_key]
|
||||
if (!try_create_portal_to(user, teleport_location))
|
||||
return
|
||||
|
||||
if (teleport_location == PORTAL_LOCATION_DANGEROUS)
|
||||
last_portal_location = PORTAL_LOCATION_DANGEROUS
|
||||
else if (!IS_WEAKREF_OF(teleport_location, last_portal_location))
|
||||
if (isweakref(teleport_location))
|
||||
var/datum/weakref/about_to_replace_location_ref = last_portal_location
|
||||
var/obj/machinery/computer/teleporter/about_to_replace_location = about_to_replace_location_ref.resolve()
|
||||
if (about_to_replace_location)
|
||||
UnregisterSignal(about_to_replace_location, COMSIG_TELEPORTER_NEW_TARGET)
|
||||
|
||||
RegisterSignal(teleport_location, COMSIG_TELEPORTER_NEW_TARGET, .proc/on_teleporter_new_target)
|
||||
|
||||
last_portal_location = WEAKREF(teleport_location)
|
||||
|
||||
/// Takes either PORTAL_LOCATION_DANGEROUS or an /obj/machinery/computer/teleport/computer.
|
||||
/obj/item/hand_tele/proc/try_create_portal_to(mob/user, teleport_location)
|
||||
if (active_portal_pairs.len >= max_portal_pairs)
|
||||
user.show_message("<span class='notice'>[src] is recharging!</span>")
|
||||
return
|
||||
|
||||
var/teleport_turf
|
||||
|
||||
if (teleport_location == PORTAL_LOCATION_DANGEROUS)
|
||||
var/list/dangerous_turfs = list()
|
||||
for(var/turf/dangerous_turf in urange(10, orange=1))
|
||||
if(dangerous_turf.x > world.maxx - PORTAL_DANGEROUS_EDGE_LIMIT || dangerous_turf.x < PORTAL_DANGEROUS_EDGE_LIMIT)
|
||||
continue //putting them at the edge is dumb
|
||||
if(T.y>world.maxy-8 || T.y<8)
|
||||
if(dangerous_turf.y > world.maxy - PORTAL_DANGEROUS_EDGE_LIMIT || dangerous_turf.y < PORTAL_DANGEROUS_EDGE_LIMIT)
|
||||
continue
|
||||
var/area/A = T.loc
|
||||
if(A.area_flags & NOTELEPORT)
|
||||
var/area/dangerous_area = dangerous_turf.loc
|
||||
if(dangerous_area.area_flags & NOTELEPORT)
|
||||
continue
|
||||
turfs += T
|
||||
if(turfs.len)
|
||||
L["None (Dangerous)"] = pick(turfs)
|
||||
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())
|
||||
dangerous_turfs += dangerous_turf
|
||||
|
||||
teleport_turf = pick(dangerous_turfs)
|
||||
else
|
||||
var/obj/machinery/computer/teleporter/computer = teleport_location
|
||||
teleport_turf = computer.target
|
||||
|
||||
if (teleport_turf == null)
|
||||
to_chat(user, "<span class='notice'>[src] vibrates, then stops. Maybe you should try something else.</span>")
|
||||
return
|
||||
if(active_portal_pairs.len >= max_portal_pairs)
|
||||
user.show_message("<span class='notice'>\The [src] is recharging!</span>")
|
||||
|
||||
var/area/teleport_area = get_area(teleport_turf)
|
||||
if (teleport_area.area_flags & NOTELEPORT)
|
||||
to_chat(user, "<span class='notice'>[src] is malfunctioning.</span>")
|
||||
return
|
||||
var/atom/T = L[t1]
|
||||
var/area/A = get_area(T)
|
||||
if(A.area_flags & NOTELEPORT)
|
||||
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
|
||||
|
||||
if (!can_teleport_notifies(user))
|
||||
return
|
||||
current_location = get_turf(user) //Recheck.
|
||||
current_area = current_location.loc
|
||||
if(!current_location || (current_area.area_flags & NOTELEPORT) || is_away_level(current_location.z) || !isturf(user.loc))//If turf was not found or they're on z level 2 or >7 which does not currently exist. or if user is not located on a turf
|
||||
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
|
||||
|
||||
var/list/obj/effect/portal/created = create_portal_pair(get_turf(user), get_teleport_turf(get_turf(teleport_turf)), 300, 1, null, atmos_link_override)
|
||||
if(LAZYLEN(created) != 2)
|
||||
return
|
||||
user.show_message("<span class='notice'>Locked In.</span>", MSG_AUDIBLE)
|
||||
var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), 300, 1, null, atmos_link_override)
|
||||
if(!(LAZYLEN(created) == 2))
|
||||
return
|
||||
RegisterSignal(created[1], COMSIG_PARENT_QDELETING, .proc/on_portal_destroy) //Gosh darn it kevinz.
|
||||
RegisterSignal(created[2], COMSIG_PARENT_QDELETING, .proc/on_portal_destroy)
|
||||
try_move_adjacent(created[1], user.dir)
|
||||
active_portal_pairs[created[1]] = created[2]
|
||||
var/obj/effect/portal/c1 = created[1]
|
||||
var/obj/effect/portal/c2 = created[2]
|
||||
investigate_log("was used by [key_name(user)] at [AREACOORD(user)] to create a portal pair with destinations [AREACOORD(c1)] and [AREACOORD(c2)].", INVESTIGATE_PORTAL)
|
||||
|
||||
var/obj/effect/portal/portal1 = created[1]
|
||||
var/obj/effect/portal/portal2 = created[2]
|
||||
|
||||
RegisterSignal(portal1, COMSIG_PARENT_QDELETING, .proc/on_portal_destroy)
|
||||
RegisterSignal(portal2, COMSIG_PARENT_QDELETING, .proc/on_portal_destroy)
|
||||
|
||||
try_move_adjacent(portal1, user.dir)
|
||||
active_portal_pairs[portal1] = portal2
|
||||
|
||||
investigate_log("was used by [key_name(user)] at [AREACOORD(user)] to create a portal pair with destinations [AREACOORD(portal1)] and [AREACOORD(portal2)].", INVESTIGATE_PORTAL)
|
||||
add_fingerprint(user)
|
||||
|
||||
user.show_message("<span class='notice'>Locked in.</span>", MSG_AUDIBLE)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/hand_tele/proc/can_teleport_notifies(mob/user)
|
||||
var/turf/current_location = get_turf(user)
|
||||
var/area/current_area = current_location.loc
|
||||
if (!current_location || (current_area.area_flags & NOTELEPORT) || is_away_level(current_location.z) || !isturf(user.loc))
|
||||
to_chat(user, "<span class='notice'>[src] is malfunctioning.</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/hand_tele/proc/on_teleporter_new_target(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (IS_WEAKREF_OF(source, last_portal_location))
|
||||
last_portal_location = null
|
||||
UnregisterSignal(source, COMSIG_TELEPORTER_NEW_TARGET)
|
||||
|
||||
/obj/item/hand_tele/proc/on_portal_destroy(obj/effect/portal/P)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -219,3 +302,6 @@
|
||||
else
|
||||
itemUser.visible_message("<span class='suicide'>[user] looks even further depressed as they realize they do not have a head...and suddenly dies of shame!</span>")
|
||||
return (BRUTELOSS)
|
||||
|
||||
#undef PORTAL_LOCATION_DANGEROUS
|
||||
#undef PORTAL_DANGEROUS_EDGE_LIMIT
|
||||
|
||||
@@ -208,6 +208,7 @@
|
||||
#include "code\__HELPERS\unsorted.dm"
|
||||
#include "code\__HELPERS\verbs.dm"
|
||||
#include "code\__HELPERS\view.dm"
|
||||
#include "code\__HELPERS\weakref.dm"
|
||||
#include "code\__HELPERS\sorts\__main.dm"
|
||||
#include "code\__HELPERS\sorts\InsertSort.dm"
|
||||
#include "code\__HELPERS\sorts\MergeSort.dm"
|
||||
|
||||
Reference in New Issue
Block a user