-
-
Notifications
You must be signed in to change notification settings - Fork 444
/
Copy path_teleport.dm
145 lines (117 loc) · 5.19 KB
/
_teleport.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
* ## Teleport Spell
*
* Teleports the caster to a turf selected by get_destinations().
*/
/datum/action/cooldown/spell/teleport
sound = 'sound/weapons/zapbang.ogg'
school = SCHOOL_TRANSLOCATION
/// What channel the teleport is done under.
var/teleport_channel = TELEPORT_CHANNEL_MAGIC
/// Whether we force the teleport to happen (ie, it cannot be blocked by noteleport areas or blessings or whatever)
var/force_teleport = FALSE
/// A list of flags related to determining if our destination target is valid or not.
var/destination_flags = NONE
/// The sound played on arrival, after the teleport.
var/post_teleport_sound = 'sound/weapons/zapbang.ogg'
/datum/action/cooldown/spell/teleport/cast(atom/cast_on)
. = ..()
var/list/turf/destinations = get_destinations(cast_on)
if(!length(destinations))
CRASH("[type] failed to find a teleport destination.")
do_teleport(cast_on, pick(destinations), asoundout = post_teleport_sound, channel = teleport_channel, forced = force_teleport)
/// Gets a list of destinations that are valid
/datum/action/cooldown/spell/teleport/proc/get_destinations(atom/center)
CRASH("[type] did not implement get_destinations and either has no effects or implemented the spell incorrectly.")
/// Checks if the passed turf is a valid destination.
/datum/action/cooldown/spell/teleport/proc/is_valid_destination(turf/selected)
if(isspaceturf(selected) && (destination_flags & TELEPORT_SPELL_SKIP_SPACE))
return FALSE
if(selected.density && (destination_flags & TELEPORT_SPELL_SKIP_DENSE))
return FALSE
if(selected.is_blocked_turf(exclude_mobs = TRUE) && (destination_flags & TELEPORT_SPELL_SKIP_BLOCKED))
return FALSE
return TRUE
/**
* ### Radius Teleport Spell
*
* A subtype of teleport that will teleport the caster
* to a random turf within a radius of themselves.
*/
/datum/action/cooldown/spell/teleport/radius_turf
/// The inner radius around the caster that we can teleport to
var/inner_tele_radius = 1
/// The outer radius around the caster that we can teleport to
var/outer_tele_radius = 2
/datum/action/cooldown/spell/teleport/radius_turf/get_destinations(atom/center)
var/list/valid_turfs = list()
var/list/possibles = RANGE_TURFS(outer_tele_radius, center)
if(inner_tele_radius > 0)
possibles -= RANGE_TURFS(inner_tele_radius, center)
for(var/turf/nearby_turf as anything in possibles)
if(!is_valid_destination(nearby_turf))
continue
valid_turfs += nearby_turf
// If there are valid turfs around us?
// Screw it, allow 'em to teleport to ANY nearby turf.
return length(valid_turfs) ? valid_turfs : possibles
/datum/action/cooldown/spell/teleport/radius_turf/is_valid_destination(turf/selected)
. = ..()
if(!.)
return FALSE
// putting them at the edge is dumb
if(selected.x > world.maxx - outer_tele_radius || selected.x < outer_tele_radius)
return FALSE
if(selected.y > world.maxy - outer_tele_radius || selected.y < outer_tele_radius)
return FALSE
return TRUE
/**
* ### Area Teleport Spell
*
* A subtype of teleport that will teleport the caster
* to a random turf within a selected (or random) area.
*/
/datum/action/cooldown/spell/teleport/area_teleport
force_teleport = TRUE // Forced, as the Wizard Den is noteleport and wizards couldn't escape otherwise.
destination_flags = TELEPORT_SPELL_SKIP_BLOCKED
/// The last area we chose to teleport / where we're currently teleporting to, if mid-cast
var/last_chosen_area_name
/// If FALSE, the caster can select the destination area. If TRUE, they will teleport to somewhere randomly instead.
var/randomise_selection = FALSE
/// If the invocation appends the selected area when said. Requires invocation mode shout or whisper.
var/invocation_says_area = TRUE
/datum/action/cooldown/spell/teleport/area_teleport/get_destinations(atom/center)
var/list/valid_turfs = list()
for(var/turf/possible_destination as anything in get_area_turfs(GLOB.teleportlocs[last_chosen_area_name]))
if(!is_valid_destination(possible_destination))
continue
valid_turfs += possible_destination
return valid_turfs
/datum/action/cooldown/spell/teleport/area_teleport/before_cast(atom/cast_on)
. = ..()
if(. & SPELL_CANCEL_CAST)
return
var/area/target_area
if(randomise_selection)
target_area = pick(GLOB.teleportlocs)
else
target_area = tgui_input_list(cast_on, "Chose an area to teleport to.", "Teleport", GLOB.teleportlocs)
if(QDELETED(src) || QDELETED(cast_on) || !can_cast_spell())
return . | SPELL_CANCEL_CAST
if(!target_area || isnull(GLOB.teleportlocs[target_area]))
return . | SPELL_CANCEL_CAST
last_chosen_area_name = target_area
/datum/action/cooldown/spell/teleport/area_teleport/cast(atom/cast_on)
if(isliving(cast_on))
var/mob/living/living_cast_on = cast_on
living_cast_on.buckled?.unbuckle_mob(cast_on, force = TRUE)
return ..()
/datum/action/cooldown/spell/teleport/area_teleport/invocation()
var/area/last_chosen_area = GLOB.teleportlocs[last_chosen_area_name]
if(!invocation_says_area || isnull(last_chosen_area))
return ..()
switch(invocation_type)
if(INVOCATION_SHOUT)
owner.say("[invocation], [uppertext(last_chosen_area.name)]!", forced = "spell ([src])")
if(INVOCATION_WHISPER)
owner.whisper("[invocation], [uppertext(last_chosen_area.name)].", forced = "spell ([src])")