mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
Up to date timesort to resolve list issues.
This commit is contained in:
@@ -31,29 +31,28 @@
|
||||
return "[output][and_text][input[index]]"
|
||||
|
||||
//Returns list element or null. Should prevent "index out of bounds" error.
|
||||
proc/listgetindex(var/list/list,index)
|
||||
if(istype(list) && list.len)
|
||||
/proc/listgetindex(list/L, index)
|
||||
if(istype(L))
|
||||
if(isnum(index))
|
||||
if(IsInRange(index,1,list.len))
|
||||
return list[index]
|
||||
else if(index in list)
|
||||
return list[index]
|
||||
if(IsInRange(index,1,L.len))
|
||||
return L[index]
|
||||
else if(index in L)
|
||||
return L[index]
|
||||
return
|
||||
|
||||
proc/islist(list/list)
|
||||
if(istype(list))
|
||||
/proc/islist(list/L)
|
||||
if(istype(L))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//Return either pick(list) or null if list is not of type /list or is empty
|
||||
proc/safepick(list/list)
|
||||
if(!islist(list) || !list.len)
|
||||
return
|
||||
return pick(list)
|
||||
/proc/safepick(list/L)
|
||||
if(istype(L) && L.len)
|
||||
return pick(L)
|
||||
|
||||
//Checks if the list is empty
|
||||
proc/isemptylist(list/list)
|
||||
if(!list.len)
|
||||
/proc/isemptylist(list/L)
|
||||
if(!L.len)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -65,17 +64,20 @@ proc/isemptylist(list/list)
|
||||
return 0
|
||||
|
||||
//Empties the list by setting the length to 0. Hopefully the elements get garbage collected
|
||||
proc/clearlist(list/list)
|
||||
/proc/clearlist(list/list)
|
||||
if(istype(list))
|
||||
list.len = 0
|
||||
return
|
||||
|
||||
//Removes any null entries from the list
|
||||
proc/listclearnulls(list/list)
|
||||
if(istype(list))
|
||||
while(null in list)
|
||||
list -= null
|
||||
return
|
||||
/proc/listclearnulls(list/L)
|
||||
if(istype(L))
|
||||
var/i=1
|
||||
for(var/thing in L)
|
||||
if(thing != null)
|
||||
++i
|
||||
continue
|
||||
L.Cut(i,i+1)
|
||||
|
||||
/*
|
||||
* Returns list containing all the entries from first list that are not present in second.
|
||||
@@ -127,21 +129,43 @@ proc/listclearnulls(list/list)
|
||||
return null
|
||||
|
||||
//Pick a random element from the list and remove it from the list.
|
||||
/proc/pick_n_take(list/listfrom)
|
||||
if (listfrom.len > 0)
|
||||
var/picked = pick(listfrom)
|
||||
listfrom -= picked
|
||||
return picked
|
||||
return null
|
||||
/proc/pick_n_take(list/L)
|
||||
if(L.len)
|
||||
var/picked = rand(1,L.len)
|
||||
. = L[picked]
|
||||
L.Cut(picked,picked+1) //Cut is far more efficient that Remove()
|
||||
|
||||
//Returns the top(last) element from the list and removes it from the list (typical stack function)
|
||||
/proc/pop(list/listfrom)
|
||||
if (listfrom.len > 0)
|
||||
var/picked = listfrom[listfrom.len]
|
||||
listfrom.len--
|
||||
return picked
|
||||
return null
|
||||
/proc/pop(list/L)
|
||||
if(L.len)
|
||||
. = L[L.len]
|
||||
L.len--
|
||||
|
||||
/proc/sorted_insert(list/L, thing, comparator)
|
||||
var/pos = L.len
|
||||
while(pos > 0 && call(comparator)(thing, L[pos]) > 0)
|
||||
pos--
|
||||
L.Insert(pos+1, thing)
|
||||
|
||||
// Returns the next item in a list
|
||||
/proc/next_list_item(var/item, var/list/L)
|
||||
var/i
|
||||
i = L.Find(item)
|
||||
if(i == L.len)
|
||||
i = 1
|
||||
else
|
||||
i++
|
||||
return L[i]
|
||||
|
||||
// Returns the previous item in a list
|
||||
/proc/previous_list_item(var/item, var/list/L)
|
||||
var/i
|
||||
i = L.Find(item)
|
||||
if(i == 1)
|
||||
i = L.len
|
||||
else
|
||||
i--
|
||||
return L[i]
|
||||
|
||||
/*
|
||||
* Sorting
|
||||
@@ -165,6 +189,7 @@ proc/listclearnulls(list/list)
|
||||
L.Swap(i,rand(1,L.len))
|
||||
|
||||
return L
|
||||
|
||||
//Return a list with no duplicate entries
|
||||
/proc/uniquelist(var/list/L)
|
||||
var/list/K = list()
|
||||
@@ -184,39 +209,12 @@ proc/listclearnulls(list/list)
|
||||
|
||||
//any value in a list
|
||||
/proc/sortList(var/list/L, cmp=/proc/cmp_text_asc)
|
||||
if(!istype(L))
|
||||
return
|
||||
return sortTim(L.Copy(), cmp)
|
||||
|
||||
//uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead
|
||||
/proc/sortNames(var/list/L, order=1)
|
||||
return sortTim(L, order >= 0 ? /proc/cmp_name_asc : /proc/cmp_name_dsc)
|
||||
|
||||
//Mergesort: divides up the list into halves to begin the sort
|
||||
/proc/sortAtom(var/list/atom/L, var/order = 1)
|
||||
if(isnull(L) || L.len < 2)
|
||||
return L
|
||||
var/middle = L.len / 2 + 1
|
||||
return mergeAtoms(sortAtom(L.Copy(0,middle)), sortAtom(L.Copy(middle)), order)
|
||||
|
||||
//Mergsort: does the actual sorting and returns the results back to sortAtom
|
||||
/proc/mergeAtoms(var/list/atom/L, var/list/atom/R, var/order = 1)
|
||||
var/Li=1
|
||||
var/Ri=1
|
||||
ASSERT(L)
|
||||
ASSERT(R)
|
||||
var/list/result = new()
|
||||
while(Li <= L.len && Ri <= R.len)
|
||||
var/atom/rL = L[Li]
|
||||
var/atom/rR = R[Ri]
|
||||
if(sorttext(rL.name, rR.name) == order)
|
||||
result += L[Li++]
|
||||
else
|
||||
result += R[Ri++]
|
||||
|
||||
if(Li <= L.len)
|
||||
return (result + L.Copy(Li, 0))
|
||||
return (result + R.Copy(Ri, 0))
|
||||
|
||||
//Converts a bitfield to a list of numbers (or words if a wordlist is provided)
|
||||
/proc/bitfield2list(bitfield = 0, list/wordlist)
|
||||
@@ -251,104 +249,38 @@ proc/listclearnulls(list/list)
|
||||
i++
|
||||
return i
|
||||
|
||||
//Don't use this on lists larger than half a dozen or so
|
||||
/proc/insertion_sort_numeric_list_ascending(var/list/L)
|
||||
//world.log << "ascending len input: [L.len]"
|
||||
var/list/out = list(pop(L))
|
||||
for(var/entry in L)
|
||||
if(isnum(entry))
|
||||
var/success = 0
|
||||
for(var/i=1, i<=out.len, i++)
|
||||
if(entry <= out[i])
|
||||
success = 1
|
||||
out.Insert(i, entry)
|
||||
break
|
||||
if(!success)
|
||||
out.Add(entry)
|
||||
|
||||
//world.log << " output: [out.len]"
|
||||
return out
|
||||
|
||||
/proc/insertion_sort_numeric_list_descending(var/list/L)
|
||||
//world.log << "descending len input: [L.len]"
|
||||
var/list/out = insertion_sort_numeric_list_ascending(L)
|
||||
//world.log << " output: [out.len]"
|
||||
return reverseRange(out)
|
||||
|
||||
// List of lists, sorts by element[key] - for things like crew monitoring computer sorting records by name.
|
||||
/proc/sortByKey(var/list/L, var/key)
|
||||
if(L.len < 2)
|
||||
return L
|
||||
var/middle = L.len / 2 + 1
|
||||
return mergeKeyedLists(sortByKey(L.Copy(0, middle), key), sortByKey(L.Copy(middle), key), key)
|
||||
|
||||
/proc/mergeKeyedLists(var/list/L, var/list/R, var/key)
|
||||
var/Li=1
|
||||
var/Ri=1
|
||||
var/list/result = new()
|
||||
while(Li <= L.len && Ri <= R.len)
|
||||
if(sorttext(L[Li][key], R[Ri][key]) < 1)
|
||||
// Works around list += list2 merging lists; it's not pretty but it works
|
||||
result += "temp item"
|
||||
result[result.len] = R[Ri++]
|
||||
else
|
||||
result += "temp item"
|
||||
result[result.len] = L[Li++]
|
||||
|
||||
if(Li <= L.len)
|
||||
return (result + L.Copy(Li, 0))
|
||||
return (result + R.Copy(Ri, 0))
|
||||
|
||||
|
||||
//Mergesort: any value in a list, preserves key=value structure
|
||||
/proc/sortAssoc(var/list/L)
|
||||
if(L.len < 2)
|
||||
return L
|
||||
var/middle = L.len / 2 + 1 // Copy is first,second-1
|
||||
return mergeAssoc(sortAssoc(L.Copy(0,middle)), sortAssoc(L.Copy(middle))) //second parameter null = to end of list
|
||||
|
||||
/proc/mergeAssoc(var/list/L, var/list/R)
|
||||
var/Li=1
|
||||
var/Ri=1
|
||||
var/list/result = new()
|
||||
while(Li <= L.len && Ri <= R.len)
|
||||
if(sorttext(L[Li], R[Ri]) < 1)
|
||||
result += R&R[Ri++]
|
||||
else
|
||||
result += L&L[Li++]
|
||||
|
||||
if(Li <= L.len)
|
||||
return (result + L.Copy(Li, 0))
|
||||
return (result + R.Copy(Ri, 0))
|
||||
|
||||
/proc/find_record(field, value, list/L)
|
||||
for(var/datum/data/record/R in L)
|
||||
if(R.fields[field] == value)
|
||||
return R
|
||||
|
||||
|
||||
//Move a single element from position fromIndex within a list, to position toIndex
|
||||
//All elements in the range [1,toIndex) before the move will be before the pivot afterwards
|
||||
//All elements in the range [toIndex, L.len+1) before the move will be after the pivot afterwards
|
||||
//In other words, it's as if the range [fromIndex,toIndex) have been rotated using a <<< operation common to other languages.
|
||||
//fromIndex and toIndex must be in the range [1,L.len+1]
|
||||
//This will preserve associations ~Carnie
|
||||
/proc/moveElement(list/L, fromIndex, toIndex)
|
||||
if(fromIndex == toIndex || fromIndex+1 == toIndex) //no need to move
|
||||
return
|
||||
if(fromIndex > toIndex)
|
||||
++fromIndex
|
||||
else
|
||||
++toIndex
|
||||
++fromIndex //since a null will be inserted before fromIndex, the index needs to be nudged right by one
|
||||
|
||||
L.Insert(toIndex, null)
|
||||
L.Swap(fromIndex, toIndex)
|
||||
L.Cut(fromIndex, fromIndex+1)
|
||||
|
||||
|
||||
//Move elements [fromIndex,fromIndex+len) to [toIndex,toIndex+len)
|
||||
//This will preserve associations and is much faster than copying to a new list
|
||||
//or checking for associative lists and manually copying elements ~Carnie
|
||||
//Move elements [fromIndex,fromIndex+len) to [toIndex-len, toIndex)
|
||||
//Same as moveElement but for ranges of elements
|
||||
//This will preserve associations ~Carnie
|
||||
/proc/moveRange(list/L, fromIndex, toIndex, len=1)
|
||||
var/distance = abs(toIndex - fromIndex)
|
||||
if(len > distance) //there are more elements to be moved than the distance to be moved. Therefore the same result can be achieved (with fewer operations) by moving elements between where we are and where we are going
|
||||
if(fromIndex < toIndex)
|
||||
toIndex += len
|
||||
else
|
||||
fromIndex += len
|
||||
if(len >= distance) //there are more elements to be moved than the distance to be moved. Therefore the same result can be achieved (with fewer operations) by moving elements between where we are and where we are going. The result being, our range we are moving is shifted left or right by dist elements
|
||||
if(fromIndex <= toIndex)
|
||||
return //no need to move
|
||||
fromIndex += len //we want to shift left instead of right
|
||||
|
||||
for(var/i=0, i<distance, ++i)
|
||||
L.Insert(fromIndex, null)
|
||||
@@ -357,8 +289,6 @@ proc/listclearnulls(list/list)
|
||||
else
|
||||
if(fromIndex > toIndex)
|
||||
fromIndex += len
|
||||
else
|
||||
toIndex += len //?
|
||||
|
||||
for(var/i=0, i<len, ++i)
|
||||
L.Insert(toIndex, null)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//These are macros used to reduce on proc calls
|
||||
#define moveElement(L, fromIndex, toIndex) if((fromIndex) > (toIndex)){L.Insert((toIndex), null);L.Swap((fromIndex)+1, (toIndex));L.Cut((fromIndex)+1, (fromIndex)+2);}else{L.Insert((toIndex)+1, null);L.Swap((fromIndex), (toIndex)+1);L.Cut((fromIndex), (fromIndex)+1);}
|
||||
#define fetchElement(L, i) (associative) ? L[L[i]] : L[i]
|
||||
|
||||
//Minimum sized sequence that will be merged. Anything smaller than this will use binary-insertion sort.
|
||||
@@ -34,8 +33,8 @@ var/datum/sortInstance/sortInstance = new()
|
||||
|
||||
|
||||
proc/timSort(start, end)
|
||||
runBases.len = 0
|
||||
runLens.len = 0
|
||||
runBases.Cut()
|
||||
runLens.Cut()
|
||||
|
||||
var/remaining = end - start
|
||||
|
||||
@@ -115,7 +114,7 @@ var/datum/sortInstance/sortInstance = new()
|
||||
//in other words, find where the pivot element should go using bisection search
|
||||
while(left < right)
|
||||
var/mid = (left + right) >> 1 //round((left+right)/2)
|
||||
if(call(cmp)(pivot, fetchElement(L,mid)) < 0)
|
||||
if(call(cmp)(fetchElement(L,mid), pivot) > 0)
|
||||
right = mid
|
||||
else
|
||||
left = mid+1
|
||||
@@ -372,23 +371,23 @@ var/datum/sortInstance/sortInstance = new()
|
||||
proc/mergeLo(base1, len1, base2, len2)
|
||||
//ASSERT(len1 > 0 && len2 > 0 && base1 + len1 == base2)
|
||||
|
||||
var/cursor1 = base1
|
||||
var/cursor2 = base2
|
||||
|
||||
//degenerate cases
|
||||
if(len2 == 1)
|
||||
moveElement(L, base2, base1)
|
||||
moveElement(L, cursor2, cursor1)
|
||||
return
|
||||
|
||||
if(len1 == 1)
|
||||
moveElement(L, base1, base2+len2-1)
|
||||
moveElement(L, cursor1, cursor2+len2)
|
||||
return
|
||||
|
||||
|
||||
//Move first element of second run
|
||||
moveElement(L, base2, base1) //L[dest++] = L[cursor2++]
|
||||
moveElement(L, cursor2++, cursor1++)
|
||||
--len2
|
||||
|
||||
var/cursor1 = base1+1
|
||||
var/cursor2 = base2+1
|
||||
|
||||
outer:
|
||||
while(1)
|
||||
var/count1 = 0 //# of times in a row that first run won
|
||||
@@ -399,9 +398,7 @@ var/datum/sortInstance/sortInstance = new()
|
||||
do
|
||||
//ASSERT(len1 > 1 && len2 > 0)
|
||||
if(call(cmp)(fetchElement(L,cursor2), fetchElement(L,cursor1)) < 0)
|
||||
moveElement(L, cursor2, cursor1)
|
||||
++cursor2
|
||||
++cursor1
|
||||
moveElement(L, cursor2++, cursor1++)
|
||||
--len2
|
||||
|
||||
++count2
|
||||
@@ -466,8 +463,7 @@ var/datum/sortInstance/sortInstance = new()
|
||||
|
||||
if(len1 == 1)
|
||||
//ASSERT(len2 > 0)
|
||||
|
||||
moveRange(L, cursor2, cursor1, len2)
|
||||
moveElement(L, cursor1, cursor2+len2)
|
||||
|
||||
//else
|
||||
//ASSERT(len2 == 0)
|
||||
@@ -477,22 +473,20 @@ var/datum/sortInstance/sortInstance = new()
|
||||
proc/mergeHi(base1, len1, base2, len2)
|
||||
//ASSERT(len1 > 0 && len2 > 0 && base1 + len1 == base2)
|
||||
|
||||
var/cursor1 = base1 + len1 - 1 //start at end of sublists
|
||||
var/cursor2 = base2 + len2 - 1
|
||||
|
||||
//degenerate cases
|
||||
if(len2 == 1)
|
||||
moveElement(L, base2, base1)
|
||||
return
|
||||
|
||||
if(len1 == 1)
|
||||
moveElement(L, base1, base2+len2-1)
|
||||
moveElement(L, base1, cursor2+1)
|
||||
return
|
||||
|
||||
var/cursor1 = base1 + len1 - 1
|
||||
var/cursor2 = base2 + len2 - 1
|
||||
|
||||
moveElement(L, cursor1, cursor2)
|
||||
moveElement(L, cursor1--, cursor2-- + 1)
|
||||
--len1
|
||||
--cursor1
|
||||
--cursor2
|
||||
|
||||
outer:
|
||||
while(1)
|
||||
@@ -503,10 +497,7 @@ var/datum/sortInstance/sortInstance = new()
|
||||
do
|
||||
//ASSERT(len1 > 0 && len2 > 1)
|
||||
if(call(cmp)(fetchElement(L,cursor2), fetchElement(L,cursor1)) < 0)
|
||||
moveElement(L, cursor1, cursor2)
|
||||
|
||||
--cursor1
|
||||
--cursor2
|
||||
moveElement(L, cursor1--, cursor2-- + 1)
|
||||
--len1
|
||||
|
||||
++count1
|
||||
@@ -533,11 +524,12 @@ var/datum/sortInstance/sortInstance = new()
|
||||
count1 = len1 - gallopRight(fetchElement(L,cursor2), base1, len1, len1-1) //should cursor1 be base1?
|
||||
if(count1)
|
||||
cursor1 -= count1
|
||||
|
||||
moveRange(L, cursor1+1, cursor2+1, count1) //cursor1+1 == cursor2 by definition
|
||||
|
||||
cursor2 -= count1
|
||||
len1 -= count1
|
||||
|
||||
moveRange(L, cursor1+1, cursor2+1, count1)
|
||||
|
||||
if(len1 == 0)
|
||||
break outer
|
||||
|
||||
@@ -546,7 +538,7 @@ var/datum/sortInstance/sortInstance = new()
|
||||
if(--len2 == 1)
|
||||
break outer
|
||||
|
||||
count2 = len2 - gallopLeft(fetchElement(L,cursor1), base1+len1, len2, len2-1)
|
||||
count2 = len2 - gallopLeft(fetchElement(L,cursor1), cursor1+1, len2, len2-1)
|
||||
if(count2)
|
||||
cursor2 -= count2
|
||||
len2 -= count2
|
||||
@@ -554,9 +546,7 @@ var/datum/sortInstance/sortInstance = new()
|
||||
if(len2 <= 1)
|
||||
break outer
|
||||
|
||||
moveElement(L, cursor1, cursor2)
|
||||
--cursor1
|
||||
--cursor2
|
||||
moveElement(L, cursor1--, cursor2-- + 1)
|
||||
--len1
|
||||
|
||||
if(len1 == 0)
|
||||
@@ -573,7 +563,6 @@ var/datum/sortInstance/sortInstance = new()
|
||||
//ASSERT(len1 > 0)
|
||||
|
||||
cursor1 -= len1
|
||||
cursor2 -= len1
|
||||
moveRange(L, cursor1+1, cursor2+1, len1)
|
||||
|
||||
//else
|
||||
@@ -664,5 +653,4 @@ var/datum/sortInstance/sortInstance = new()
|
||||
#undef MIN_GALLOP
|
||||
#undef MIN_MERGE
|
||||
|
||||
#undef moveElement
|
||||
#undef fetchElement
|
||||
@@ -69,7 +69,7 @@
|
||||
. = "[ls[++i]]" // Make sure the initial element is converted to text.
|
||||
|
||||
if(l-1 & 0x01) // 'i' will always be 1 here.
|
||||
. += S1 // Append 1 element if the remaining elements are not a multiple of 2.
|
||||
. += "[S1]" // Append 1 element if the remaining elements are not a multiple of 2.
|
||||
if(l-i & 0x02)
|
||||
. = text("[][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4.
|
||||
if(l-i & 0x04)
|
||||
|
||||
@@ -424,7 +424,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
|
||||
//Orders mobs by type then by name
|
||||
/proc/sortmobs()
|
||||
var/list/moblist = list()
|
||||
var/list/sortmob = sortAtom(mob_list)
|
||||
var/list/sortmob = sortNames(mob_list)
|
||||
for(var/mob/living/silicon/ai/M in sortmob)
|
||||
moblist.Add(M)
|
||||
for(var/mob/camera/M in sortmob)
|
||||
@@ -767,16 +767,21 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl
|
||||
if(A.vars.Find(lowertext(varname))) return 1
|
||||
else return 0
|
||||
|
||||
//Returns: all the areas in the world
|
||||
/proc/return_areas()
|
||||
var/list/area/areas = list()
|
||||
//Returns sortedAreas list if populated
|
||||
//else populates the list first before returning it
|
||||
/proc/SortAreas()
|
||||
for(var/area/A in world)
|
||||
areas += A
|
||||
return areas
|
||||
if(A.lighting_subarea)
|
||||
continue
|
||||
sortedAreas.Add(A)
|
||||
|
||||
//Returns: all the areas in the world, sorted.
|
||||
/proc/return_sorted_areas()
|
||||
return sortNames(return_areas())
|
||||
sortTim(sortedAreas, /proc/cmp_name_asc)
|
||||
|
||||
|
||||
|
||||
/area/proc/addSorted()
|
||||
sortedAreas.Add(src)
|
||||
sortTim(sortedAreas, /proc/cmp_name_asc)
|
||||
|
||||
//Takes: Area type as text string or as typepath OR an instance of the area.
|
||||
//Returns: A list of all areas of that type in the world.
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
"}
|
||||
var/even = 0
|
||||
// sort mobs
|
||||
for(var/datum/data/record/t in data_core.general)
|
||||
for(var/datum/data/record/t in sortRecord(data_core.general))
|
||||
var/name = t.fields["name"]
|
||||
var/rank = t.fields["rank"]
|
||||
var/real_rank = t.fields["real_rank"]
|
||||
|
||||
@@ -79,26 +79,12 @@ proc/process_teleport_locs()
|
||||
for(var/area/AR in world)
|
||||
if(istype(AR, /area/shuttle) || istype(AR, /area/syndicate_station) || istype(AR, /area/wizard_station)) continue
|
||||
if(teleportlocs.Find(AR.name)) continue
|
||||
var/list/turfss = get_area_turfs(AR.type)
|
||||
if(!istype(turfss) || !turfss.len)
|
||||
//warning("Area [AR] had no turfs!")
|
||||
continue
|
||||
//testing("Picking a turf from [AR]/([AR.type]) turfs length [turfss.len]")
|
||||
var/turf/picked = pick(get_area_turfs(AR.type))
|
||||
if (picked.z == 1)
|
||||
var/turf/picked = safepick(get_area_turfs(AR.type))
|
||||
if (picked && picked.z == 1)
|
||||
teleportlocs += AR.name
|
||||
teleportlocs[AR.name] = AR
|
||||
|
||||
var/not_in_order = 0
|
||||
do
|
||||
not_in_order = 0
|
||||
if(teleportlocs.len <= 1)
|
||||
break
|
||||
for(var/i = 1, i <= (teleportlocs.len - 1), i++)
|
||||
if(sorttext(teleportlocs[i], teleportlocs[i+1]) == -1)
|
||||
teleportlocs.Swap(i, i+1)
|
||||
not_in_order = 1
|
||||
while(not_in_order)
|
||||
sortTim(teleportlocs, /proc/cmp_text_dsc)
|
||||
|
||||
var/list/ghostteleportlocs = list()
|
||||
|
||||
@@ -108,45 +94,24 @@ proc/process_ghost_teleport_locs()
|
||||
if(istype(AR, /area/turret_protected/aisat) || istype(AR, /area/derelict) || istype(AR, /area/tdome))
|
||||
ghostteleportlocs += AR.name
|
||||
ghostteleportlocs[AR.name] = AR
|
||||
var/list/turfss = get_area_turfs(AR.type)
|
||||
if(!istype(turfss) || !turfss.len)
|
||||
//warning("Area [AR] had no turfs!")
|
||||
continue
|
||||
//testing("Picking a turf from [AR]/([AR.type]) turfs length [turfss.len]")
|
||||
var/turf/picked = pick(get_area_turfs(AR.type))
|
||||
if (picked.z == 1 || picked.z == 5 || picked.z == 3)
|
||||
var/turf/picked = safepick(get_area_turfs(AR.type))
|
||||
if (picked && (picked.z == 1 || picked.z == 5 || picked.z == 3))
|
||||
ghostteleportlocs += AR.name
|
||||
ghostteleportlocs[AR.name] = AR
|
||||
|
||||
var/not_in_order = 0
|
||||
do
|
||||
not_in_order = 0
|
||||
if(ghostteleportlocs.len <= 1)
|
||||
break
|
||||
for(var/i = 1, i <= (ghostteleportlocs.len - 1), i++)
|
||||
if(sorttext(ghostteleportlocs[i], ghostteleportlocs[i+1]) == -1)
|
||||
ghostteleportlocs.Swap(i, i+1)
|
||||
not_in_order = 1
|
||||
while(not_in_order)
|
||||
sortTim(ghostteleportlocs, /proc/cmp_text_dsc)
|
||||
|
||||
var/global/list/adminbusteleportlocs = list()
|
||||
|
||||
proc/process_adminbus_teleport_locs()
|
||||
for(var/area/AR in world)
|
||||
if(adminbusteleportlocs.Find(AR.name)) continue
|
||||
var/turf/picked = safepick(get_area_turfs(AR.type))
|
||||
if (picked)
|
||||
adminbusteleportlocs += AR.name
|
||||
adminbusteleportlocs[AR.name] = AR
|
||||
|
||||
var/not_in_order = 0
|
||||
do
|
||||
not_in_order = 0
|
||||
if(adminbusteleportlocs.len <= 1)
|
||||
break
|
||||
for(var/i = 1, i <= (adminbusteleportlocs.len - 1), i++)
|
||||
if(sorttext(adminbusteleportlocs[i], adminbusteleportlocs[i+1]) == -1)
|
||||
adminbusteleportlocs.Swap(i, i+1)
|
||||
not_in_order = 1
|
||||
while(not_in_order)
|
||||
sortTim(adminbusteleportlocs, /proc/cmp_text_dsc)
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
//crewmembers += "temporary item"
|
||||
//crewmembers[crewmembers.len] = crewmemberData
|
||||
|
||||
crewmembers = sortByKey(crewmembers, "name")
|
||||
crewmembers = sortList(crewmembers)
|
||||
|
||||
data["crewmembers"] = crewmembers
|
||||
|
||||
|
||||
@@ -265,7 +265,7 @@
|
||||
else
|
||||
user << "<span class='notice'>\The [src] smartly refuses [O].</span>"
|
||||
return 1
|
||||
|
||||
sortList(item_quants)
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/smartfridge/attack_paw(mob/user as mob)
|
||||
|
||||
@@ -132,6 +132,7 @@ move an amendment</a> to the drawing.</p>
|
||||
A.power_environ = 0
|
||||
A.always_unpowered = 0
|
||||
A.SetDynamicLighting()
|
||||
A.addSorted()
|
||||
spawn() move_turfs_to_area(turfs, A)
|
||||
|
||||
A.always_unpowered = 0
|
||||
|
||||
@@ -21,7 +21,7 @@ var/global/list/camera_bugs = list()
|
||||
|
||||
for (var/obj/item/device/camera_bug/C in cameras)
|
||||
friendly_cameras.Add(C.c_tag)
|
||||
var/target = input("Select the camera to observe", null) as null|anything in friendly_cameras
|
||||
var/target = input("Select the camera to observe", null) as null|anything in sortList(friendly_cameras)
|
||||
if (!target)
|
||||
user.unset_machine()
|
||||
user.reset_view(user)
|
||||
|
||||
@@ -368,3 +368,6 @@ var/global/datum/gas_mixture/space_gas = new
|
||||
|
||||
//Announcement intercom
|
||||
var/obj/item/device/radio/intercom/announcement_intercom = new(null)
|
||||
|
||||
//used by jump-to-area etc. Updated by area/updateName()
|
||||
var/list/sortedAreas = list()
|
||||
@@ -247,6 +247,7 @@ var/list/admin_verbs_hideable = list(
|
||||
/client/proc/cmd_debug_tog_aliens,
|
||||
/client/proc/air_report,
|
||||
/client/proc/enable_debug_verbs,
|
||||
/client/proc/mob_list()
|
||||
/proc/possess,
|
||||
/proc/release
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/client/proc/Jump(var/area/A in return_sorted_areas())
|
||||
/client/proc/Jump(var/area/A in sortedAreas)
|
||||
set name = "Jump to Area"
|
||||
set desc = "Area to jump to"
|
||||
set category = "Admin"
|
||||
@@ -7,10 +7,21 @@
|
||||
return
|
||||
|
||||
if(config.allow_admin_jump)
|
||||
var/list/L = get_area_turfs(A)
|
||||
if(!L || !L.len)
|
||||
if(!A)
|
||||
return
|
||||
usr.loc = pick(get_area_turfs(A))
|
||||
|
||||
var/list/turfs = list()
|
||||
for(var/area/Ar in A.related)
|
||||
for(var/turf/T in Ar)
|
||||
if(T.density)
|
||||
continue
|
||||
turfs.Add(T)
|
||||
|
||||
var/turf/T = pick_n_take(turfs)
|
||||
if(!T)
|
||||
src << "Nowhere to jump to!"
|
||||
return
|
||||
usr.loc = T
|
||||
|
||||
log_admin("[key_name(usr)] jumped to [A]")
|
||||
message_admins("[key_name_admin(usr)] jumped to [A]", 1)
|
||||
@@ -148,7 +159,7 @@
|
||||
if(!src.holder)
|
||||
src << "Only administrators may use this command."
|
||||
return
|
||||
var/area/A = input(usr, "Pick an area.", "Pick an area") in return_sorted_areas()
|
||||
var/area/A = input(usr, "Pick an area.", "Pick an area") in sortedAreas
|
||||
if(A)
|
||||
if(config.allow_admin_jump)
|
||||
M.loc = pick(get_area_turfs(A))
|
||||
|
||||
@@ -1258,3 +1258,20 @@ client/proc/delete_all_adminbus()
|
||||
|
||||
for(var/obj/structure/stool/bed/chair/vehicle/adminbus/AB in world)
|
||||
AB.Adminbus_Deletion()
|
||||
|
||||
client/proc/mob_list()
|
||||
set name = "show mob list"
|
||||
set category = "Debug"
|
||||
if(!holder) return
|
||||
usr << "mob list length is [mob_list.len]"
|
||||
var/foundnull = 0
|
||||
for(var/mob/V in mob_list)
|
||||
var/msg = "mob ([V]) is in slot [mob_list.Find(V)]"
|
||||
if(!ismob(V))
|
||||
if(isnull(V))
|
||||
foundnull++
|
||||
msg = "Non mob found in mob list [isnull(V) ? "null entry found at mob_list.Find(V)" : "[V]'s type is [V.type]"]"
|
||||
usr << msg
|
||||
if(foundnull)
|
||||
usr << "Found [foundnull] null entries in the mob list, running null clearer."
|
||||
listclearnulls(mob_list)
|
||||
@@ -51,6 +51,7 @@ USE THIS CHEMISTRY DISPENSER FOR MAPS SO THEY START AT 100 ENERGY
|
||||
)
|
||||
|
||||
RefreshParts()
|
||||
dispensable_reagents = sortList(dispensable_reagents)
|
||||
|
||||
/obj/machinery/chem_dispenser/RefreshParts()
|
||||
var/T = 0
|
||||
|
||||
@@ -131,6 +131,7 @@
|
||||
process_teleport_locs() //Sets up the wizard teleport locations
|
||||
process_ghost_teleport_locs() //Sets up ghost teleport locations.
|
||||
process_adminbus_teleport_locs() //Sets up adminbus teleport locations.
|
||||
SortAreas() //Build the list of all existing areas and sort it alphabetically
|
||||
|
||||
spawn(3000) //so we aren't adding to the round-start lag
|
||||
if(config.ToRban)
|
||||
|
||||
Reference in New Issue
Block a user