Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13
This commit is contained in:
@@ -114,10 +114,7 @@
|
||||
/turf/open/floor/mineral/plasma,
|
||||
/area/shuttle/escape)
|
||||
"v" = (
|
||||
/obj/machinery/disco{
|
||||
anchored = 1;
|
||||
req_access = null
|
||||
},
|
||||
/obj/machinery/disco/indestructible,
|
||||
/turf/open/floor/light/colour_cycle,
|
||||
/area/shuttle/escape)
|
||||
"w" = (
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
|
||||
//////////////////////
|
||||
//Heap object
|
||||
//datum/Heap object
|
||||
//////////////////////
|
||||
|
||||
/Heap
|
||||
/datum/Heap
|
||||
var/list/L
|
||||
var/cmp
|
||||
|
||||
/Heap/New(compare)
|
||||
/datum/Heap/New(compare)
|
||||
L = new()
|
||||
cmp = compare
|
||||
|
||||
/Heap/proc/IsEmpty()
|
||||
/datum/Heap/proc/IsEmpty()
|
||||
return !L.len
|
||||
|
||||
//Insert and place at its position a new node in the heap
|
||||
/Heap/proc/Insert(atom/A)
|
||||
/datum/Heap/proc/Insert(atom/A)
|
||||
|
||||
L.Add(A)
|
||||
Swim(L.len)
|
||||
|
||||
//removes and returns the first element of the heap
|
||||
//(i.e the max or the min dependant on the comparison function)
|
||||
/Heap/proc/Pop()
|
||||
/datum/Heap/proc/Pop()
|
||||
if(!L.len)
|
||||
return 0
|
||||
. = L[1]
|
||||
@@ -33,7 +33,7 @@
|
||||
Sink(1)
|
||||
|
||||
//Get a node up to its right position in the heap
|
||||
/Heap/proc/Swim(var/index)
|
||||
/datum/Heap/proc/Swim(var/index)
|
||||
var/parent = round(index * 0.5)
|
||||
|
||||
while(parent > 0 && (call(cmp)(L[index],L[parent]) > 0))
|
||||
@@ -42,7 +42,7 @@
|
||||
parent = round(index * 0.5)
|
||||
|
||||
//Get a node down to its right position in the heap
|
||||
/Heap/proc/Sink(var/index)
|
||||
/datum/Heap/proc/Sink(var/index)
|
||||
var/g_child = GetGreaterChild(index)
|
||||
|
||||
while(g_child > 0 && (call(cmp)(L[index],L[g_child]) < 0))
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
//Returns the greater (relative to the comparison proc) of a node children
|
||||
//or 0 if there's no child
|
||||
/Heap/proc/GetGreaterChild(var/index)
|
||||
/datum/Heap/proc/GetGreaterChild(var/index)
|
||||
if(index * 2 > L.len)
|
||||
return 0
|
||||
|
||||
@@ -65,11 +65,11 @@
|
||||
return index * 2
|
||||
|
||||
//Replaces a given node so it verify the heap condition
|
||||
/Heap/proc/ReSort(atom/A)
|
||||
/datum/Heap/proc/ReSort(atom/A)
|
||||
var/index = L.Find(A)
|
||||
|
||||
Swim(index)
|
||||
Sink(index)
|
||||
|
||||
/Heap/proc/List()
|
||||
/datum/Heap/proc/List()
|
||||
. = L.Copy()
|
||||
|
||||
+29
-4
@@ -21,7 +21,7 @@ Last space-z level = empty
|
||||
#define CITY_OF_COGS "City of Cogs"
|
||||
#define EMPTY_AREA_1 "Empty Area 1"
|
||||
#define EMPTY_AREA_2 "Empty Area 2"
|
||||
#define MINING "Mining Asteroid"
|
||||
#define MINING_ASTEROID "Mining Asteroid"
|
||||
#define EMPTY_AREA_3 "Empty Area 3"
|
||||
#define EMPTY_AREA_4 "Empty Area 4"
|
||||
#define EMPTY_AREA_5 "Empty Area 5"
|
||||
@@ -36,11 +36,8 @@ Last space-z level = empty
|
||||
#define MAP_REMOVE_JOB(jobpath) /datum/job/##jobpath/map_check() { return (SSmapping.config.map_name != JOB_MODIFICATION_MAP_NAME) && ..() }
|
||||
|
||||
//zlevel defines, can be overridden for different maps in the appropriate _maps file.
|
||||
#define ZLEVEL_CENTCOM 1
|
||||
#define ZLEVEL_STATION_PRIMARY 2
|
||||
#define ZLEVEL_MINING 5
|
||||
#define ZLEVEL_LAVALAND 5
|
||||
#define ZLEVEL_CITYOFCOGS 6
|
||||
#define ZLEVEL_EMPTY_SPACE 12
|
||||
//Unless you modify it in map config should be equal to ZLEVEL_SPACEMAX
|
||||
#define ZLEVEL_TRANSIT 13
|
||||
@@ -49,3 +46,31 @@ Last space-z level = empty
|
||||
#define ZLEVEL_SPACEMAX 13
|
||||
|
||||
#define SPACERUIN_MAP_EDGE_PAD 15
|
||||
#define ZLEVEL_SPACE_RUIN_COUNT 5
|
||||
|
||||
// traits
|
||||
#define ZTRAIT_CENTCOM "CentCom"
|
||||
#define ZTRAIT_STATION "Station"
|
||||
#define ZTRAIT_MINING "Mining"
|
||||
#define ZTRAIT_REEBE "Reebe"
|
||||
#define ZTRAIT_TRANSIT "Transit"
|
||||
#define ZTRAIT_AWAY "Away Mission"
|
||||
#define ZTRAIT_SPACE_RUINS "Space Ruins"
|
||||
#define ZTRAIT_LAVA_RUINS "Lava Ruins"
|
||||
#define ZTRAIT_BOMBCAP_MULTIPLIER "Bombcap Multiplier"
|
||||
|
||||
// trait definitions
|
||||
#define DL_NAME "name"
|
||||
#define DL_LINKAGE "linkage"
|
||||
#define DL_TRAITS "traits"
|
||||
|
||||
#define DECLARE_LEVEL(NAME, LINKAGE, TRAITS) list(DL_NAME = NAME, DL_LINKAGE = LINKAGE, DL_TRAITS = TRAITS)
|
||||
// corresponds to basemap.dm
|
||||
#define DEFAULT_MAP_TRAITS list(\
|
||||
DECLARE_LEVEL("CentCom", SELFLOOPING, list(ZTRAIT_CENTCOM = TRUE)),\
|
||||
DECLARE_LEVEL("Main Station", CROSSLINKED, list(ZTRAIT_STATION = TRUE)),\
|
||||
DECLARE_LEVEL("Empty Area 1", CROSSLINKED, list(ZTRAIT_SPACE_RUINS = TRUE)),\
|
||||
DECLARE_LEVEL("Empty Area 2", CROSSLINKED, list(ZTRAIT_SPACE_RUINS = TRUE)),\
|
||||
DECLARE_LEVEL("Lavaland", UNAFFECTED, list(ZTRAIT_MINING = TRUE, ZTRAIT_LAVA_RUINS = TRUE, ZTRAIT_BOMBCAP_MULTIPLIER = 3)),\
|
||||
DECLARE_LEVEL("Reebe", UNAFFECTED, list(ZTRAIT_REEBE = TRUE, ZTRAIT_BOMBCAP_MULTIPLIER = 0.5)),\
|
||||
)
|
||||
|
||||
+12
-12
@@ -25,19 +25,19 @@ Actual Adjacent procs :
|
||||
*/
|
||||
|
||||
//////////////////////
|
||||
//PathNode object
|
||||
//datum/PathNode object
|
||||
//////////////////////
|
||||
|
||||
//A* nodes variables
|
||||
/PathNode
|
||||
/datum/PathNode
|
||||
var/turf/source //turf associated with the PathNode
|
||||
var/PathNode/prevNode //link to the parent PathNode
|
||||
var/datum/PathNode/prevNode //link to the parent PathNode
|
||||
var/f //A* Node weight (f = g + h)
|
||||
var/g //A* movement cost variable
|
||||
var/h //A* heuristic variable
|
||||
var/nt //count the number of Nodes traversed
|
||||
|
||||
/PathNode/New(s,p,pg,ph,pnt)
|
||||
/datum/PathNode/New(s,p,pg,ph,pnt)
|
||||
source = s
|
||||
prevNode = p
|
||||
g = pg
|
||||
@@ -45,7 +45,7 @@ Actual Adjacent procs :
|
||||
f = g + h
|
||||
nt = pnt
|
||||
|
||||
/PathNode/proc/calc_f()
|
||||
/datum/PathNode/proc/calc_f()
|
||||
f = g + h
|
||||
|
||||
//////////////////////
|
||||
@@ -53,11 +53,11 @@ Actual Adjacent procs :
|
||||
//////////////////////
|
||||
|
||||
//the weighting function, used in the A* algorithm
|
||||
/proc/PathWeightCompare(PathNode/a, PathNode/b)
|
||||
/proc/PathWeightCompare(datum/PathNode/a, datum/PathNode/b)
|
||||
return a.f - b.f
|
||||
|
||||
//reversed so that the Heap is a MinHeap rather than a MaxHeap
|
||||
/proc/HeapPathWeightCompare(PathNode/a, PathNode/b)
|
||||
/proc/HeapPathWeightCompare(datum/PathNode/a, datum/PathNode/b)
|
||||
return b.f - a.f
|
||||
|
||||
//wrapper that returns an empty list if A* failed to find a path
|
||||
@@ -81,13 +81,13 @@ Actual Adjacent procs :
|
||||
return 0
|
||||
maxnodedepth = maxnodes //no need to consider path longer than maxnodes
|
||||
|
||||
var/Heap/open = new /Heap(/proc/HeapPathWeightCompare) //the open list
|
||||
var/datum/Heap/open = new /datum/Heap(/proc/HeapPathWeightCompare) //the open list
|
||||
var/list/closed = new() //the closed list
|
||||
var/list/path = null //the returned path, if any
|
||||
var/PathNode/cur //current processed turf
|
||||
var/datum/PathNode/cur //current processed turf
|
||||
|
||||
//initialization
|
||||
open.Insert(new /PathNode(start,null,0,call(start,dist)(end),0))
|
||||
open.Insert(new /datum/PathNode(start,null,0,call(start,dist)(end),0))
|
||||
|
||||
//then run the main loop
|
||||
while(!open.IsEmpty() && !path)
|
||||
@@ -123,10 +123,10 @@ Actual Adjacent procs :
|
||||
|
||||
var/newg = cur.g + call(cur.source,dist)(T)
|
||||
|
||||
var/PathNode/P = pnodelist[T]
|
||||
var/datum/PathNode/P = pnodelist[T]
|
||||
if(!P)
|
||||
//is not already in open list, so add it
|
||||
var/PathNode/newnode = new /PathNode(T,cur,newg,call(T,dist)(end),cur.nt+1)
|
||||
var/datum/PathNode/newnode = new /datum/PathNode(T,cur,newg,call(T,dist)(end),cur.nt+1)
|
||||
open.Insert(newnode)
|
||||
pnodelist[T] = newnode
|
||||
else //is already in open list, check if it's a better way from the current turf
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
// Helpers for checking whether a z-level conforms to a specific requirement
|
||||
|
||||
// Basic levels
|
||||
#define is_centcom_level(z) ((z) == ZLEVEL_CENTCOM)
|
||||
#define is_centcom_level(z) SSmapping.level_trait(z, ZTRAIT_CENTCOM)
|
||||
|
||||
#define is_station_level(z) ((z) in GLOB.station_z_levels)
|
||||
#define is_station_level(z) SSmapping.level_trait(z, ZTRAIT_STATION)
|
||||
|
||||
#define is_mining_level(z) ((z) == ZLEVEL_MINING)
|
||||
#define is_mining_level(z) SSmapping.level_trait(z, ZTRAIT_MINING)
|
||||
|
||||
#define is_reebe(z) ((z) == ZLEVEL_CITYOFCOGS)
|
||||
#define is_reebe(z) SSmapping.level_trait(z, ZTRAIT_REEBE)
|
||||
|
||||
#define is_transit_level(z) ((z) == ZLEVEL_TRANSIT)
|
||||
#define is_transit_level(z) SSmapping.level_trait(z, ZTRAIT_TRANSIT)
|
||||
|
||||
#define is_away_level(z) ((z) > ZLEVEL_SPACEMAX)
|
||||
#define is_away_level(z) SSmapping.level_trait(z, ZTRAIT_AWAY)
|
||||
|
||||
// If true, the singularity cannot strip away asteroid turf on this Z
|
||||
#define is_planet_level(z) (GLOB.z_is_planet["z"])
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
#define Z_NORTH 1
|
||||
#define Z_EAST 2
|
||||
#define Z_SOUTH 3
|
||||
#define Z_WEST 4
|
||||
|
||||
GLOBAL_LIST_INIT(cardinals, list(NORTH, SOUTH, EAST, WEST))
|
||||
GLOBAL_LIST_INIT(alldirs, list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
|
||||
GLOBAL_LIST_INIT(diagonals, list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
|
||||
|
||||
GLOBAL_LIST_INIT(station_z_levels, list(ZLEVEL_STATION_PRIMARY))
|
||||
|
||||
GLOBAL_LIST(global_map)
|
||||
//list/global_map = list(list(1,5),list(4,3))//an array of map Z levels.
|
||||
//Resulting sector map looks like
|
||||
|
||||
@@ -22,6 +22,9 @@ SUBSYSTEM_DEF(mapping)
|
||||
|
||||
var/loading_ruins = FALSE
|
||||
|
||||
// Z-manager stuff
|
||||
var/list/z_list
|
||||
|
||||
/datum/controller/subsystem/mapping/PreInit()
|
||||
if(!config)
|
||||
#ifdef FORCE_MAP
|
||||
@@ -39,28 +42,34 @@ SUBSYSTEM_DEF(mapping)
|
||||
repopulate_sorted_areas()
|
||||
process_teleport_locs() //Sets up the wizard teleport locations
|
||||
preloadTemplates()
|
||||
|
||||
// Create space levels
|
||||
for(var/I in 1 to ZLEVEL_SPACE_RUIN_COUNT)
|
||||
add_new_zlevel("Empty Area [2 + I]", CROSSLINKED, list(ZTRAIT_SPACE_RUINS = TRUE))
|
||||
add_new_zlevel("Empty Area [3 + ZLEVEL_SPACE_RUIN_COUNT]", CROSSLINKED, list()) // no ruins
|
||||
add_new_zlevel("Transit", UNAFFECTED, list(ZTRAIT_TRANSIT = TRUE))
|
||||
|
||||
// Pick a random away mission.
|
||||
createRandomZlevel()
|
||||
// Generate mining.
|
||||
if (z_list.len < world.maxz)
|
||||
add_new_zlevel("Away Mission", UNAFFECTED, list(ZTRAIT_AWAY = TRUE))
|
||||
|
||||
// Generate mining ruins
|
||||
loading_ruins = TRUE
|
||||
var/mining_type = config.minetype
|
||||
if (mining_type == "lavaland")
|
||||
seedRuins(list(ZLEVEL_LAVALAND), CONFIG_GET(number/lavaland_budget), /area/lavaland/surface/outdoors/unexplored, lava_ruins_templates)
|
||||
spawn_rivers()
|
||||
var/list/lava_ruins = levels_by_trait(ZTRAIT_LAVA_RUINS)
|
||||
if (lava_ruins.len)
|
||||
seedRuins(lava_ruins, CONFIG_GET(number/lavaland_budget), /area/lavaland/surface/outdoors/unexplored, lava_ruins_templates)
|
||||
for (var/lava_z in lava_ruins)
|
||||
spawn_rivers(lava_z)
|
||||
|
||||
// deep space ruins
|
||||
var/space_zlevels = list()
|
||||
for(var/i in ZLEVEL_SPACEMIN to ZLEVEL_SPACEMAX)
|
||||
switch(i)
|
||||
if(ZLEVEL_MINING, ZLEVEL_LAVALAND, ZLEVEL_EMPTY_SPACE, ZLEVEL_TRANSIT, ZLEVEL_CITYOFCOGS)
|
||||
continue
|
||||
else
|
||||
space_zlevels += i
|
||||
|
||||
seedRuins(space_zlevels, CONFIG_GET(number/space_budget), /area/space, space_ruins_templates)
|
||||
// Generate deep space ruins
|
||||
var/list/space_ruins = levels_by_trait(ZTRAIT_SPACE_RUINS)
|
||||
if (space_ruins.len)
|
||||
seedRuins(space_ruins, CONFIG_GET(number/space_budget), /area/space, space_ruins_templates)
|
||||
loading_ruins = FALSE
|
||||
|
||||
repopulate_sorted_areas()
|
||||
// Set up Z-level transistions.
|
||||
// Set up Z-level transitions.
|
||||
setup_map_transitions()
|
||||
generate_station_area_list()
|
||||
..()
|
||||
@@ -98,6 +107,8 @@ SUBSYSTEM_DEF(mapping)
|
||||
config = SSmapping.config
|
||||
next_map_config = SSmapping.next_map_config
|
||||
|
||||
z_list = SSmapping.z_list
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/TryLoadZ(filename, errorList, forceLevel, last)
|
||||
var/static/dmm_suite/loader
|
||||
if(!loader)
|
||||
@@ -107,11 +118,6 @@ SUBSYSTEM_DEF(mapping)
|
||||
if(last)
|
||||
QDEL_NULL(loader)
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/CreateSpace(MaxZLevel)
|
||||
while(world.maxz < MaxZLevel)
|
||||
++world.maxz
|
||||
CHECK_TICK
|
||||
|
||||
#define INIT_ANNOUNCE(X) to_chat(world, "<span class='boldannounce'>[X]</span>"); log_world(X)
|
||||
/datum/controller/subsystem/mapping/proc/loadWorld()
|
||||
//if any of these fail, something has gone horribly, HORRIBLY, wrong
|
||||
@@ -121,6 +127,7 @@ SUBSYSTEM_DEF(mapping)
|
||||
|
||||
INIT_ANNOUNCE("Loading [config.map_name]...")
|
||||
TryLoadZ(config.GetFullMapPath(), FailedZs, ZLEVEL_STATION_PRIMARY)
|
||||
InitializeDefaultZLevels()
|
||||
INIT_ANNOUNCE("Loaded station in [(REALTIMEOFDAY - start_time)/10]s!")
|
||||
if(SSdbcore.Connect())
|
||||
var/datum/DBQuery/query_round_map_name = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET map_name = '[config.map_name]' WHERE id = [GLOB.round_id]")
|
||||
@@ -129,8 +136,6 @@ SUBSYSTEM_DEF(mapping)
|
||||
if(config.minetype != "lavaland")
|
||||
INIT_ANNOUNCE("WARNING: A map without lavaland set as its minetype was loaded! This is being ignored! Update the maploader code!")
|
||||
|
||||
CreateSpace(ZLEVEL_SPACEMAX)
|
||||
|
||||
if(LAZYLEN(FailedZs)) //but seriously, unless the server's filesystem is messed up this will never happen
|
||||
var/msg = "RED ALERT! The following map files failed to load: [FailedZs[1]]"
|
||||
if(FailedZs.len > 1)
|
||||
|
||||
@@ -5,9 +5,10 @@ SUBSYSTEM_DEF(minimap)
|
||||
var/const/MINIMAP_SIZE = 2048
|
||||
var/const/TILE_SIZE = 8
|
||||
|
||||
var/list/z_levels = list(ZLEVEL_STATION_PRIMARY)
|
||||
var/list/z_levels
|
||||
|
||||
/datum/controller/subsystem/minimap/Initialize(timeofday)
|
||||
z_levels = SSmapping.levels_by_trait(ZTRAIT_STATION)
|
||||
var/hash = md5(SSmapping.config.GetFullMapPath())
|
||||
if(CONFIG_GET(flag/generate_minimaps))
|
||||
if(hash == trim(file2text(hash_path())))
|
||||
|
||||
@@ -34,7 +34,7 @@ SUBSYSTEM_DEF(squeak)
|
||||
/datum/controller/subsystem/squeak/proc/find_exposed_wires()
|
||||
exposed_wires.Cut()
|
||||
var/list/all_turfs
|
||||
for (var/z in GLOB.station_z_levels)
|
||||
for (var/z in SSmapping.levels_by_trait(ZTRAIT_STATION))
|
||||
all_turfs += block(locate(1,1,z), locate(world.maxx,world.maxy,z))
|
||||
for(var/turf/open/floor/plating/T in all_turfs)
|
||||
if(is_blocked_turf(T))
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#define EXPLOSION_THROW_SPEED 4
|
||||
#define CITYOFCOGS_CAP_MULTIPLIER 0.5
|
||||
#define MINING_CAP_MULTIPLIER 3
|
||||
|
||||
GLOBAL_LIST_EMPTY(explosions)
|
||||
//Against my better judgement, I will return the explosion datum
|
||||
@@ -54,17 +52,14 @@ GLOBAL_LIST_EMPTY(explosions)
|
||||
var/orig_dev_range = devastation_range
|
||||
var/orig_heavy_range = heavy_impact_range
|
||||
var/orig_light_range = light_impact_range
|
||||
|
||||
|
||||
var/orig_max_distance = max(devastation_range, heavy_impact_range, light_impact_range, flash_range, flame_range)
|
||||
|
||||
|
||||
//Zlevel specific bomb cap multiplier
|
||||
var/cap_multiplier = 1
|
||||
switch(epicenter.z)
|
||||
if(ZLEVEL_CITYOFCOGS)
|
||||
cap_multiplier = CITYOFCOGS_CAP_MULTIPLIER
|
||||
if(ZLEVEL_MINING)
|
||||
cap_multiplier = MINING_CAP_MULTIPLIER
|
||||
|
||||
var/cap_multiplier = SSmapping.level_trait(epicenter.z, ZTRAIT_BOMBCAP_MULTIPLIER)
|
||||
if (isnull(cap_multiplier))
|
||||
cap_multiplier = 1
|
||||
|
||||
if(!ignorecap)
|
||||
devastation_range = min(GLOB.MAX_EX_DEVESTATION_RANGE * cap_multiplier, devastation_range)
|
||||
heavy_impact_range = min(GLOB.MAX_EX_HEAVY_RANGE * cap_multiplier, heavy_impact_range)
|
||||
@@ -91,11 +86,11 @@ GLOBAL_LIST_EMPTY(explosions)
|
||||
if(adminlog)
|
||||
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area: [epi_area] [ADMIN_COORDJMP(epicenter)]")
|
||||
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z])")
|
||||
|
||||
|
||||
var/x0 = epicenter.x
|
||||
var/y0 = epicenter.y
|
||||
var/z0 = epicenter.z
|
||||
|
||||
|
||||
SSblackbox.record_feedback("associative", "explosion", 1, list("dev" = devastation_range, "heavy" = heavy_impact_range, "light" = light_impact_range, "flash" = flash_range, "flame" = flame_range, "orig_dev" = orig_dev_range, "orig_heavy" = orig_heavy_range, "orig_light" = orig_light_range, "x" = x0, "y" = y0, "z" = z0, "area" = epi_area.type))
|
||||
|
||||
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
|
||||
@@ -199,7 +194,7 @@ GLOBAL_LIST_EMPTY(explosions)
|
||||
//------- EX_ACT AND TURF FIRES -------
|
||||
|
||||
if(T == epicenter) // Ensures explosives detonating from bags trigger other explosives in that bag
|
||||
var/list/items = list()
|
||||
var/list/items = list()
|
||||
for(var/I in T)
|
||||
var/atom/A = I
|
||||
items += A.GetAllContents()
|
||||
@@ -418,6 +413,3 @@ GLOBAL_LIST_EMPTY(explosions)
|
||||
// 10 explosion power is a (1, 3, 6) explosion.
|
||||
// 5 explosion power is a (0, 1, 3) explosion.
|
||||
// 1 explosion power is a (0, 0, 1) explosion.
|
||||
|
||||
#undef CITYOFCOGS_CAP_MULTIPLIER
|
||||
#undef MINING_CAP_MULTIPLIER
|
||||
|
||||
@@ -166,9 +166,12 @@
|
||||
|
||||
// Safe location finder
|
||||
|
||||
/proc/find_safe_turf(zlevel = ZLEVEL_STATION_PRIMARY, list/zlevels, extended_safety_checks = FALSE)
|
||||
/proc/find_safe_turf(zlevel, list/zlevels, extended_safety_checks = FALSE)
|
||||
if(!zlevels)
|
||||
zlevels = list(zlevel)
|
||||
if (zlevel)
|
||||
zlevels = list(zlevel)
|
||||
else
|
||||
zlevels = SSmapping.levels_by_trait(ZTRAIT_STATION)
|
||||
var/cycles = 1000
|
||||
for(var/cycle in 1 to cycles)
|
||||
// DRUNK DIALLING WOOOOOOOOO
|
||||
|
||||
+2
-2
@@ -1174,7 +1174,7 @@
|
||||
if(devilinfo)
|
||||
devilinfo.ascendable = FALSE
|
||||
message_admins("[key_name_admin(usr)] has made [current] unable to ascend as a devil.")
|
||||
log_admin("[key_name_admin(usr)] has made [current] unable to ascend as a devil.")
|
||||
log_admin("[key_name(usr)] has made [current] unable to ascend as a devil.")
|
||||
return
|
||||
if(!ishuman(current) && !iscyborg(current))
|
||||
to_chat(usr, "<span class='warning'>This only works on humans and cyborgs!</span>")
|
||||
@@ -1186,7 +1186,7 @@
|
||||
if(devilinfo)
|
||||
devilinfo.ascendable = TRUE
|
||||
message_admins("[key_name_admin(usr)] has made [current] able to ascend as a devil.")
|
||||
log_admin("[key_name_admin(usr)] has made [current] able to ascend as a devil.")
|
||||
log_admin("[key_name(usr)] has made [current] able to ascend as a devil.")
|
||||
return
|
||||
if(!ishuman(current) && !iscyborg(current))
|
||||
to_chat(usr, "<span class='warning'>This only works on humans and cyborgs!</span>")
|
||||
|
||||
@@ -1,239 +1,239 @@
|
||||
//Designed for things that need precision trajectories like projectiles.
|
||||
//Don't use this for anything that you don't absolutely have to use this with (like projectiles!) because it isn't worth using a datum unless you need accuracy down to decimal places in pixels.
|
||||
|
||||
#define RETURN_PRECISE_POSITION(A) new /datum/position(A)
|
||||
#define RETURN_PRECISE_POINT(A) new /datum/point(A)
|
||||
|
||||
/datum/position //For positions with map x/y/z and pixel x/y so you don't have to return lists. Could use addition/subtraction in the future I guess.
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/z = 0
|
||||
var/pixel_x = 0
|
||||
var/pixel_y = 0
|
||||
|
||||
/datum/position/proc/valid()
|
||||
return x && y && z && !isnull(pixel_x) && !isnull(pixel_y)
|
||||
|
||||
/datum/position/New(_x = 0, _y = 0, _z = 0, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/point.
|
||||
if(istype(_x, /datum/point))
|
||||
var/datum/point/P = _x
|
||||
var/turf/T = P.return_turf()
|
||||
_x = T.x
|
||||
_y = T.y
|
||||
_z = T.z
|
||||
_pixel_x = P.return_px()
|
||||
_pixel_y = P.return_py()
|
||||
else if(isatom(_x))
|
||||
var/atom/A = _x
|
||||
_x = A.x
|
||||
_y = A.y
|
||||
_z = A.z
|
||||
_pixel_x = A.pixel_x
|
||||
_pixel_y = A.pixel_y
|
||||
x = _x
|
||||
y = _y
|
||||
z = _z
|
||||
pixel_x = _pixel_x
|
||||
pixel_y = _pixel_y
|
||||
|
||||
/datum/position/proc/return_turf()
|
||||
return locate(x, y, z)
|
||||
|
||||
/datum/position/proc/return_px()
|
||||
return pixel_x
|
||||
|
||||
/datum/position/proc/return_py()
|
||||
return pixel_y
|
||||
|
||||
/datum/position/proc/return_point()
|
||||
return new /datum/point(src)
|
||||
|
||||
/proc/point_midpoint_points(datum/point/a, datum/point/b) //Obviously will not support multiZ calculations! Same for the two below.
|
||||
var/datum/point/P = new
|
||||
P.x = round(a.x + (b.x - a.x) / 2, 1)
|
||||
P.y = round(a.y + (b.y - a.y) / 2, 1)
|
||||
P.z = a.z
|
||||
return P
|
||||
|
||||
/proc/pixel_length_between_points(datum/point/a, datum/point/b)
|
||||
return sqrt(((b.x - a.x) ** 2) + ((b.y - a.y) ** 2))
|
||||
|
||||
/proc/angle_between_points(datum/point/a, datum/point/b)
|
||||
return ATAN2((b.y - a.y), (b.x - a.x))
|
||||
|
||||
/datum/point //A precise point on the map in absolute pixel locations based on world.icon_size. Pixels are FROM THE EDGE OF THE MAP!
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/z = 0
|
||||
|
||||
/datum/point/proc/valid()
|
||||
return x && y && z
|
||||
|
||||
/datum/point/proc/copy_to(datum/point/p = new)
|
||||
p.x = x
|
||||
p.y = y
|
||||
p.z = z
|
||||
return p
|
||||
|
||||
/datum/point/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/position or /atom.
|
||||
if(istype(_x, /datum/position))
|
||||
var/datum/position/P = _x
|
||||
_x = P.x
|
||||
_y = P.y
|
||||
_z = P.z
|
||||
_pixel_x = P.pixel_x
|
||||
_pixel_y = P.pixel_y
|
||||
else if(istype(_x, /atom))
|
||||
var/atom/A = _x
|
||||
_x = A.x
|
||||
_y = A.y
|
||||
_z = A.z
|
||||
_pixel_x = A.pixel_x
|
||||
_pixel_y = A.pixel_y
|
||||
initialize_location(_x, _y, _z, _pixel_x, _pixel_y)
|
||||
|
||||
/datum/point/proc/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0)
|
||||
if(!isnull(tile_x))
|
||||
x = ((tile_x - 1) * world.icon_size) + world.icon_size / 2 + p_x
|
||||
if(!isnull(tile_y))
|
||||
y = ((tile_y - 1) * world.icon_size) + world.icon_size / 2+ p_y
|
||||
if(!isnull(tile_z))
|
||||
z = tile_z
|
||||
|
||||
/datum/point/proc/return_turf()
|
||||
return locate(CEILING(x / world.icon_size, 1), CEILING(y / world.icon_size, 1), z)
|
||||
|
||||
/datum/point/proc/return_coordinates() //[turf_x, turf_y, z]
|
||||
return list(CEILING(x / world.icon_size, 1), CEILING(y / world.icon_size, 1), z)
|
||||
|
||||
/datum/point/proc/return_position()
|
||||
return new /datum/position(src)
|
||||
|
||||
/datum/point/proc/return_px()
|
||||
return MODULUS(x, world.icon_size) - 16
|
||||
|
||||
/datum/point/proc/return_py()
|
||||
return MODULUS(y, world.icon_size) - 16
|
||||
|
||||
/datum/point/proc/mapcheck()
|
||||
. = FALSE
|
||||
var/maxx = world.icon_size * world.maxx
|
||||
var/maxy = world.icon_size * world.maxy
|
||||
var/move_zx = 0
|
||||
var/move_zy = 0
|
||||
if(x < 0)
|
||||
x += maxx
|
||||
move_zx -= 1
|
||||
if(y < 0)
|
||||
y += maxy
|
||||
move_zy -= 1
|
||||
if(x > maxx)
|
||||
x -= maxx
|
||||
move_zx += 1
|
||||
if(y > maxy)
|
||||
y -= maxy
|
||||
move_zy += 1
|
||||
var/datum/space_level/S = GLOB.z_levels_list["[z]"]
|
||||
if(move_zx != 0)
|
||||
var/datum/space_level/L = S.neigbours["[move_zx < 0? WEST : EAST]"]
|
||||
z = L.z_value
|
||||
. = TRUE
|
||||
if(move_zy != 0)
|
||||
var/datum/space_level/L = S.neigbours["[move_zy < 0? SOUTH : NORTH]"]
|
||||
z = L.z_value
|
||||
. = TRUE
|
||||
|
||||
/datum/point/vector
|
||||
var/speed = 32 //pixels per iteration
|
||||
var/iteration = 0
|
||||
var/angle = 0
|
||||
var/mpx = 0 //calculated x/y movement amounts to prevent having to do trig every step.
|
||||
var/mpy = 0
|
||||
var/starting_x = 0 //just like before, pixels from EDGE of map! This is set in initialize_location().
|
||||
var/starting_y = 0
|
||||
var/starting_z = 0
|
||||
|
||||
/datum/point/vector/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0, _angle, _speed)
|
||||
..()
|
||||
initialize_trajectory(_speed, _angle)
|
||||
|
||||
/datum/point/vector/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0)
|
||||
. = ..()
|
||||
starting_x = x
|
||||
starting_y = y
|
||||
starting_z = z
|
||||
|
||||
/datum/point/vector/copy_to(datum/point/vector/v = new)
|
||||
..(v)
|
||||
v.speed = speed
|
||||
v.iteration = iteration
|
||||
v.angle = angle
|
||||
v.mpx = mpx
|
||||
v.mpy = mpy
|
||||
v.starting_x = starting_x
|
||||
v.starting_y = starting_y
|
||||
v.starting_z = starting_z
|
||||
return v
|
||||
|
||||
/datum/point/vector/proc/initialize_trajectory(pixel_speed, new_angle)
|
||||
if(!isnull(pixel_speed))
|
||||
speed = pixel_speed
|
||||
set_angle(new_angle)
|
||||
|
||||
/datum/point/vector/proc/set_angle(new_angle) //calculations use "byond angle" where north is 0 instead of 90, and south is 180 instead of 270.
|
||||
if(isnull(angle))
|
||||
return
|
||||
angle = new_angle
|
||||
update_offsets()
|
||||
|
||||
/datum/point/vector/proc/update_offsets()
|
||||
mpx = sin(angle) * speed
|
||||
mpy = cos(angle) * speed
|
||||
|
||||
/datum/point/vector/proc/set_speed(new_speed)
|
||||
if(isnull(new_speed) || speed == new_speed)
|
||||
return
|
||||
speed = new_speed
|
||||
update_offsets()
|
||||
|
||||
/datum/point/vector/proc/increment(multiplier = 1)
|
||||
iteration++
|
||||
x += mpx * 1
|
||||
y += mpy * 1
|
||||
if(mapcheck())
|
||||
on_z_change()
|
||||
|
||||
/datum/point/vector/proc/return_vector_after_increments(amount = 7, multiplier = 1, force_simulate = FALSE)
|
||||
var/datum/point/vector/v = copy_to()
|
||||
if(force_simulate)
|
||||
for(var/i in 1 to amount)
|
||||
v.increment(multiplier)
|
||||
else
|
||||
v.increment(multiplier * amount)
|
||||
return v
|
||||
|
||||
/datum/point/vector/proc/on_z_change()
|
||||
return
|
||||
|
||||
/datum/point/vector/processed //pixel_speed is per decisecond.
|
||||
var/last_process = 0
|
||||
var/last_move = 0
|
||||
var/paused = FALSE
|
||||
|
||||
/datum/point/vector/processed/Destroy()
|
||||
STOP_PROCESSING(SSprojectiles, src)
|
||||
|
||||
/datum/point/vector/processed/proc/start()
|
||||
last_process = world.time
|
||||
last_move = world.time
|
||||
START_PROCESSING(SSprojectiles, src)
|
||||
|
||||
/datum/point/vector/processed/process()
|
||||
if(paused)
|
||||
last_move += world.time - last_process
|
||||
last_process = world.time
|
||||
return
|
||||
var/needed_time = world.time - last_move
|
||||
last_process = world.time
|
||||
last_move = world.time
|
||||
increment(needed_time)
|
||||
//Designed for things that need precision trajectories like projectiles.
|
||||
//Don't use this for anything that you don't absolutely have to use this with (like projectiles!) because it isn't worth using a datum unless you need accuracy down to decimal places in pixels.
|
||||
|
||||
#define RETURN_PRECISE_POSITION(A) new /datum/position(A)
|
||||
#define RETURN_PRECISE_POINT(A) new /datum/point(A)
|
||||
|
||||
/datum/position //For positions with map x/y/z and pixel x/y so you don't have to return lists. Could use addition/subtraction in the future I guess.
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/z = 0
|
||||
var/pixel_x = 0
|
||||
var/pixel_y = 0
|
||||
|
||||
/datum/position/proc/valid()
|
||||
return x && y && z && !isnull(pixel_x) && !isnull(pixel_y)
|
||||
|
||||
/datum/position/New(_x = 0, _y = 0, _z = 0, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/point.
|
||||
if(istype(_x, /datum/point))
|
||||
var/datum/point/P = _x
|
||||
var/turf/T = P.return_turf()
|
||||
_x = T.x
|
||||
_y = T.y
|
||||
_z = T.z
|
||||
_pixel_x = P.return_px()
|
||||
_pixel_y = P.return_py()
|
||||
else if(isatom(_x))
|
||||
var/atom/A = _x
|
||||
_x = A.x
|
||||
_y = A.y
|
||||
_z = A.z
|
||||
_pixel_x = A.pixel_x
|
||||
_pixel_y = A.pixel_y
|
||||
x = _x
|
||||
y = _y
|
||||
z = _z
|
||||
pixel_x = _pixel_x
|
||||
pixel_y = _pixel_y
|
||||
|
||||
/datum/position/proc/return_turf()
|
||||
return locate(x, y, z)
|
||||
|
||||
/datum/position/proc/return_px()
|
||||
return pixel_x
|
||||
|
||||
/datum/position/proc/return_py()
|
||||
return pixel_y
|
||||
|
||||
/datum/position/proc/return_point()
|
||||
return new /datum/point(src)
|
||||
|
||||
/proc/point_midpoint_points(datum/point/a, datum/point/b) //Obviously will not support multiZ calculations! Same for the two below.
|
||||
var/datum/point/P = new
|
||||
P.x = round(a.x + (b.x - a.x) / 2, 1)
|
||||
P.y = round(a.y + (b.y - a.y) / 2, 1)
|
||||
P.z = a.z
|
||||
return P
|
||||
|
||||
/proc/pixel_length_between_points(datum/point/a, datum/point/b)
|
||||
return sqrt(((b.x - a.x) ** 2) + ((b.y - a.y) ** 2))
|
||||
|
||||
/proc/angle_between_points(datum/point/a, datum/point/b)
|
||||
return ATAN2((b.y - a.y), (b.x - a.x))
|
||||
|
||||
/datum/point //A precise point on the map in absolute pixel locations based on world.icon_size. Pixels are FROM THE EDGE OF THE MAP!
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/z = 0
|
||||
|
||||
/datum/point/proc/valid()
|
||||
return x && y && z
|
||||
|
||||
/datum/point/proc/copy_to(datum/point/p = new)
|
||||
p.x = x
|
||||
p.y = y
|
||||
p.z = z
|
||||
return p
|
||||
|
||||
/datum/point/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/position or /atom.
|
||||
if(istype(_x, /datum/position))
|
||||
var/datum/position/P = _x
|
||||
_x = P.x
|
||||
_y = P.y
|
||||
_z = P.z
|
||||
_pixel_x = P.pixel_x
|
||||
_pixel_y = P.pixel_y
|
||||
else if(istype(_x, /atom))
|
||||
var/atom/A = _x
|
||||
_x = A.x
|
||||
_y = A.y
|
||||
_z = A.z
|
||||
_pixel_x = A.pixel_x
|
||||
_pixel_y = A.pixel_y
|
||||
initialize_location(_x, _y, _z, _pixel_x, _pixel_y)
|
||||
|
||||
/datum/point/proc/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0)
|
||||
if(!isnull(tile_x))
|
||||
x = ((tile_x - 1) * world.icon_size) + world.icon_size / 2 + p_x
|
||||
if(!isnull(tile_y))
|
||||
y = ((tile_y - 1) * world.icon_size) + world.icon_size / 2+ p_y
|
||||
if(!isnull(tile_z))
|
||||
z = tile_z
|
||||
|
||||
/datum/point/proc/return_turf()
|
||||
return locate(CEILING(x / world.icon_size, 1), CEILING(y / world.icon_size, 1), z)
|
||||
|
||||
/datum/point/proc/return_coordinates() //[turf_x, turf_y, z]
|
||||
return list(CEILING(x / world.icon_size, 1), CEILING(y / world.icon_size, 1), z)
|
||||
|
||||
/datum/point/proc/return_position()
|
||||
return new /datum/position(src)
|
||||
|
||||
/datum/point/proc/return_px()
|
||||
return MODULUS(x, world.icon_size) - 16
|
||||
|
||||
/datum/point/proc/return_py()
|
||||
return MODULUS(y, world.icon_size) - 16
|
||||
|
||||
/datum/point/proc/mapcheck()
|
||||
. = FALSE
|
||||
var/maxx = world.icon_size * world.maxx
|
||||
var/maxy = world.icon_size * world.maxy
|
||||
var/move_zx = 0
|
||||
var/move_zy = 0
|
||||
if(x < 0)
|
||||
x += maxx
|
||||
move_zx -= 1
|
||||
if(y < 0)
|
||||
y += maxy
|
||||
move_zy -= 1
|
||||
if(x > maxx)
|
||||
x -= maxx
|
||||
move_zx += 1
|
||||
if(y > maxy)
|
||||
y -= maxy
|
||||
move_zy += 1
|
||||
var/datum/space_level/S = SSmapping.get_level(z)
|
||||
if(move_zx != 0)
|
||||
var/datum/space_level/L = S.neigbours["[move_zx < 0? WEST : EAST]"]
|
||||
z = L.z_value
|
||||
. = TRUE
|
||||
if(move_zy != 0)
|
||||
var/datum/space_level/L = S.neigbours["[move_zy < 0? SOUTH : NORTH]"]
|
||||
z = L.z_value
|
||||
. = TRUE
|
||||
|
||||
/datum/point/vector
|
||||
var/speed = 32 //pixels per iteration
|
||||
var/iteration = 0
|
||||
var/angle = 0
|
||||
var/mpx = 0 //calculated x/y movement amounts to prevent having to do trig every step.
|
||||
var/mpy = 0
|
||||
var/starting_x = 0 //just like before, pixels from EDGE of map! This is set in initialize_location().
|
||||
var/starting_y = 0
|
||||
var/starting_z = 0
|
||||
|
||||
/datum/point/vector/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0, _angle, _speed)
|
||||
..()
|
||||
initialize_trajectory(_speed, _angle)
|
||||
|
||||
/datum/point/vector/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0)
|
||||
. = ..()
|
||||
starting_x = x
|
||||
starting_y = y
|
||||
starting_z = z
|
||||
|
||||
/datum/point/vector/copy_to(datum/point/vector/v = new)
|
||||
..(v)
|
||||
v.speed = speed
|
||||
v.iteration = iteration
|
||||
v.angle = angle
|
||||
v.mpx = mpx
|
||||
v.mpy = mpy
|
||||
v.starting_x = starting_x
|
||||
v.starting_y = starting_y
|
||||
v.starting_z = starting_z
|
||||
return v
|
||||
|
||||
/datum/point/vector/proc/initialize_trajectory(pixel_speed, new_angle)
|
||||
if(!isnull(pixel_speed))
|
||||
speed = pixel_speed
|
||||
set_angle(new_angle)
|
||||
|
||||
/datum/point/vector/proc/set_angle(new_angle) //calculations use "byond angle" where north is 0 instead of 90, and south is 180 instead of 270.
|
||||
if(isnull(angle))
|
||||
return
|
||||
angle = new_angle
|
||||
update_offsets()
|
||||
|
||||
/datum/point/vector/proc/update_offsets()
|
||||
mpx = sin(angle) * speed
|
||||
mpy = cos(angle) * speed
|
||||
|
||||
/datum/point/vector/proc/set_speed(new_speed)
|
||||
if(isnull(new_speed) || speed == new_speed)
|
||||
return
|
||||
speed = new_speed
|
||||
update_offsets()
|
||||
|
||||
/datum/point/vector/proc/increment(multiplier = 1)
|
||||
iteration++
|
||||
x += mpx * 1
|
||||
y += mpy * 1
|
||||
if(mapcheck())
|
||||
on_z_change()
|
||||
|
||||
/datum/point/vector/proc/return_vector_after_increments(amount = 7, multiplier = 1, force_simulate = FALSE)
|
||||
var/datum/point/vector/v = copy_to()
|
||||
if(force_simulate)
|
||||
for(var/i in 1 to amount)
|
||||
v.increment(multiplier)
|
||||
else
|
||||
v.increment(multiplier * amount)
|
||||
return v
|
||||
|
||||
/datum/point/vector/proc/on_z_change()
|
||||
return
|
||||
|
||||
/datum/point/vector/processed //pixel_speed is per decisecond.
|
||||
var/last_process = 0
|
||||
var/last_move = 0
|
||||
var/paused = FALSE
|
||||
|
||||
/datum/point/vector/processed/Destroy()
|
||||
STOP_PROCESSING(SSprojectiles, src)
|
||||
|
||||
/datum/point/vector/processed/proc/start()
|
||||
last_process = world.time
|
||||
last_move = world.time
|
||||
START_PROCESSING(SSprojectiles, src)
|
||||
|
||||
/datum/point/vector/processed/process()
|
||||
if(paused)
|
||||
last_move += world.time - last_process
|
||||
last_process = world.time
|
||||
return
|
||||
var/needed_time = world.time - last_move
|
||||
last_process = world.time
|
||||
last_move = world.time
|
||||
increment(needed_time)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
var/mach = 0
|
||||
|
||||
/datum/station_state/proc/count()
|
||||
for(var/Z in GLOB.station_z_levels)
|
||||
for(var/Z in SSmapping.levels_by_trait(ZTRAIT_STATION))
|
||||
for(var/turf/T in block(locate(1,1,Z), locate(world.maxx,world.maxy,Z)))
|
||||
// don't count shuttles since they may have just left
|
||||
if(istype(T.loc, /area/shuttle))
|
||||
|
||||
@@ -98,9 +98,9 @@
|
||||
for(var/mob/living/carbon/C in GLOB.mob_list)
|
||||
var/mob/living/simple_animal/borer/D = C.has_brain_worms()
|
||||
var/turf/location = get_turf(C)
|
||||
if(location.z == ZLEVEL_CENTCOM && D && D.stat != DEAD)
|
||||
if(is_centcom_level(location.z) && D && D.stat != DEAD)
|
||||
total_borer_hosts++
|
||||
if(target_amount <= total_borer_hosts)
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
return FALSE
|
||||
|
||||
@@ -140,6 +140,9 @@
|
||||
hierophant_message("<span class='large_brass bold'>With the conversion of a new servant the Ark's power grows. Application scriptures are now available.</span>")
|
||||
if(add_servant_of_ratvar(L))
|
||||
L.log_message("<font color=#BE8700>Conversion was done with a [sigil_name].</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/M = L
|
||||
M.uncuff()
|
||||
L.Knockdown(50) //Completely defenseless for five seconds - mainly to give them time to read over the information they've just been presented with
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
|
||||
@@ -146,12 +146,15 @@
|
||||
countdown = null
|
||||
for(var/mob/L in GLOB.player_list)
|
||||
if(L.z == z)
|
||||
L.forceMove(get_turf(pick(GLOB.generic_event_spawns)))
|
||||
var/atom/movable/target = L
|
||||
if(isobj(L.loc))
|
||||
target = L.loc
|
||||
target.forceMove(get_turf(pick(GLOB.generic_event_spawns)))
|
||||
L.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
|
||||
L.clear_fullscreen("flash", 30)
|
||||
if(isliving(L))
|
||||
var/mob/living/LI = L
|
||||
LI.Stun(50)
|
||||
L.clear_fullscreen("flash", 30)
|
||||
if(isliving(L))
|
||||
var/mob/living/LI = L
|
||||
LI.Stun(50)
|
||||
for(var/obj/effect/clockwork/city_of_cogs_rift/R in GLOB.all_clockwork_objects)
|
||||
qdel(R)
|
||||
if(GLOB.ark_of_the_clockwork_justiciar == src)
|
||||
|
||||
@@ -102,8 +102,8 @@
|
||||
return
|
||||
wiggle_wiggle = FALSE
|
||||
else
|
||||
user.visible_message("<span class='danger'>You start tenderly lifting [user] off of [src]...</span>", \
|
||||
"<span class='danger'>You start tenderly lifting [user] off of [src]...</span>")
|
||||
user.visible_message("<span class='danger'>[user] starts tenderly lifting [skewee] off of [src]...</span>", \
|
||||
"<span class='danger'>You start tenderly lifting [skewee] off of [src]...</span>")
|
||||
if(!do_after(user, 60, target = skewee))
|
||||
skewee.visible_message("<span class='warning'>[skewee] painfully slides back down [src].</span>")
|
||||
skewee.emote("moan")
|
||||
|
||||
@@ -31,7 +31,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
var/max_i = 10//number of tries to spawn meteor.
|
||||
while(!isspaceturf(pickedstart))
|
||||
var/startSide = pick(GLOB.cardinals)
|
||||
var/startZ = pick(GLOB.station_z_levels)
|
||||
var/startZ = pick(SSmapping.levels_by_trait(ZTRAIT_STATION))
|
||||
pickedstart = spaceDebrisStartLoc(startSide, startZ)
|
||||
pickedgoal = spaceDebrisFinishLoc(startSide, startZ)
|
||||
max_i--
|
||||
@@ -40,7 +40,6 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
var/Me = pickweight(meteortypes)
|
||||
var/obj/effect/meteor/M = new Me(pickedstart, pickedgoal)
|
||||
M.dest = pickedgoal
|
||||
M.z_original = M.z
|
||||
|
||||
/proc/spaceDebrisStartLoc(startSide, Z)
|
||||
var/starty
|
||||
@@ -95,7 +94,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
pass_flags = PASSTABLE
|
||||
var/heavy = 0
|
||||
var/meteorsound = 'sound/effects/meteorimpact.ogg'
|
||||
var/z_original = ZLEVEL_STATION_PRIMARY
|
||||
var/z_original
|
||||
var/threat = 0 // used for determining which meteors are most interesting
|
||||
var/lifetime = DEFAULT_METEOR_LIFETIME
|
||||
var/timerid = null
|
||||
@@ -126,6 +125,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
|
||||
/obj/effect/meteor/Initialize(mapload, target)
|
||||
. = ..()
|
||||
z_original = z
|
||||
GLOB.meteor_list += src
|
||||
SSaugury.register_doom(src, threat)
|
||||
SpinAnimation()
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
APC.interact(usr, GLOB.not_incapacitated_state)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
message_admins("[key_name_admin(usr)] remotely accessed [APC] from [src] at [get_area(src)].")
|
||||
log_game("[key_name_admin(usr)] remotely accessed [APC] from [src] at [get_area(src)].")
|
||||
log_game("[key_name(usr)] remotely accessed [APC] from [src] at [get_area(src)].")
|
||||
if(APC.locked)
|
||||
APC.say("Remote access detected. Interface unlocked.")
|
||||
playsound(APC, 'sound/machines/boltsup.ogg', 25, 0)
|
||||
@@ -196,7 +196,7 @@
|
||||
if(emagged)
|
||||
return
|
||||
user.visible_message("<span class='warning'>You emag [src], disabling precise logging and allowing you to clear logs.</span>")
|
||||
log_game("[key_name_admin(user)] emagged [src] at [get_area(src)], disabling operator tracking.")
|
||||
log_game("[key_name(user)] emagged [src] at [get_area(src)], disabling operator tracking.")
|
||||
playsound(src, "sparks", 50, 1)
|
||||
emagged = TRUE
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
/obj/machinery/computer/camera_advanced/Initialize()
|
||||
. = ..()
|
||||
if(station_lock_override)
|
||||
z_lock = GLOB.station_z_levels.Copy()
|
||||
z_lock = SSmapping.levels_by_trait(ZTRAIT_STATION)
|
||||
|
||||
/obj/machinery/computer/camera_advanced/syndie
|
||||
icon_keyboard = "syndie_key"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// DISCO DANCE MACHINE - For engineering power optimization incentive nurturing test system (POINTS)
|
||||
// DISCO DANCE MACHINE - For admin, engineering and shuttle memes/abuse.
|
||||
|
||||
/obj/machinery/disco
|
||||
name = "radiant dance machine mark IV"
|
||||
@@ -23,6 +23,14 @@
|
||||
)
|
||||
var/datum/track/selection = null
|
||||
|
||||
/obj/machinery/disco/indestructible
|
||||
name = "radiant dance machine mark V"
|
||||
desc = "Now redesigned with data gathered from the extensive disco and plasma research."
|
||||
req_access = null
|
||||
anchored = TRUE
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
flags_1 = NODECONSTRUCT_1
|
||||
|
||||
/datum/track
|
||||
var/song_name = "generic"
|
||||
var/song_path = null
|
||||
@@ -59,7 +67,7 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/disco/attackby(obj/item/O, mob/user, params)
|
||||
if(!active)
|
||||
if(!active && !(flags_1 & NODECONSTRUCT_1))
|
||||
if(istype(O, /obj/item/wrench))
|
||||
if(!anchored && !isinspace())
|
||||
to_chat(user,"<span class='notice'>You secure [src] to the floor.</span>")
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
GLOB.bombers += "[key_name(user)] attached a [item] to a transfer valve."
|
||||
message_admins("[key_name_admin(user)] attached a [item] to a transfer valve.")
|
||||
log_game("[key_name_admin(user)] attached a [item] to a transfer valve.")
|
||||
log_game("[key_name(user)] attached a [item] to a transfer valve.")
|
||||
attacher = user
|
||||
return
|
||||
|
||||
|
||||
@@ -185,11 +185,11 @@
|
||||
return 0
|
||||
objective = stripped_input(usr,"What order do you want to imprint on [C]?","Enter the order","",120)
|
||||
message_admins("[key_name_admin(user)] set brainwash machine objective to '[objective]'.")
|
||||
log_game("[key_name_admin(user)] set brainwash machine objective to '[objective]'.")
|
||||
log_game("[key_name(user)] set brainwash machine objective to '[objective]'.")
|
||||
var/datum/objective/custom_objective = new/datum/objective(objective)
|
||||
custom_objective.owner = C.mind
|
||||
C.mind.objectives += custom_objective
|
||||
C.mind.announce_objectives()
|
||||
message_admins("[key_name_admin(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.")
|
||||
log_game("[key_name_admin(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.")
|
||||
log_game("[key_name(user)] brainwashed [key_name(C)] with objective '[objective]'.")
|
||||
return 1
|
||||
|
||||
@@ -290,7 +290,7 @@
|
||||
resin_cooldown = TRUE
|
||||
R.remove_any(100)
|
||||
var/obj/effect/resin_container/A = new (get_turf(src))
|
||||
log_game("[key_name_admin(user)] used Resin Launcher at [get_area(user)] [COORD(user)].")
|
||||
log_game("[key_name(user)] used Resin Launcher at [get_area(user)] [COORD(user)].")
|
||||
playsound(src,'sound/items/syringeproj.ogg',40,1)
|
||||
for(var/a=0, a<5, a++)
|
||||
step_towards(A, target)
|
||||
|
||||
@@ -414,7 +414,7 @@
|
||||
message_admins("An explosion has triggered a gibtonite deposit reaction at [A.name] [ADMIN_JMP(bombturf)].")
|
||||
|
||||
if(!triggered_by_explosion)
|
||||
log_game("[key_name(user)] has triggered a gibtonite deposit reaction at [A.name] [ADMIN_JMP(bombturf)].")
|
||||
log_game("[key_name(user)] has triggered a gibtonite deposit reaction at [A.name] [COORD(bombturf)].")
|
||||
else
|
||||
log_game("An explosion has triggered a gibtonite deposit reaction at [A.name] [COORD(bombturf)]")
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define RANDOM_LOWER_X 50
|
||||
#define RANDOM_LOWER_Y 50
|
||||
|
||||
/proc/spawn_rivers(target_z = ZLEVEL_LAVALAND, nodes = 4, turf_type = /turf/open/lava/smooth/lava_land_surface, whitelist_area = /area/lavaland/surface/outdoors, min_x = RANDOM_LOWER_X, min_y = RANDOM_LOWER_Y, max_x = RANDOM_UPPER_X, max_y = RANDOM_UPPER_Y)
|
||||
/proc/spawn_rivers(target_z, nodes = 4, turf_type = /turf/open/lava/smooth/lava_land_surface, whitelist_area = /area/lavaland/surface/outdoors, min_x = RANDOM_LOWER_X, min_y = RANDOM_LOWER_Y, max_x = RANDOM_UPPER_X, max_y = RANDOM_UPPER_Y)
|
||||
var/list/river_nodes = list()
|
||||
var/num_spawned = 0
|
||||
while(num_spawned < nodes)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
return
|
||||
|
||||
if(!isobserver(usr))
|
||||
log_game("[key_name_admin(usr)] checked the player panel while in game.")
|
||||
log_game("[key_name(usr)] checked the player panel while in game.")
|
||||
|
||||
if(!M)
|
||||
to_chat(usr, "You seem to be selecting a mob that doesn't exist anymore.")
|
||||
|
||||
@@ -1242,7 +1242,7 @@
|
||||
to_chat(usr, "<span class='danger'>Failed to apply ban.</span>")
|
||||
return
|
||||
ban_unban_log_save("[key_name(usr)] has permabanned [key_name(M)]. - Reason: [reason] - This is a permanent ban.")
|
||||
log_admin_private("[key_name(usr)] has banned [key_name_admin(M)].\nReason: [reason]\nThis is a permanent ban.")
|
||||
log_admin_private("[key_name(usr)] has banned [key_name(M)].\nReason: [reason]\nThis is a permanent ban.")
|
||||
var/msg = "<span class='adminnotice'>[key_name_admin(usr)] has banned [key_name_admin(M)].\nReason: [reason]\nThis is a permanent ban.</span>"
|
||||
message_admins(msg)
|
||||
var/datum/admin_help/AH = M.client ? M.client.current_ticket : null
|
||||
|
||||
@@ -9,17 +9,17 @@
|
||||
//all plumbing - yes, some things might get stated twice, doesn't matter.
|
||||
for (var/obj/machinery/atmospherics/plumbing in GLOB.machines)
|
||||
if (plumbing.nodealert)
|
||||
to_chat(usr, "Unconnected [plumbing.name] located at [plumbing.x],[plumbing.y],[plumbing.z] ([get_area(plumbing.loc)])")
|
||||
to_chat(usr, "Unconnected [plumbing.name] located at [ADMIN_COORDJMP(plumbing)] ([get_area(plumbing.loc)])")
|
||||
|
||||
//Manifolds
|
||||
for (var/obj/machinery/atmospherics/pipe/manifold/pipe in GLOB.machines)
|
||||
if (!pipe.nodes[1] || !pipe.nodes[2] || !pipe.nodes[3])
|
||||
to_chat(usr, "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])")
|
||||
to_chat(usr, "Unconnected [pipe.name] located at [ADMIN_COORDJMP(pipe)] ([get_area(pipe.loc)])")
|
||||
|
||||
//Pipes
|
||||
for (var/obj/machinery/atmospherics/pipe/simple/pipe in GLOB.machines)
|
||||
if (!pipe.nodes[1] || !pipe.nodes[2])
|
||||
to_chat(usr, "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])")
|
||||
to_chat(usr, "Unconnected [pipe.name] located at [ADMIN_COORDJMP(pipe)] ([get_area(pipe.loc)])")
|
||||
|
||||
/client/proc/powerdebug()
|
||||
set category = "Mapping"
|
||||
@@ -33,9 +33,9 @@
|
||||
if (!PN.nodes || !PN.nodes.len)
|
||||
if(PN.cables && (PN.cables.len > 1))
|
||||
var/obj/structure/cable/C = PN.cables[1]
|
||||
to_chat(usr, "Powernet with no nodes! (number [PN.number]) - example cable at [C.x], [C.y], [C.z] in area [get_area(C.loc)]")
|
||||
to_chat(usr, "Powernet with no nodes! (number [PN.number]) - example cable at [ADMIN_COORDJMP(C)] in area [get_area(C.loc)]")
|
||||
|
||||
if (!PN.cables || (PN.cables.len < 10))
|
||||
if(PN.cables && (PN.cables.len > 1))
|
||||
var/obj/structure/cable/C = PN.cables[1]
|
||||
to_chat(usr, "Powernet with fewer than 10 cables! (number [PN.number]) - example cable at [C.x], [C.y], [C.z] in area [get_area(C.loc)]")
|
||||
to_chat(usr, "Powernet with fewer than 10 cables! (number [PN.number]) - example cable at [ADMIN_COORDJMP(C)] in area [get_area(C.loc)]")
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
organ = organs[organ]
|
||||
organ = new organ
|
||||
organ.Insert(C)
|
||||
log_admin("[key_name(usr)] has added organ [organ.type] to [key_name(C)]")
|
||||
message_admins("[key_name_admin(usr)] has added organ [organ.type] to [key_name(C)]")
|
||||
|
||||
if("add implant")
|
||||
for(var/path in subtypesof(/obj/item/implant))
|
||||
@@ -24,6 +26,8 @@
|
||||
organ = organs[organ]
|
||||
organ = new organ
|
||||
organ.implant(C)
|
||||
log_admin("[key_name(usr)] has added implant [organ.type] to [key_name(C)]")
|
||||
message_admins("[key_name_admin(usr)] has added implant [organ.type] to [key_name(C)]")
|
||||
|
||||
if("drop organ/implant", "remove organ/implant")
|
||||
for(var/X in C.internal_organs)
|
||||
@@ -41,6 +45,9 @@
|
||||
var/obj/item/organ/O
|
||||
var/obj/item/implant/I
|
||||
|
||||
log_admin("[key_name(usr)] has removed [organ.type] from [key_name(C)]")
|
||||
message_admins("[key_name_admin(usr)] has removed [organ.type] from [key_name(C)]")
|
||||
|
||||
if(isorgan(organ))
|
||||
O = organ
|
||||
O.Remove(C)
|
||||
|
||||
@@ -45,7 +45,8 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
|
||||
/client/proc/start_line_profiling,
|
||||
/client/proc/stop_line_profiling,
|
||||
/client/proc/show_line_profiling,
|
||||
/client/proc/create_mapping_job_icons
|
||||
/client/proc/create_mapping_job_icons,
|
||||
/client/proc/debug_z_levels,
|
||||
))
|
||||
|
||||
/obj/effect/debugging/mapfix_marker
|
||||
@@ -96,28 +97,28 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
|
||||
for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
CL += C
|
||||
|
||||
var/output = {"<B>CAMERA ANNOMALITIES REPORT</B><HR>
|
||||
<B>The following annomalities have been detected. The ones in red need immediate attention: Some of those in black may be intentional.</B><BR><ul>"}
|
||||
var/output = {"<B>Camera Abnormalities Report</B><HR>
|
||||
<B>The following abnormalities have been detected. The ones in red need immediate attention: Some of those in black may be intentional.</B><BR><ul>"}
|
||||
|
||||
for(var/obj/machinery/camera/C1 in CL)
|
||||
for(var/obj/machinery/camera/C2 in CL)
|
||||
if(C1 != C2)
|
||||
if(C1.c_tag == C2.c_tag)
|
||||
output += "<li><font color='red'>c_tag match for sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) and \[[C2.x], [C2.y], [C2.z]\] ([C2.loc.loc]) - c_tag is [C1.c_tag]</font></li>"
|
||||
output += "<li><font color='red'>c_tag match for cameras at [ADMIN_COORDJMP(C1)] ([C1.loc.loc]) and [ADMIN_COORDJMP(C2)] ([C2.loc.loc]) - c_tag is [C1.c_tag]</font></li>"
|
||||
if(C1.loc == C2.loc && C1.dir == C2.dir && C1.pixel_x == C2.pixel_x && C1.pixel_y == C2.pixel_y)
|
||||
output += "<li><font color='red'>FULLY overlapping sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Networks: [C1.network] and [C2.network]</font></li>"
|
||||
output += "<li><font color='red'>FULLY overlapping cameras at [ADMIN_COORDJMP(C1)] ([C1.loc.loc]) Networks: [json_encode(C1.network)] and [json_encode(C2.network)]</font></li>"
|
||||
if(C1.loc == C2.loc)
|
||||
output += "<li>overlapping sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Networks: [C1.network] and [C2.network]</font></li>"
|
||||
output += "<li>Overlapping cameras at [ADMIN_COORDJMP(C1)] ([C1.loc.loc]) Networks: [json_encode(C1.network)] and [json_encode(C2.network)]</li>"
|
||||
var/turf/T = get_step(C1,turn(C1.dir,180))
|
||||
if(!T || !isturf(T) || !T.density )
|
||||
if(!(locate(/obj/structure/grille,T)))
|
||||
if(!(locate(/obj/structure/grille) in T))
|
||||
var/window_check = 0
|
||||
for(var/obj/structure/window/W in T)
|
||||
if (W.dir == turn(C1.dir,180) || W.dir in list(5,6,9,10) )
|
||||
window_check = 1
|
||||
break
|
||||
if(!window_check)
|
||||
output += "<li><font color='red'>Camera not connected to wall at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Network: [C1.network]</color></li>"
|
||||
output += "<li><font color='red'>Camera not connected to wall at [ADMIN_COORDJMP(C1)] ([C1.loc.loc]) Network: [json_encode(C1.network)]</font></li>"
|
||||
|
||||
output += "</ul>"
|
||||
usr << browse(output,"window=airreport;size=1000x500")
|
||||
@@ -292,4 +293,64 @@ GLOBAL_VAR_INIT(say_disabled, FALSE)
|
||||
//Also add the x
|
||||
for(var/x_number in 1 to 4)
|
||||
final.Insert(icon('icons/mob/screen_gen.dmi', "x[x_number == 1 ? "" : x_number]"), "x[x_number == 1 ? "" : x_number]")
|
||||
fcopy(final, "icons/mob/landmarks.dmi")
|
||||
fcopy(final, "icons/mob/landmarks.dmi")
|
||||
|
||||
/client/proc/debug_z_levels()
|
||||
set name = "Debug Z-Levels"
|
||||
set category = "Mapping"
|
||||
|
||||
var/list/z_list = SSmapping.z_list
|
||||
var/list/messages = list()
|
||||
messages += "<b>World</b>: [world.maxx] x [world.maxy] x [world.maxz]<br>"
|
||||
|
||||
var/list/linked_levels = list()
|
||||
var/min_x = INFINITY
|
||||
var/min_y = INFINITY
|
||||
var/max_x = -INFINITY
|
||||
var/max_y = -INFINITY
|
||||
|
||||
for(var/z in 1 to max(world.maxz, z_list.len))
|
||||
if (z > z_list.len)
|
||||
messages += "<b>[z]</b>: Unmanaged (out of bounds)<br>"
|
||||
continue
|
||||
var/datum/space_level/S = z_list[z]
|
||||
if (!S)
|
||||
messages += "<b>[z]</b>: Unmanaged (null)<br>"
|
||||
continue
|
||||
var/linkage
|
||||
switch (S.linkage)
|
||||
if (UNAFFECTED)
|
||||
linkage = "no linkage"
|
||||
if (SELFLOOPING)
|
||||
linkage = "self-looping"
|
||||
if (CROSSLINKED)
|
||||
linkage = "linked at ([S.xi], [S.yi])"
|
||||
linked_levels += S
|
||||
min_x = min(min_x, S.xi)
|
||||
min_y = min(min_y, S.yi)
|
||||
max_x = max(max_x, S.xi)
|
||||
max_y = max(max_y, S.yi)
|
||||
else
|
||||
linkage = "unknown linkage '[S.linkage]'"
|
||||
|
||||
messages += "<b>[z]</b>: [S.name], [linkage], traits: [json_encode(S.traits)]<br>"
|
||||
if (S.z_value != z)
|
||||
messages += "-- z_value is [S.z_value], should be [z]<br>"
|
||||
if (S.name == initial(S.name))
|
||||
messages += "-- name not set<br>"
|
||||
if (z > world.maxz)
|
||||
messages += "-- exceeds max z"
|
||||
|
||||
var/grid[max_x - min_x + 1][max_y - min_y + 1]
|
||||
for(var/datum/space_level/S in linked_levels)
|
||||
grid[S.xi - min_x + 1][S.yi - min_y + 1] = S.z_value
|
||||
|
||||
messages += "<table border='1'>"
|
||||
for(var/y in max_y to min_y step -1)
|
||||
var/list/part = list()
|
||||
for(var/x in min_x to max_x)
|
||||
part += "[grid[x - min_x + 1][y - min_y + 1]]"
|
||||
messages += "<tr><td>[part.Join("</td><td>")]</td></tr>"
|
||||
messages += "</table>"
|
||||
|
||||
to_chat(src, messages.Join(""))
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
gas_type = /datum/gas/plasma
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/bz
|
||||
name = "BZ canister"
|
||||
name = "\improper BZ canister"
|
||||
desc = "BZ, a powerful hallucinogenic nerve agent."
|
||||
icon_state = "purple"
|
||||
gas_type = /datum/gas/bz
|
||||
@@ -383,7 +383,7 @@
|
||||
if(newtype)
|
||||
var/obj/machinery/portable_atmospherics/canister/replacement = newtype
|
||||
name = initial(replacement.name)
|
||||
desc = initial(replacement.name)
|
||||
desc = initial(replacement.desc)
|
||||
icon_state = initial(replacement.icon_state)
|
||||
if("restricted")
|
||||
restricted = !restricted
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
var/question = "Travel back?"
|
||||
var/list/zlevels = list()
|
||||
var/list/zlevels
|
||||
|
||||
/obj/structure/signpost/New()
|
||||
. = ..()
|
||||
set_light(2)
|
||||
zlevels = GLOB.station_z_levels
|
||||
zlevels = SSmapping.levels_by_trait(ZTRAIT_STATION)
|
||||
|
||||
/obj/structure/signpost/attackby(obj/item/W, mob/user, params)
|
||||
return attack_hand(user)
|
||||
@@ -44,6 +44,6 @@
|
||||
zlevels = list()
|
||||
for(var/i in 1 to world.maxz)
|
||||
zlevels += i
|
||||
zlevels -= ZLEVEL_CENTCOM // no easy victory, even with meme signposts
|
||||
zlevels -= SSmapping.levels_by_trait(ZTRAIT_CENTCOM) // no easy victory, even with meme signposts
|
||||
// also, could you think of the horror if they ended up in a holodeck
|
||||
// template or something
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
var/obj/item/clothing/gloves/G = gloves
|
||||
G.add_blood_DNA(blood_dna)
|
||||
else if(length(blood_dna))
|
||||
AddComponent(/datum/component/forensics, null, null, dna)
|
||||
AddComponent(/datum/component/forensics, null, null, blood_dna)
|
||||
bloody_hands = rand(2, 4)
|
||||
update_inv_gloves() //handles bloody hands overlays and updating
|
||||
return TRUE
|
||||
|
||||
@@ -32,8 +32,9 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
||||
/datum/round_event/immovable_rod/start()
|
||||
var/datum/round_event_control/immovable_rod/C = control
|
||||
var/startside = pick(GLOB.cardinals)
|
||||
var/turf/startT = spaceDebrisStartLoc(startside, ZLEVEL_STATION_PRIMARY)
|
||||
var/turf/endT = spaceDebrisFinishLoc(startside, ZLEVEL_STATION_PRIMARY)
|
||||
var/z = pick(SSmapping.levels_by_trait(ZTRAIT_STATION))
|
||||
var/turf/startT = spaceDebrisStartLoc(startside, z)
|
||||
var/turf/endT = spaceDebrisFinishLoc(startside, z)
|
||||
new /obj/effect/immovablerod(startT, endT, C.special_target)
|
||||
|
||||
/obj/effect/immovablerod
|
||||
@@ -60,7 +61,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
||||
enter_link="<a href=?src=[REF(src)];orbit=1>(Click to orbit)</a>",
|
||||
source=src, action=NOTIFY_ORBIT)
|
||||
GLOB.poi_list += src
|
||||
|
||||
|
||||
var/special_target_valid = FALSE
|
||||
if(special_target)
|
||||
var/turf/T = get_turf(special_target)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/datum/space_level
|
||||
var/name = "Your config settings failed, you need to fix this for the datum space levels to work"
|
||||
var/list/neigbours = list()
|
||||
var/list/traits
|
||||
var/z_value = 1 //actual z placement
|
||||
var/linkage = SELFLOOPING
|
||||
var/xi
|
||||
var/yi //imaginary placements on the grid
|
||||
|
||||
/datum/space_level/New(new_z, new_name, new_linkage = SELFLOOPING, list/new_traits = list())
|
||||
z_value = new_z
|
||||
name = new_name
|
||||
traits = new_traits
|
||||
set_linkage(new_linkage)
|
||||
+18
-44
@@ -1,18 +1,6 @@
|
||||
//This is a simple 3 by 3 grid working off the corpse of the space torus. The donut is dead, cube has been avenged!
|
||||
|
||||
GLOBAL_LIST_EMPTY(z_levels_list)
|
||||
|
||||
/datum/space_level
|
||||
var/name = "Your config settings failed, you need to fix this for the datum space levels to work"
|
||||
var/list/neigbours = list()
|
||||
var/z_value = 1 //actual z placement
|
||||
var/linked = SELFLOOPING
|
||||
var/xi
|
||||
var/yi //imaginary placements on the grid
|
||||
|
||||
/datum/space_level/New(transition_type)
|
||||
linked = transition_type
|
||||
if(linked == SELFLOOPING)
|
||||
/datum/space_level/proc/set_linkage(new_linkage)
|
||||
linkage = new_linkage
|
||||
if(linkage == SELFLOOPING)
|
||||
neigbours = list()
|
||||
var/list/L = list(TEXT_NORTH,TEXT_SOUTH,TEXT_EAST,TEXT_WEST)
|
||||
for(var/A in L)
|
||||
@@ -69,21 +57,15 @@ GLOBAL_LIST_EMPTY(z_levels_list)
|
||||
if(y-1 >= 1)
|
||||
neigbours |= grid[x][y-1]
|
||||
|
||||
/proc/setup_map_transitions() //listamania
|
||||
/datum/controller/subsystem/mapping/proc/setup_map_transitions() //listamania
|
||||
var/list/SLS = list()
|
||||
var/datum/space_level/D
|
||||
var/list/cached_transitions = SSmapping.config.transition_config
|
||||
var/conf_set_len = cached_transitions.len
|
||||
var/k = 1
|
||||
for(var/A in cached_transitions)
|
||||
D = new(cached_transitions[A])
|
||||
D.name = A
|
||||
D.z_value = k
|
||||
if(D.linked != CROSSLINKED)
|
||||
GLOB.z_levels_list["[D.z_value]"] = D
|
||||
else
|
||||
var/list/cached_z_list = z_list
|
||||
var/conf_set_len = 0
|
||||
for(var/A in cached_z_list)
|
||||
var/datum/space_level/D = A
|
||||
if (D.linkage == CROSSLINKED)
|
||||
SLS.Add(D)
|
||||
k++
|
||||
conf_set_len++
|
||||
var/list/point_grid[conf_set_len*2+1][conf_set_len*2+1]
|
||||
var/list/grid = list()
|
||||
var/datum/space_transition_point/P
|
||||
@@ -99,7 +81,7 @@ GLOBAL_LIST_EMPTY(z_levels_list)
|
||||
var/list/used_points = list()
|
||||
grid.Cut()
|
||||
while(SLS.len)
|
||||
D = pick_n_take(SLS)
|
||||
var/datum/space_level/D = pick_n_take(SLS)
|
||||
D.xi = P.x
|
||||
D.yi = P.y
|
||||
P.spl = D
|
||||
@@ -108,10 +90,7 @@ GLOBAL_LIST_EMPTY(z_levels_list)
|
||||
possible_points.Remove(used_points)
|
||||
D.set_neigbours(used_points)
|
||||
P = pick(possible_points)
|
||||
grid["[D.z_value]"] = D
|
||||
|
||||
for(var/A in GLOB.z_levels_list)
|
||||
grid[A] = GLOB.z_levels_list[A]
|
||||
CHECK_TICK
|
||||
|
||||
//Lists below are pre-calculated values arranged in the list in such a way to be easily accessable in the loop by the counter
|
||||
//Its either this or madness with lotsa math
|
||||
@@ -123,13 +102,12 @@ GLOBAL_LIST_EMPTY(z_levels_list)
|
||||
var/list/x_pos_transition = list(1, 1, TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2) //values of x for the transition from respective blocks on the side of zlevel, 1 is being translated into turfs respective x value later in the code
|
||||
var/list/y_pos_transition = list(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2, 1, 1) //values of y for the transition from respective blocks on the side of zlevel, 1 is being translated into turfs respective y value later in the code
|
||||
|
||||
for(var/zlevelnumber = 1, zlevelnumber<=grid.len, zlevelnumber++)
|
||||
D = grid["[zlevelnumber]"]
|
||||
if(!D)
|
||||
CRASH("[zlevelnumber] position has no space level datum.")
|
||||
if(!(D.neigbours.len))
|
||||
for(var/I in cached_z_list)
|
||||
var/datum/space_level/D = I
|
||||
if(!D.neigbours.len)
|
||||
continue
|
||||
for(var/side = 1, side<5, side++)
|
||||
var/zlevelnumber = D.z_value
|
||||
for(var/side in 1 to 4)
|
||||
var/turf/beginning = locate(x_pos_beginning[side], y_pos_beginning[side], zlevelnumber)
|
||||
var/turf/ending = locate(x_pos_ending[side], y_pos_ending[side], zlevelnumber)
|
||||
var/list/turfblock = block(beginning, ending)
|
||||
@@ -143,12 +121,8 @@ GLOBAL_LIST_EMPTY(z_levels_list)
|
||||
while(D.neigbours["[dirside]"] && D.neigbours["[dirside]"] != D)
|
||||
D = D.neigbours["[dirside]"]
|
||||
zdestination = D.z_value
|
||||
D = grid["[zlevelnumber]"]
|
||||
D = I
|
||||
for(var/turf/open/space/S in turfblock)
|
||||
S.destination_x = x_pos_transition[side] == 1 ? S.x : x_pos_transition[side]
|
||||
S.destination_y = y_pos_transition[side] == 1 ? S.y : y_pos_transition[side]
|
||||
S.destination_z = zdestination
|
||||
//S.maptext = "[zdestination]" // for debugging
|
||||
|
||||
for(var/A in grid)
|
||||
GLOB.z_levels_list[A] = grid[A]
|
||||
@@ -0,0 +1,46 @@
|
||||
// Look up levels[z].traits[trait]
|
||||
/datum/controller/subsystem/mapping/proc/level_trait(z, trait)
|
||||
if (!z)
|
||||
return null
|
||||
var/list/trait_list
|
||||
if (z_list)
|
||||
var/datum/space_level/S = get_level(z)
|
||||
trait_list = S.traits
|
||||
else
|
||||
var/list/default_map_traits = DEFAULT_MAP_TRAITS
|
||||
trait_list = default_map_traits[z][DL_TRAITS]
|
||||
return trait_list[trait]
|
||||
|
||||
// Check if levels[z] has any of the specified traits
|
||||
/datum/controller/subsystem/mapping/proc/level_has_any_trait(z, list/traits)
|
||||
for (var/I in traits)
|
||||
if (level_trait(z, I))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
// Check if levels[z] has all of the specified traits
|
||||
/datum/controller/subsystem/mapping/proc/level_has_all_traits(z, list/traits)
|
||||
for (var/I in traits)
|
||||
if (!level_trait(z, I))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
// Get a list of all z which have the specified trait
|
||||
/datum/controller/subsystem/mapping/proc/levels_by_trait(trait)
|
||||
. = list()
|
||||
var/list/_z_list = z_list
|
||||
for(var/A in _z_list)
|
||||
var/datum/space_level/S = A
|
||||
if (S.traits[trait])
|
||||
. += S.z_value
|
||||
|
||||
// Get a list of all z which have any of the specified traits
|
||||
/datum/controller/subsystem/mapping/proc/levels_by_any_trait(list/traits)
|
||||
. = list()
|
||||
var/list/_z_list = z_list
|
||||
for(var/A in _z_list)
|
||||
var/datum/space_level/S = A
|
||||
for (var/trait in traits)
|
||||
if (S.traits[trait])
|
||||
. += S.z_value
|
||||
break
|
||||
@@ -0,0 +1,32 @@
|
||||
// Populate the space level list and prepare space transitions
|
||||
/datum/controller/subsystem/mapping/proc/InitializeDefaultZLevels()
|
||||
if (z_list) // subsystem/Recover or badminnery, no need
|
||||
return
|
||||
|
||||
z_list = list()
|
||||
var/list/default_map_traits = DEFAULT_MAP_TRAITS
|
||||
|
||||
if (default_map_traits.len != world.maxz)
|
||||
WARNING("More or less map attributes pre-defined ([default_map_traits.len]) than existent z-levels ([world.maxz]). Ignoring the larger.")
|
||||
if (default_map_traits.len > world.maxz)
|
||||
default_map_traits.Cut(world.maxz + 1)
|
||||
|
||||
for (var/I in 1 to default_map_traits.len)
|
||||
var/list/features = default_map_traits[I]
|
||||
var/datum/space_level/S = new(I, features[DL_NAME], features[DL_LINKAGE], features[DL_TRAITS])
|
||||
z_list += S
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/add_new_zlevel(name, linkage = SELFLOOPING, traits = list(), z_type = /datum/space_level)
|
||||
var/new_z = z_list.len + 1
|
||||
if (world.maxz < new_z)
|
||||
++world.maxz
|
||||
CHECK_TICK
|
||||
// TODO: sleep here if the Z level needs to be cleared
|
||||
var/datum/space_level/S = new z_type(new_z, name, linkage, traits)
|
||||
z_list += S
|
||||
return new_z
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/get_level(z)
|
||||
. = z_list[z]
|
||||
if (!.)
|
||||
CRASH("Unmanaged z-level: '[z]'")
|
||||
@@ -102,7 +102,10 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
|
||||
|
||||
if(href_list["random"] && !possible_destinations)
|
||||
usr.changeNext_move(CLICK_CD_RAPID) //Anti-spam
|
||||
var/turf/LZ = safepick(Z_TURFS(ZLEVEL_MINING)) //Pick a random mining Z-level turf
|
||||
var/list/all_mining_turfs = list()
|
||||
for (var/z_level in SSmapping.levels_by_trait(ZTRAIT_MINING))
|
||||
all_mining_turfs += Z_TURFS(z_level)
|
||||
var/turf/LZ = safepick(all_mining_turfs) //Pick a random mining Z-level turf
|
||||
if(!ismineralturf(LZ) && !istype(LZ, /turf/open/floor/plating/asteroid))
|
||||
//Find a suitable mining turf. Reduces chance of landing in a bad area
|
||||
to_chat(usr, "<span class='warning'>Landing zone scan failed. Please try again.</span>")
|
||||
|
||||
@@ -231,6 +231,19 @@
|
||||
message_param = "points at %t."
|
||||
restraint_check = TRUE
|
||||
|
||||
/datum/emote/living/point/run_emote(mob/user, params)
|
||||
message_param = initial(message_param) // reset
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.get_num_arms() == 0)
|
||||
if(H.get_num_legs() != 0)
|
||||
message_param = "tries to point at %t with a leg, <span class='userdanger'>falling down</span> in the process!"
|
||||
H.Knockdown(20)
|
||||
else
|
||||
message_param = "<span class='userdanger'>bumps their head on the ground</span> trying to motion towards %t."
|
||||
H.adjustBrainLoss(5)
|
||||
..()
|
||||
|
||||
/datum/emote/living/pout
|
||||
key = "pout"
|
||||
key_third_person = "pouts"
|
||||
|
||||
@@ -888,13 +888,16 @@
|
||||
..()
|
||||
if(health < maxHealth*0.5) //Gradual break down of modules as more damage is sustained
|
||||
if(uneq_module(held_items[3]))
|
||||
to_chat(src, "<span class='warning'>SYSTEM ERROR: Module 3 OFFLINE.</span>")
|
||||
playsound(loc, 'sound/machines/warning-buzzer.ogg', 50, 1, 1)
|
||||
visible_message("<span class='warning'>[src] sounds an alarm! \"SYSTEM ERROR: Module 3 OFFLINE.\"</span>", "<span class='userdanger'>SYSTEM ERROR: Module 3 OFFLINE.</span>")
|
||||
if(health < 0)
|
||||
if(uneq_module(held_items[2]))
|
||||
to_chat(src, "<span class='warning'>SYSTEM ERROR: Module 2 OFFLINE.</span>")
|
||||
visible_message("<span class='warning'>[src] sounds an alarm! \"SYSTEM ERROR: Module 2 OFFLINE.\"</span>", "<span class='userdanger'>SYSTEM ERROR: Module 2 OFFLINE.</span>")
|
||||
playsound(loc, 'sound/machines/warning-buzzer.ogg', 60, 1, 1)
|
||||
if(health < -maxHealth*0.5)
|
||||
if(uneq_module(held_items[1]))
|
||||
to_chat(src, "<span class='warning'>CRITICAL ERROR: All modules OFFLINE.</span>")
|
||||
visible_message("<span class='warning'>[src] sounds an alarm! \"CRITICAL ERROR: All modules OFFLINE.\"</span>", "<span class='userdanger'>CRITICAL ERROR: All modules OFFLINE.</span>")
|
||||
playsound(loc, 'sound/machines/warning-buzzer.ogg', 75, 1, 1)
|
||||
|
||||
/mob/living/silicon/robot/update_sight()
|
||||
if(!client)
|
||||
|
||||
@@ -161,7 +161,7 @@ Auto Patrol[]"},
|
||||
final = final|JUDGE_RECORDCHECK
|
||||
if(weaponscheck)
|
||||
final = final|JUDGE_WEAPONCHECK
|
||||
if(emagged)
|
||||
if(emagged == 2)
|
||||
final = final|JUDGE_EMAGGED
|
||||
//ED209's ignore monkeys
|
||||
final = final|JUDGE_IGNOREMONKEYS
|
||||
|
||||
@@ -102,7 +102,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
|
||||
var/final = NONE
|
||||
if(check_records)
|
||||
final = final|JUDGE_RECORDCHECK
|
||||
if(emagged)
|
||||
if(emagged == 2)
|
||||
final = final|JUDGE_EMAGGED
|
||||
return final
|
||||
|
||||
|
||||
@@ -353,6 +353,11 @@
|
||||
if(emagged == 2) //Everyone needs our medicine. (Our medicine is toxins)
|
||||
return TRUE
|
||||
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if((H.head && (H.head.flags_1 & THICKMATERIAL_1)) && (H.wear_suit && (H.wear_suit.flags_1 & THICKMATERIAL_1)))
|
||||
return FALSE // Skip over them if they have no exposed flesh.
|
||||
|
||||
if(declare_crit && C.health <= 0) //Critical condition! Call for help!
|
||||
declare(C)
|
||||
|
||||
@@ -479,7 +484,7 @@
|
||||
C.visible_message("<span class='danger'>[src] is trying to inject [patient]!</span>", \
|
||||
"<span class='userdanger'>[src] is trying to inject you!</span>")
|
||||
|
||||
var/failed = FALSE;
|
||||
var/failed = FALSE
|
||||
if(do_mob(src, patient, 30)) //Is C == patient? This is so confusing
|
||||
if((get_dist(src, patient) <= 1) && (on) && assess_patient(patient))
|
||||
if(reagent_id == "internal_beaker")
|
||||
|
||||
@@ -163,7 +163,7 @@ Auto Patrol: []"},
|
||||
final = final|JUDGE_RECORDCHECK
|
||||
if(weaponscheck)
|
||||
final = final|JUDGE_WEAPONCHECK
|
||||
if(emagged)
|
||||
if(emagged == 2)
|
||||
final = final|JUDGE_EMAGGED
|
||||
return final
|
||||
|
||||
|
||||
@@ -318,6 +318,11 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/harvester/AttackingTarget()
|
||||
if(iscarbon(target))
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(H.dna && H.dna.species)
|
||||
if(NODISMEMBER in H.dna.species.species_traits)
|
||||
return ..() //ATTACK!
|
||||
var/mob/living/carbon/C = target
|
||||
var/list/parts = list()
|
||||
var/undismembermerable_limbs = 0
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
var/turns_since_scan = 0
|
||||
var/mob/living/simple_animal/mouse/movement_target
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
collar_type = "cat"
|
||||
|
||||
/mob/living/simple_animal/pet/cat/Initialize()
|
||||
. = ..()
|
||||
@@ -39,8 +40,11 @@
|
||||
if(client && stat != DEAD)
|
||||
if (resting)
|
||||
icon_state = "[icon_living]_rest"
|
||||
collar_type = "[initial(collar_type)]_rest"
|
||||
else
|
||||
icon_state = "[icon_living]"
|
||||
collar_type = "[initial(collar_type)]"
|
||||
regenerate_icons()
|
||||
|
||||
|
||||
/mob/living/simple_animal/pet/cat/space
|
||||
@@ -60,6 +64,7 @@
|
||||
icon_state = "original"
|
||||
icon_living = "original"
|
||||
icon_dead = "original_dead"
|
||||
collar_type = null
|
||||
unique_pet = TRUE
|
||||
|
||||
/mob/living/simple_animal/pet/cat/kitten
|
||||
@@ -71,6 +76,7 @@
|
||||
density = FALSE
|
||||
pass_flags = PASSMOB
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
collar_type = "kitten"
|
||||
|
||||
//RUNTIME IS ALIVE! SQUEEEEEEEE~
|
||||
/mob/living/simple_animal/pet/cat/Runtime
|
||||
@@ -162,17 +168,20 @@
|
||||
if(prob(1))
|
||||
emote("me", 1, pick("stretches out for a belly rub.", "wags its tail.", "lies down."))
|
||||
icon_state = "[icon_living]_rest"
|
||||
collar_type = "[initial(collar_type)]_rest"
|
||||
resting = 1
|
||||
update_canmove()
|
||||
else if (prob(1))
|
||||
emote("me", 1, pick("sits down.", "crouches on its hind legs.", "looks alert."))
|
||||
icon_state = "[icon_living]_sit"
|
||||
collar_type = "[initial(collar_type)]_sit"
|
||||
resting = 1
|
||||
update_canmove()
|
||||
else if (prob(1))
|
||||
if (resting)
|
||||
emote("me", 1, pick("gets up and meows.", "walks around.", "stops resting."))
|
||||
icon_state = "[icon_living]"
|
||||
collar_type = "[initial(collar_type)]"
|
||||
resting = 0
|
||||
update_canmove()
|
||||
else
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
var/nofur = 0 //Corgis that have risen past the material plane of existence.
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
can_be_held = TRUE
|
||||
collar_type = "corgi"
|
||||
|
||||
/mob/living/simple_animal/pet/dog/pug
|
||||
name = "\improper pug"
|
||||
@@ -42,6 +43,7 @@
|
||||
icon_dead = "pug_dead"
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/pug = 3)
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
collar_type = "pug"
|
||||
|
||||
/mob/living/simple_animal/pet/dog/Initialize()
|
||||
. = ..()
|
||||
@@ -469,7 +471,7 @@
|
||||
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/regenerate_icons()
|
||||
cut_overlays()
|
||||
..()
|
||||
if(inventory_head)
|
||||
var/image/head_icon
|
||||
var/datum/dog_fashion/DF = new inventory_head.dog_fashion(src)
|
||||
@@ -509,10 +511,6 @@
|
||||
back_icon = DF.get_overlay()
|
||||
add_overlay(back_icon)
|
||||
|
||||
if(pcollar)
|
||||
add_overlay(collar)
|
||||
add_overlay(pettag)
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -527,6 +525,7 @@
|
||||
density = FALSE
|
||||
pass_flags = PASSMOB
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
collar_type = "puppy"
|
||||
|
||||
//puppies cannot wear anything.
|
||||
/mob/living/simple_animal/pet/dog/corgi/puppy/Topic(href, href_list)
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
/mob/living/simple_animal/pet
|
||||
icon = 'icons/mob/pets.dmi'
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
var/obj/item/clothing/neck/petcollar/pcollar = null
|
||||
var/collar = ""
|
||||
var/pettag = ""
|
||||
var/obj/item/clothing/neck/petcollar/pcollar
|
||||
var/collar_type
|
||||
var/unique_pet = FALSE
|
||||
blood_volume = BLOOD_VOLUME_NORMAL
|
||||
|
||||
/mob/living/simple_animal/pet/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, /obj/item/clothing/neck/petcollar) && !pcollar)
|
||||
var/pet_icon_states = icon_states("[icon]")
|
||||
if("[icon_state]collar" in pet_icon_states)
|
||||
if(collar_type)
|
||||
var/obj/item/clothing/neck/petcollar/P = O
|
||||
pcollar = P
|
||||
collar = "[icon_state]collar"
|
||||
pettag = "[icon_state]tag"
|
||||
pcollar = P.type
|
||||
regenerate_icons()
|
||||
to_chat(user, "<span class='notice'>You put the [P] around [src]'s neck.</span>")
|
||||
if(P.tagname && !unique_pet)
|
||||
@@ -41,17 +37,25 @@
|
||||
|
||||
/mob/living/simple_animal/pet/revive(full_heal = 0, admin_revive = 0)
|
||||
if(..())
|
||||
if(collar_type)
|
||||
collar_type = "[initial(collar_type)]"
|
||||
regenerate_icons()
|
||||
. = 1
|
||||
. = TRUE
|
||||
|
||||
/mob/living/simple_animal/pet/death(gibbed)
|
||||
..(gibbed)
|
||||
if(collar_type)
|
||||
collar_type = "[initial(collar_type)]_dead"
|
||||
regenerate_icons()
|
||||
|
||||
/mob/living/simple_animal/pet/gib()
|
||||
if(pcollar)
|
||||
new pcollar(drop_location())
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/pet/regenerate_icons()
|
||||
cut_overlays()
|
||||
if(collar)
|
||||
add_overlay(collar)
|
||||
if(pettag)
|
||||
add_overlay(pettag)
|
||||
if(pcollar && collar_type)
|
||||
add_overlay("[collar_type]collar")
|
||||
add_overlay("[collar_type]tag")
|
||||
|
||||
|
||||
@@ -476,12 +476,15 @@ mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with mega
|
||||
toggle_ai(AI_Z_OFF)
|
||||
return
|
||||
|
||||
if (isturf(T) && !is_station_level(T.z))
|
||||
var/cheap_search = isturf(T) && !is_station_level(T.z)
|
||||
if (cheap_search)
|
||||
tlist = ListTargetsLazy(T.z)
|
||||
else
|
||||
tlist = ListTargets()
|
||||
|
||||
if(AIStatus == AI_IDLE && FindTarget(tlist, 1))
|
||||
if(cheap_search) //Try again with full effort
|
||||
FindTarget()
|
||||
toggle_ai(AI_ON)
|
||||
|
||||
/mob/living/simple_animal/hostile/proc/ListTargetsLazy(var/_Z)//Step 1, find out what we can see
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
/mob
|
||||
use_tag = TRUE
|
||||
|
||||
/mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game.
|
||||
GLOB.mob_list -= src
|
||||
GLOB.dead_mob_list -= src
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
flags_1 = HEAR_1
|
||||
hud_possible = list(ANTAG_HUD)
|
||||
pressure_resistance = 8
|
||||
use_tag = TRUE
|
||||
var/lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
|
||||
var/datum/mind/mind
|
||||
var/list/datum/action/actions = list()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
/datum/mapGenerator/lavaland
|
||||
var/start_z = ZLEVEL_LAVALAND
|
||||
var/start_z
|
||||
var/min_x = 0
|
||||
var/min_y = 0
|
||||
var/max_x = 0
|
||||
@@ -19,11 +19,9 @@
|
||||
/datum/mapGeneratorModule/river
|
||||
var/river_type = /turf/open/lava/smooth
|
||||
var/river_nodes = 4
|
||||
var/start_z = ZLEVEL_LAVALAND
|
||||
|
||||
/datum/mapGeneratorModule/river/generate()
|
||||
var/datum/mapGenerator/lavaland/L = mother
|
||||
if(!istype(L))
|
||||
return
|
||||
start_z = L.start_z
|
||||
spawn_rivers(start_z, river_nodes, river_type, min_x = L.min_x, min_y = L.min_y, max_x = L.max_x, max_y = L.max_y)
|
||||
spawn_rivers(L.start_z, river_nodes, river_type, min_x = L.min_x, min_y = L.min_y, max_x = L.max_x, max_y = L.max_y)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "CitadelStationBot"
|
||||
delete-after: True
|
||||
changes:
|
||||
- refactor: "Information about the properties of z-levels is now less hardcoded than before."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "ShizCalev"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Medbots are no longer able to inject you if you do not have any exposed flesh."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "CitadelStationBot"
|
||||
delete-after: True
|
||||
changes:
|
||||
- spellcheck: "Fixed message grammar when lifting someone off a brass skewer"
|
||||
@@ -0,0 +1,5 @@
|
||||
author: "CitadelStationBot"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Cyborgs that take enough damage to have a module disabled will now automatically announce that they've had a module disabled to anybody nearby. Now if you want to stop a cyborg from interfering with your business but don't want to kill it, you can simply bash until you see the CRITICAL ERROR message."
|
||||
- soundadd: "Borgs will play an alarm sound in addition to displaying this message as they have their modules disabled."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "CitadelStationBot"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Securitrons/ED-209s/Honkbots will only activate their emag functions after their internals are emagged"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Dax Dupont"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Thanks to the extensive disco and plasma research gathered by the Disco Inferno shuttles, an indestructible mark V disco machine is now available. The latest edition of the Disco Inferno shuttle now carries it."
|
||||
@@ -0,0 +1,5 @@
|
||||
author: "Cobby"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "As a human, you will now point with your legs when you have no arms, falling over each time."
|
||||
- tweak: "As a human, you will bump your head on the ground trying to motion towards something when you have no arms or legs."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "More Robust Than You"
|
||||
delete-after: True
|
||||
changes:
|
||||
- balance: "Sigils of submission now uncuff upon successful conversion"
|
||||
@@ -0,0 +1,22 @@
|
||||
author: "ShizCalev"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "You can now attach collars to pets again!"
|
||||
- bugfix: "Corrected pet collars icon mismatch."
|
||||
- bugfix: "Pets will now drop their collars when gibbed."
|
||||
- tweak: "You will no longer be able to rename unique pets, such as Ian or Runtime. You can still rename pets without a special name."
|
||||
- bugfix: "Secbot assemblies will no longer lose their weld hole when dragged North"
|
||||
- imageadd: "Secbot assemblies now have new North facing sprites!"
|
||||
- imageadd: "Cleaned up a rogue pixel on beepsky's sprite."
|
||||
- bugfix: "Defibrillators now have inhands again!"
|
||||
- bugfix: "Defibrillators will no longer stay in your hands after you die."
|
||||
- bugfix: "Losing an arm while wielding a two handed weapon will now cause you to drop the weapon."
|
||||
- bugfix: "Losing an arm while carrying an item that requires two hands to hold will now cause you to drop the item."
|
||||
- spellcheck: "Improved user feedback from chem dispenser macros."
|
||||
- bugfix: "Fixed Tests Areas debug verb."
|
||||
- bugfix: "Only the chaplain can now purify a bloody bastard sword."
|
||||
- bugfix: "Fully healing a mob as an admin now cures disabilities properly."
|
||||
- bugfix: "Non-cultists hulks can no longer withstand the immense powers of Ratvar's influence while holding a bloody bastard sword."
|
||||
- bugfix: "The average body temperature has been corrected to 98.6F."
|
||||
- tweak: "Safe dials will now present itself in 1 number increments, instead of 5."
|
||||
- bugfix: "Relabeled canisters will no longer switch to an incorrect sprite when broken."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "CitadelStationBot"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Relabelled canisters once again have the correct description."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "JJRcop"
|
||||
delete-after: True
|
||||
changes:
|
||||
- code_imp: "Removes some links intended for admins from game logs."
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
+4
-1
@@ -1685,6 +1685,10 @@
|
||||
#include "code\modules\mapping\mapping_helpers.dm"
|
||||
#include "code\modules\mapping\reader.dm"
|
||||
#include "code\modules\mapping\ruins.dm"
|
||||
#include "code\modules\mapping\space_management\space_level.dm"
|
||||
#include "code\modules\mapping\space_management\space_transition.dm"
|
||||
#include "code\modules\mapping\space_management\traits.dm"
|
||||
#include "code\modules\mapping\space_management\zlevel_manager.dm"
|
||||
#include "code\modules\mining\abandoned_crates.dm"
|
||||
#include "code\modules\mining\aux_base.dm"
|
||||
#include "code\modules\mining\aux_base_camera.dm"
|
||||
@@ -2332,7 +2336,6 @@
|
||||
#include "code\modules\shuttle\supply.dm"
|
||||
#include "code\modules\shuttle\syndicate.dm"
|
||||
#include "code\modules\shuttle\white_ship.dm"
|
||||
#include "code\modules\space_transition\space_transition.dm"
|
||||
#include "code\modules\spells\spell.dm"
|
||||
#include "code\modules\spells\spell_types\aimed.dm"
|
||||
#include "code\modules\spells\spell_types\area_teleport.dm"
|
||||
|
||||
@@ -85,9 +85,10 @@ def merge_map(new_map, old_map, delete_unused=False):
|
||||
|
||||
def main(settings):
|
||||
for fname in frontend.process(settings, "merge", backup=True):
|
||||
shutil.copyfile(fname, fname + ".before")
|
||||
old_map = DMM.from_file(fname + ".backup")
|
||||
new_map = DMM.from_file(fname)
|
||||
merge_map(old_map, new_map).to_file(fname, settings.tgm)
|
||||
merge_map(new_map, old_map).to_file(fname, settings.tgm)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(frontend.read_settings())
|
||||
|
||||
Reference in New Issue
Block a user