Landmark Shuttles (#8512)

The lifeless live again. Or in this case, what never actually lived here.

Ports Baystation12/Baystation12#17460 probably for real this time. What this allows us to do is create shuttles on runtime and make shuttles easier by just making landmarks and a shuttle instead of areas and shuttles. Also allows runtime landmark creation via flares or whatever AND allows shuttles to use different landmarks at will.

I removed most of the overmap stuff, I think. It shouldn't be hard to slam it in whenever we need to.

Changes:

    "Shuttle code has been completely reworked."
    "Shuttles can now be modified to have more than one destination."
    "Shuttles now have a takeoff sound."
    "You can now throw mobs against walls to damage them. A lot."
    "You now need a neckgrab to throw mobs."
    "BEING UNBUCKLED DURING SHUTTLE LAUNCH IS DANGEROUS! Don't do it."
    "Adminghosts can now interact with all shuttles."
This commit is contained in:
Matt Atlas
2020-04-05 21:15:31 +03:00
committed by GitHub
parent cf7fe3eff7
commit 2e5fdf970c
100 changed files with 15780 additions and 16628 deletions
+16 -20
View File
@@ -45,31 +45,27 @@
// Turf matches, add it.
. += T
// Moves the contents of this area to A. If turf_to_leave is defined, that type will be excluded from the area.
/area/proc/move_contents_to(area/A, turf_to_leave = null)
var/list/source_turfs = src.build_ordered_turf_list(turf_to_leave)
var/list/target_turfs = A.build_ordered_turf_list()
/area/proc/move_contents_to(var/area/A)
//Takes: Area.
//Returns: Nothing.
//Notes: Attempts to move the contents of one area to another area.
// Movement based on lower left corner.
ASSERT(source_turfs.len == target_turfs.len)
if(!A || !src) return
for (var/i = 1 to source_turfs.len)
var/turf/ST = source_turfs[i]
if (!ST) // Excluded turfs are null to keep the list ordered.
continue
var/list/turfs_src = get_area_turfs("\ref[src]")
if(istype(ST, /turf/unsimulated) || istype(ST, /turf/space))
ST.ChangeTurf(A.base_turf, 1, 0, 1)
if(!turfs_src.len)
return
var/turf/TT = ST.copy_turf(target_turfs[i])
//figure out a suitable origin - this assumes the shuttle areas are the exact same size and shape
//might be worth doing this with a shuttle core object instead of areas, in the future
var/src_origin = locate(src.x, src.y, src.z)
var/trg_origin = locate(A.x, A.y, A.z)
for (var/thing in ST)
var/atom/movable/AM = thing
AM.shuttle_move(TT)
ST.ChangeTurf(ST.baseturf)
TT.update_icon()
TT.update_above()
if(src_origin && trg_origin)
var/translation = get_turf_translation(src_origin, trg_origin, turfs_src)
translate_turfs(translation, null)
// Called when a movable area wants to move this object.
/atom/movable/proc/shuttle_move(turf/loc)
+102 -49
View File
@@ -1,55 +1,108 @@
//Takes: Area type as text string or as typepath OR an instance of the area.
//Returns: A list of all turfs in areas of that type of that type in the world.
/proc/get_area_turfs(areatype, var/list/predicates, target_z = 0, subtypes=TRUE)
if(istext(areatype))
areatype = text2path(areatype)
else if(isarea(areatype))
var/area/areatemp = areatype
areatype = areatemp.type
else if(!ispath(areatype))
return null
/*
List generation helpers
*/
/proc/get_filtered_areas(var/list/predicates = list(/proc/is_area_with_turf))
. = list()
if(!predicates)
return
if(!islist(predicates))
predicates = list(predicates)
for(var/area/A)
if(all_predicates_true(list(A), predicates))
. += A
var/list/turfs = list()
if(subtypes)
var/list/cache = typecacheof(areatype)
for(var/V in all_areas)
var/area/A = V
if(!cache[A.type])
continue
for(var/turf/T in A)
CHECK_TICK
if(target_z == 0 || target_z == T.z)
if (predicates && predicates.len)
var/predicates_true = TRUE
for (var/predicate in predicates)
if (!call(predicate)(T))
predicates_true = FALSE
break
if (predicates_true)
turfs += T
else
turfs += T
else
for(var/V in all_areas)
var/area/A = V
if(A.type != areatype)
continue
for(var/turf/T in A)
CHECK_TICK
if (target_z == 0 || target_z == T.z)
if (predicates && predicates.len)
var/predicates_true = TRUE
for (var/predicate in predicates)
if (!call(predicate)(T))
predicates_true = FALSE
break
if (predicates_true)
turfs += T
else
turfs += T
return turfs
/proc/get_area_turfs(var/area/A, var/list/predicates)
. = new/list()
A = istype(A) ? A : locate(A)
if(!A)
return
for(var/turf/T in A.contents)
if(!predicates || all_predicates_true(list(T), predicates))
. += T
/proc/get_subarea_turfs(var/area/A, var/list/predicates)
. = new/list()
A = istype(A) ? A.type : A
if(!ispath(A))
return
for(var/sub_area_type in typesof(A))
var/area/sub_area = locate(sub_area_type)
for(var/turf/T in sub_area.contents)
if(!predicates || all_predicates_true(list(T), predicates))
. += T
/proc/group_areas_by_name(var/list/predicates)
. = list()
for(var/area/A in get_filtered_areas(predicates))
group_by(., A.name, A)
/proc/group_areas_by_z_level(var/list/predicates)
. = list()
var/enough_digits_to_contain_all_zlevels = 3
for(var/area/A in get_filtered_areas(predicates))
group_by(., add_zero(num2text(A.z), enough_digits_to_contain_all_zlevels), A)
/*
Pick helpers
*/
/proc/pick_subarea_turf(var/areatype, var/list/predicates)
var/list/turfs = get_subarea_turfs(areatype, predicates)
if(LAZYLEN(turfs))
return pick(turfs)
/proc/pick_area(var/list/predicates)
var/list/areas = get_filtered_areas(predicates)
if(LAZYLEN(areas))
. = pick(areas)
/proc/pick_area_and_turf(var/list/area_predicates, var/list/turf_predicates)
var/list/areas = get_filtered_areas(area_predicates)
// We loop over all area candidates, until we finally get a valid turf or run out of areas
while(!. && length(areas))
var/area/A = pick_n_take(areas)
. = pick_area_turf(A, turf_predicates)
/proc/pick_area_turf_in_connected_z_levels(var/list/area_predicates, var/list/turf_predicates, var/z_level)
area_predicates = area_predicates.Copy()
var/z_levels = GetConnectedZlevels(z_level)
area_predicates[/proc/area_belongs_to_zlevels] = z_levels
return pick_area_and_turf(area_predicates, turf_predicates)
/proc/pick_area_turf(var/areatype, var/list/predicates)
var/list/turfs = get_area_turfs(areatype, predicates)
if(turfs && turfs.len)
return pick(turfs)
/*
Predicate Helpers
*/
/proc/area_belongs_to_zlevels(var/area/A, var/list/z_levels)
. = (A.z in z_levels)
/proc/is_station_area(var/area/A)
. = isStationLevel(A.z)
/proc/is_contact_area(var/area/A)
. = isContactLevel(A.z)
/proc/is_player_area(var/area/A)
. = isPlayerLevel(A.z)
/proc/is_not_space_area(var/area/A)
. = !istype(A,/area/space)
/proc/is_not_shuttle_area(var/area/A)
. = !istype(A,/area/shuttle)
/proc/is_area_with_turf(var/area/A)
. = isnum(A.x)
/proc/is_area_without_turf(var/area/A)
. = !is_area_with_turf(A)
/proc/is_maint_area(var/area/A)
. = istype(A,/area/maintenance)
/proc/is_not_maint_area(var/area/A)
. = !is_maint_area(A)
+14
View File
@@ -690,3 +690,17 @@
for(var/entry in L)
if(istype(entry, type))
. += entry
/proc/group_by(var/list/group_list, var/key, var/value)
var/values = group_list[key]
if(!values)
values = list()
group_list[key] = values
values += value
// Return a list of the values in an assoc list (including null)
/proc/list_values(var/list/L)
. = list()
for(var/e in L)
. += L[e]
+56
View File
@@ -95,3 +95,59 @@
if(pressure < SOUND_MINIMUM_PRESSURE)
return TRUE
return FALSE
/*
Turf manipulation
*/
//Returns an assoc list that describes how turfs would be changed if the
//turfs in turfs_src were translated by shifting the src_origin to the dst_origin
/proc/get_turf_translation(turf/src_origin, turf/dst_origin, list/turfs_src)
var/list/turf_map = list()
for(var/turf/source in turfs_src)
var/x_pos = (source.x - src_origin.x)
var/y_pos = (source.y - src_origin.y)
var/z_pos = (source.z - src_origin.z)
var/turf/target = locate(dst_origin.x + x_pos, dst_origin.y + y_pos, dst_origin.z + z_pos)
if(!target)
error("Null turf in translation @ ([dst_origin.x + x_pos], [dst_origin.y + y_pos], [dst_origin.z + z_pos])")
turf_map[source] = target //if target is null, preserve that information in the turf map
return turf_map
/proc/translate_turfs(var/list/translation, var/area/base_area = null, var/turf/base_turf)
for(var/turf/source in translation)
var/turf/target = translation[source]
if(target)
if(base_area)
ChangeArea(target, get_area(source))
ChangeArea(source, base_area)
transport_turf_contents(source, target)
//change the old turfs
for(var/turf/source in translation)
source.ChangeTurf(base_turf ? base_turf : get_base_turf_by_area(source), 1, 1)
//Transports a turf from a source turf to a target turf, moving all of the turf's contents and making the target a copy of the source.
/proc/transport_turf_contents(turf/source, turf/target)
var/turf/new_turf = target.ChangeTurf(source.type, 1, 1)
new_turf.transport_properties_from(source)
for(var/obj/O in source)
if(O.simulated)
O.forceMove(new_turf)
else if(istype(O,/obj/effect))
var/obj/effect/E = O
if(E.movable_flags & MOVABLE_FLAG_EFFECTMOVE)
E.forceMove(new_turf)
for(var/mob/M in source)
if(isEye(M)) continue // If we need to check for more mobs, I'll add a variable
M.forceMove(new_turf)
return new_turf