Merge branch 'master' into upstream-merge-27721

This commit is contained in:
LetterJay
2017-05-31 01:47:16 -05:00
committed by GitHub
297 changed files with 401907 additions and 224973 deletions
+1
View File
@@ -23,6 +23,7 @@
#define WACKY "Wacky"
#define MUT_MUTE "Mute"
#define SMILE "Smile"
#define STONER "Stoner"
#define UNINTELLIGABLE "Unintelligable"
#define SWEDISH "Swedish"
#define CHAV "Chav"
+2
View File
@@ -14,6 +14,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define NOBLUDGEON 4 // when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
#define MASKINTERNALS 8 // mask allows internals
#define HEAR 16 // This flag is what recursive_hear_check() uses to determine wether to add an item to the hearer list or not.
#define CHECK_RICOCHET 32 // Projectiels will check ricochet on things impacted that have this.
#define CONDUCT 64 // conducts electricity (metal etc.)
#define ABSTRACT 128 // for all things that are technically items but used for various different stuff, made it 128 because it could conflict with other flags other way
#define NODECONSTRUCT 128 // For machines and structures that should not break into parts, eg, holodeck stuff
@@ -57,6 +58,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define UNUSED_TRANSIT_TURF 2
#define CAN_BE_DIRTY 4 //If a turf can be made dirty at roundstart. This is also used in areas.
#define NO_DEATHRATTLE 16 // Do not notify deadchat about any deaths that occur on this turf.
//#define CHECK_RICOCHET 32 //Same thing as atom flag.
/*
These defines are used specifically with the atom/pass_flags bitmask
+2
View File
@@ -51,8 +51,10 @@
#define LIGHT_COLOR_GREEN "#64C864" //Bright but quickly dissipating neon green. rgb(100, 200, 100)
#define LIGHT_COLOR_BLUE "#6496FA" //Cold, diluted blue. rgb(100, 150, 250)
#define LIGHT_COLOR_BLUEGREEN "#7DE1AF" //Light blueish green. rgb(125, 225, 175)
#define LIGHT_COLOR_CYAN "#7DE1E1" //Diluted cyan. rgb(125, 225, 225)
#define LIGHT_COLOR_LIGHT_CYAN "#40CEFF" //More-saturated cyan. rgb(64, 206, 255)
#define LIGHT_COLOR_DARK_BLUE "#6496FA" //Saturated blue. rgb(51, 117, 248)
#define LIGHT_COLOR_PINK "#E17DE1" //Diluted, mid-warmth pink. rgb(225, 125, 225)
#define LIGHT_COLOR_YELLOW "#E1E17D" //Dimmed yellow, leaning kaki. rgb(225, 225, 125)
#define LIGHT_COLOR_BROWN "#966432" //Clear brown, mostly dim. rgb(150, 100, 50)
+2 -2
View File
@@ -34,8 +34,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_STATION 1
#define ZLEVEL_CENTCOM 2
#define ZLEVEL_CENTCOM 1
#define ZLEVEL_STATION 2
#define ZLEVEL_MINING 5
#define ZLEVEL_LAVALAND 5
#define ZLEVEL_EMPTY_SPACE 11
+13
View File
@@ -4,6 +4,19 @@
// #define EAST 4
// #define WEST 8
//These get to go at the top, because they're special
//You can use these defines to get the typepath of the currently running proc/verb (yes procs + verbs are objects)
/* eg:
/mob/living/carbon/human/death()
world << THIS_PROC_TYPE_STR //You can only output the string versions
Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a string with () (eg: the _WITH_ARGS defines) to make it look nicer)
*/
#define THIS_PROC_TYPE .....
#define THIS_PROC_TYPE_STR "[THIS_PROC_TYPE]" //Because you can only obtain a string of THIS_PROC_TYPE using "[]", and it's nice to just +/+= strings
#define THIS_PROC_TYPE_STR_WITH_ARGS "[THIS_PROC_TYPE]([args.Join(",")])"
#define THIS_PROC_TYPE_WEIRD ...... //This one is WEIRD, in some cases (When used in certain defines? (eg: ASSERT)) THIS_PROC_TYPE will fail to work, but THIS_PROC_TYPE_WEIRD will work instead
#define THIS_PROC_TYPE_WEIRD_STR "[THIS_PROC_TYPE_WEIRD]" //Included for completeness
#define THIS_PROC_TYPE_WEIRD_STR_WITH_ARGS "[THIS_PROC_TYPE_WEIRD]([args.Join(",")])" //Ditto
#define MIDNIGHT_ROLLOVER 864000 //number of deciseconds in a day
+5
View File
@@ -124,3 +124,8 @@
#define MAX_CHICKENS 50
#define UNHEALING_EAR_DAMAGE 100
#define INCORPOREAL_MOVE_BASIC 1
#define INCORPOREAL_MOVE_SHADOW 2 // leaves a trail of shadows
#define INCORPOREAL_MOVE_JAUNT 3 // is blocked by holy water/salt
+3 -1
View File
@@ -39,8 +39,10 @@
// Subsystem init_order, from highest priority to lowest priority
// Subsystems shutdown in the reverse of the order they initialize in
// The numbers just define the ordering, they are meaningless otherwise.
#define INIT_ORDER_DBCORE 17
#define INIT_ORDER_SERVER_MAINT 16
#define INIT_ORDER_JOBS 15
#define INIT_ORDER_EVENTS 14
@@ -71,4 +73,4 @@
#define RUNLEVEL_GAME 4
#define RUNLEVEL_POSTGAME 8
#define RUNLEVELS_DEFAULT (RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME)
#define RUNLEVELS_DEFAULT (RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME)
+2 -2
View File
@@ -3,8 +3,8 @@
#define WIRE_AI "AI Connection"
#define WIRE_ALARM "Alarm"
#define WIRE_AVOIDANCE "Avoidance"
#define WIRE_BACKUP1 "Auxillary Power 1"
#define WIRE_BACKUP2 "Auxillary Power 2"
#define WIRE_BACKUP1 "Auxiliary Power 1"
#define WIRE_BACKUP2 "Auxiliary Power 2"
#define WIRE_BEACON "Beacon"
#define WIRE_BOLTS "Bolts"
#define WIRE_BOOM "Boom"
+6 -15
View File
@@ -167,23 +167,14 @@
underlay_appearance.icon = fixed_underlay["icon"]
underlay_appearance.icon_state = fixed_underlay["icon_state"]
else
var/turf/T = get_step(src, turn(adjacencies, 180))
if(T && (T.density || T.smooth))
var/turned_adjacency = turn(adjacencies, 180)
var/turf/T = get_step(src, turned_adjacency)
if(!T.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
T = get_step(src, turn(adjacencies, 135))
if(T && (T.density || T.smooth))
if(!T.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
T = get_step(src, turn(adjacencies, 225))
if(isspaceturf(T) && !istype(T, /turf/open/space/transit))
underlay_appearance.icon = 'icons/turf/space.dmi'
underlay_appearance.icon_state = SPACE_ICON_STATE
underlay_appearance.plane = PLANE_SPACE
else if(T && !T.density && !T.smooth)
underlay_appearance.icon = T.icon
underlay_appearance.icon_state = T.icon_state
else if(baseturf && !initial(baseturf.density) && !initial(baseturf.smooth))
underlay_appearance.icon = initial(baseturf.icon)
underlay_appearance.icon_state = initial(baseturf.icon_state)
else
//if all else fails, ask our own turf
if(!T.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency) && !get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
underlay_appearance.icon = DEFAULT_UNDERLAY_ICON
underlay_appearance.icon_state = DEFAULT_UNDERLAY_ICON_STATE
underlays = U
+16 -2
View File
@@ -130,6 +130,22 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,
var/t = round((val - min) / d)
return val - (t * d)
#define NORM_ROT(rot) ((((rot % 360) + (rot - round(rot, 1))) > 0) ? ((rot % 360) + (rot - round(rot, 1))) : (((rot % 360) + (rot - round(rot, 1))) + 360))
/proc/get_angle_of_incidence(face_angle, angle_in, auto_normalize = TRUE)
var/angle_in_s = NORM_ROT(angle_in)
var/face_angle_s = NORM_ROT(face_angle)
var/incidence = face_angle_s - angle_in_s
var/incidence_s = incidence
while(incidence_s < -90)
incidence_s += 180
while(incidence_s > 90)
incidence_s -= 180
if(auto_normalize)
return incidence_s
else
return incidence
//A logarithm that converts an integer to a number scaled between 0 and 1 (can be tweaked to be higher).
//Currently, this is used for hydroponics-produce sprite transforming, but could be useful for other transform functions.
@@ -141,8 +157,6 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,
return size_factor + scaling_modifier //scale mod of 0 results in a number from 0 to 1. A scale modifier of +0.5 returns 0.5 to 1.5
//to_chat(world, "Transform multiplier of [src] is [size_factor + scaling_modifer]")
//converts a uniform distributed random number into a normal distributed one
//since this method produces two random numbers, one is saved for subsequent calls
//(making the cost negligble for every second call)
+8 -7
View File
@@ -1079,18 +1079,17 @@ B --><-- A
return L
//similar function to RANGE_TURFS(), but will search spiralling outwards from the center (like the above, but only turfs)
/proc/spiral_range_turfs(dist=0, center=usr, orange=0)
/proc/spiral_range_turfs(dist=0, center=usr, orange=0, list/outlist = list(), tick_checked)
outlist.Cut()
if(!dist)
if(!orange)
return list(center)
else
return list()
outlist += center
return outlist
var/turf/t_center = get_turf(center)
if(!t_center)
return list()
return outlist
var/list/L = list()
var/list/L = outlist
var/turf/T
var/y
var/x
@@ -1128,6 +1127,8 @@ B --><-- A
if(T)
L += T
c_dist++
if(tick_checked)
CHECK_TICK
return L
+9 -9
View File
@@ -22,12 +22,12 @@ GLOBAL_VAR_INIT(tinted_weldhelh, TRUE)
// Debug2 is used in conjunction with a lot of admin verbs and therefore is actually legit.
GLOBAL_VAR_INIT(Debug, FALSE) // global debug switch
GLOBAL_VAR_INIT(Debug2, FALSE)
//This was a define, but I changed it to a variable so it can be changed in-game.(kept the all-caps definition because... code...) -Errorage
GLOBAL_VAR_INIT(MAX_EX_DEVESTATION_RANGE, 3)
GLOBAL_VAR_INIT(MAX_EX_HEAVY_RANGE, 7)
GLOBAL_VAR_INIT(MAX_EX_LIGHT_RANGE, 14)
GLOBAL_VAR_INIT(MAX_EX_FLASH_RANGE, 14)
GLOBAL_VAR_INIT(MAX_EX_FLAME_RANGE, 14)
GLOBAL_VAR_INIT(DYN_EX_SCALE, 0.5)
//This was a define, but I changed it to a variable so it can be changed in-game.(kept the all-caps definition because... code...) -Errorage
GLOBAL_VAR_INIT(MAX_EX_DEVESTATION_RANGE, 3)
GLOBAL_VAR_INIT(MAX_EX_HEAVY_RANGE, 7)
GLOBAL_VAR_INIT(MAX_EX_LIGHT_RANGE, 14)
GLOBAL_VAR_INIT(MAX_EX_FLASH_RANGE, 14)
GLOBAL_VAR_INIT(MAX_EX_FLAME_RANGE, 14)
GLOBAL_VAR_INIT(DYN_EX_SCALE, 0.5)
+2 -2
View File
@@ -119,7 +119,7 @@
//User itself, current loc, and user inventory
if(DirectAccess(A))
if(W)
melee_item_attack_chain(src,W,A,params)
W.melee_attack_chain(src, A, params)
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
@@ -133,7 +133,7 @@
//Standard reach turf to turf or reaching inside storage
if(CanReach(A,W))
if(W)
melee_item_attack_chain(src,W,A,params)
W.melee_attack_chain(src, A, params)
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
+2 -2
View File
@@ -71,7 +71,7 @@
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc in contents)
if(A == loc || (A in loc) || (A in contents))
melee_item_attack_chain(src, W, A, params)
W.melee_attack_chain(src, A, params)
return
if(!isturf(loc))
@@ -80,7 +80,7 @@
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc))
if(isturf(A) || isturf(A.loc))
if(A.Adjacent(src)) // see adjacent.dm
melee_item_attack_chain(src, W, A, params)
W.melee_attack_chain(src, A, params)
return
else
W.afterattack(A, src, 0, params)
+5 -5
View File
@@ -1,10 +1,10 @@
/proc/melee_item_attack_chain(mob/user, obj/item/I, atom/target, params)
if(I.pre_attackby(target, user, params))
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
if(pre_attackby(target, user, params))
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
var/resolved = target.attackby(I,user,params)
if(!resolved && target && I)
I.afterattack(target, user, 1, params) // 1: clicking something Adjacent
var/resolved = target.attackby(src, user, params)
if(!resolved && target && !QDELETED(src))
afterattack(target, user, 1, params) // 1: clicking something Adjacent
// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
+2 -1
View File
@@ -124,7 +124,8 @@
if(!isturf(target) && istype(focus,/obj/item) && target.Adjacent(focus))
apply_focus_overlay()
melee_item_attack_chain(tk_user, focus, target, params) //isn't copying the attack chain fun. we should do it more often.
var/obj/item/I = focus
I.melee_attack_chain(tk_user, target, params) //isn't copying the attack chain fun. we should do it more often.
if(check_if_focusable(focus))
focus.do_attack_animation(target, null, focus)
else
+2 -1
View File
@@ -177,7 +177,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
to_chat(world, "<span class='boldannounce'>[msg]</span>")
log_world(msg)
SetRunLevel(1)
if (!current_runlevel)
SetRunLevel(1)
// Sort subsystems by display setting for easy access.
sortTim(subsystems, /proc/cmp_subsystem_display)
-2
View File
@@ -82,8 +82,6 @@ SUBSYSTEM_DEF(blackbox)
add_details("radio_usage","PDA-[pda_msg_amt]")
add_details("radio_usage","RC-[rc_msg_amt]")
set_details("round_end","[time2text(world.realtime)]") //This one MUST be the last one that gets set.
if (!SSdbcore.Connect())
return
+17 -12
View File
@@ -1,7 +1,7 @@
SUBSYSTEM_DEF(dbcore)
name = "Database"
flags = SS_NO_INIT|SS_NO_FIRE
init_order = INIT_ORDER_DBCORE
var/const/FAILED_DB_CONNECTION_CUTOFF = 5
var/const/Default_Cursor = 0
@@ -30,6 +30,11 @@ SUBSYSTEM_DEF(dbcore)
_db_con = SSdbcore._db_con
/datum/controller/subsystem/dbcore/Shutdown()
//This is as close as we can get to the true round end before Disconnect() without changing where it's called, defeating the reason this is a subsystem
if(SSdbcore.Connect())
var/sql_station_name = sanitizeSQL(station_name())
var/datum/DBQuery/query_round_end = SSdbcore.NewQuery("INSERT INTO [format_table_name("round")] (end_datetime, game_mode_result, end_state, station_name) VALUES (Now(), '[SSticker.mode_result]', '[SSticker.end_state]', '[sql_station_name]') WHERE id = [GLOB.round_id]")
query_round_end.Execute()
if(IsConnected())
Disconnect()
@@ -48,7 +53,7 @@ SUBSYSTEM_DEF(dbcore)
if(failed_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to connect anymore.
return FALSE
if(!config.sql_enabled)
return FALSE
@@ -171,16 +176,16 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
var/_db_query
/datum/DBQuery/New(sql_query, datum/controller/subsystem/dbcore/connection_handler, cursor_handler)
if(sql_query)
if(sql_query)
sql = sql_query
if(connection_handler)
if(connection_handler)
db_connection = connection_handler
if(cursor_handler)
if(cursor_handler)
default_cursor = cursor_handler
item = list()
_db_query = _dm_db_new_query()
/datum/DBQuery/proc/Connect(datum/controller/subsystem/dbcore/connection_handler)
/datum/DBQuery/proc/Connect(datum/controller/subsystem/dbcore/connection_handler)
db_connection = connection_handler
/datum/DBQuery/proc/warn_execute()
@@ -194,16 +199,16 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
if(!. && log_error)
log_sql("[ErrorMsg()] | Query used: [sql]")
/datum/DBQuery/proc/NextRow()
/datum/DBQuery/proc/NextRow()
return _dm_db_next_row(_db_query,item,conversions)
/datum/DBQuery/proc/RowsAffected()
return _dm_db_rows_affected(_db_query)
/datum/DBQuery/proc/RowCount()
/datum/DBQuery/proc/RowCount()
return _dm_db_row_count(_db_query)
/datum/DBQuery/proc/ErrorMsg()
/datum/DBQuery/proc/ErrorMsg()
return _dm_db_error_msg(_db_query)
/datum/DBQuery/proc/Columns()
@@ -232,11 +237,11 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
return db_connection.Quote(str)
/datum/DBQuery/proc/SetConversion(column,conversion)
if(istext(column))
if(istext(column))
column = columns.Find(column)
if(!conversions)
if(!conversions)
conversions = list(column)
else if(conversions.len < column)
else if(conversions.len < column)
conversions.len = column
conversions[column] = conversion
+1 -1
View File
@@ -105,7 +105,7 @@ SUBSYSTEM_DEF(events)
//These are needed because /area/engine has to be removed from the list, but we still want these areas to get fucked up.
var/list/danger_areas = list(
/area/engine/break_room,
/area/engine/chiefs_office)
/area/crew_quarters/heads/chief)
//Need to locate() as it's just a list of paths.
return locate(pick((GLOB.the_station_areas - safe_areas) + danger_areas))
+510
View File
@@ -0,0 +1,510 @@
SUBSYSTEM_DEF(explosion)
priority = 99
wait = 1
flags = SS_TICKER|SS_NO_INIT
var/list/explosions
var/rebuild_tick_split_count = FALSE
var/tick_portions_required = 0
var/list/logs
var/list/zlevels_that_ignore_bombcap
var/list/doppler_arrays
//legacy caps, set by config
var/devastation_cap = 3
var/heavy_cap = 7
var/light_cap = 14
var/flash_cap = 14
var/flame_cap = 14
var/dyn_ex_scale = 0.5
var/id_counter = 0
/datum/controller/subsystem/explosion/PreInit()
doppler_arrays = list()
logs = list()
explosions = list()
zlevels_that_ignore_bombcap = list("[ZLEVEL_MINING]")
/datum/controller/subsystem/explosion/Shutdown()
QDEL_LIST(explosions)
QDEL_LIST(logs)
zlevels_that_ignore_bombcap.Cut()
/datum/controller/subsystem/explosion/Recover()
explosions = SSexplosion.explosions
logs = SSexplosion.logs
id_counter = SSexplosion.id_counter
rebuild_tick_split_count = TRUE
zlevels_that_ignore_bombcap = SSexplosion.zlevels_that_ignore_bombcap
doppler_arrays = SSexplosion.doppler_arrays
devastation_cap = SSexplosion.devastation_cap
heavy_cap = SSexplosion.heavy_cap
light_cap = SSexplosion.light_cap
flash_cap = SSexplosion.flash_cap
flame_cap = SSexplosion.flame_cap
dyn_ex_scale = SSexplosion.dyn_ex_scale
/datum/controller/subsystem/explosion/fire()
var/list/cached_explosions = explosions
var/num_explosions = cached_explosions.len
if(!num_explosions)
return
//figure exactly how many tick splits are required
var/num_splits
if(rebuild_tick_split_count)
var/reactionary = config.reactionary_explosions
num_splits = num_explosions
for(var/I in cached_explosions)
var/datum/explosion/E = I
if(!E.turfs_processed)
++num_splits
if(reactionary && !E.densities_processed)
++num_splits
tick_portions_required = num_splits
else
num_splits = tick_portions_required
MC_SPLIT_TICK_INIT(num_splits)
for(var/I in cached_explosions)
var/datum/explosion/E = I
var/etp = E.turfs_processed
if(!etp)
if(GatherTurfs(E))
--tick_portions_required
etp = TRUE
MC_SPLIT_TICK
var/edp = E.densities_processed
if(!edp)
if(DensityCalculate(E, etp))
--tick_portions_required
edp = TRUE
MC_SPLIT_TICK
if(ProcessExplosion(E, edp)) //splits the tick
--tick_portions_required
explosions -= E
logs += E
NotifyDopplers(E)
MC_SPLIT_TICK
/datum/controller/subsystem/explosion/proc/NotifyDopplers(datum/explosion/E)
for(var/array in doppler_arrays)
var/obj/machinery/doppler_array/A = array
A.sense_explosion(E.epicenter, E.devastation, E.heavy, E.light, E.finished_at - E.started_at, E.orig_dev_range, E.orig_heavy_range, E.orig_light_range)
/datum/controller/subsystem/explosion/proc/Create(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = TRUE, ignorecap = FALSE, flame_range = 0 , silent = FALSE, smoke = FALSE)
epicenter = get_turf(epicenter)
if(!epicenter)
return
if(adminlog)
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area: [get_area(epicenter)] [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/datum/explosion/E = new(++id_counter, epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, flame_range, silent, smoke, ignorecap)
if(heavy_impact_range > 1)
var/datum/effect_system/explosion/Eff
if(smoke)
Eff = new /datum/effect_system/explosion/smoke
else
Eff = new
Eff.set_up(epicenter)
Eff.start()
//flash mobs
if(flash_range)
for(var/mob/living/L in viewers(flash_range, epicenter))
L.flash_act()
if(!silent)
ExplosionSound(epicenter, devastation_range, heavy_impact_range, E.extent)
//add to SS
if(E.extent)
tick_portions_required += 2 + (config.reactionary_explosions ? 1 : 0)
explosions += E
else
logs += E //Already done processing
/datum/controller/subsystem/explosion/proc/CreateDynamic(atom/epicenter, power, flash_range, adminlog = TRUE, ignorecap = TRUE, flame_range = 0 , silent = FALSE, smoke = TRUE)
if(!power)
return
var/range = round((2 * power) ** dyn_ex_scale)
Create(epicenter, round(range * 0.25), round(range * 0.5), round(range), flash_range*range, adminlog, ignorecap, flame_range*range, silent, smoke)
// Using default dyn_ex scale:
// 100 explosion power is a (5, 10, 20) explosion.
// 75 explosion power is a (4, 8, 17) explosion.
// 50 explosion power is a (3, 7, 14) explosion.
// 25 explosion power is a (2, 5, 10) explosion.
// 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.
/datum/explosion
var/explosion_id
var/turf/epicenter
var/started_at
var/finished_at
var/tick_started
var/tick_finished
var/turfs_processed = FALSE
var/densities_processed = FALSE
var/orig_dev_range
var/orig_heavy_range
var/orig_light_range
var/orig_flash_range
var/orig_flame_range
var/devastation
var/heavy
var/light
var/extent
var/flash
var/flame
var/gather_dist = 0
var/list/gathered_turfs
var/list/calculated_turfs
var/list/unsafe_turfs
/datum/explosion/New(id, turf/epi, devastation_range, heavy_impact_range, light_impact_range, flash_range, flame_range, silent, smoke, ignorecap)
explosion_id = id
epicenter = epi
densities_processed = !config.reactionary_explosions
orig_dev_range = devastation_range
orig_heavy_range = heavy_impact_range
orig_light_range = light_impact_range
orig_flash_range = flash_range
orig_flame_range = flame_range
if(!ignorecap && !("[epicenter.z]" in SSexplosion.zlevels_that_ignore_bombcap))
//Clamp all values
devastation_range = min(SSexplosion.devastation_cap, devastation_range)
heavy_impact_range = min(SSexplosion.heavy_cap, heavy_impact_range)
light_impact_range = min(SSexplosion.light_cap, light_impact_range)
flash_range = min(SSexplosion.flash_cap, flash_range)
flame_range = min(SSexplosion.flame_cap, flame_range)
//store this
devastation = devastation_range
heavy = heavy_impact_range
light = light_impact_range
extent = max(devastation_range, heavy_impact_range, light_impact_range, flame_range)
flash = flash_range
flame = flame_range
started_at = REALTIMEOFDAY
tick_started = world.time
gathered_turfs = list()
calculated_turfs = list()
unsafe_turfs = list()
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
// Stereo users will also hear the direction of the explosion!
// Calculate far explosion sound range. Only allow the sound effect for heavy/devastating explosions.
// 3/7/14 will calculate to 80 + 35
/proc/ExplosionSound(turf/epicenter, devastation_range, heavy_impact_range, extent)
var/far_dist = 0
far_dist += heavy_impact_range * 5
far_dist += devastation_range * 20
var/z0 = epicenter.z
var/frequency = get_rand_frequency()
var/ex_sound = get_sfx("explosion")
for(var/mob/M in GLOB.player_list)
// Double check for client
var/turf/M_turf = get_turf(M)
if(M_turf && M_turf.z == z0)
var/dist = get_dist(M_turf, epicenter)
// If inside the blast radius + world.view - 2
if(dist <= round(extent + world.view - 2, 1))
M.playsound_local(epicenter, ex_sound, 100, 1, frequency, falloff = 5)
// You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
else if(dist <= far_dist)
var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
/datum/explosion/Destroy()
SSexplosion.explosions -= src
SSexplosion.logs -= src
LAZYCLEARLIST(gathered_turfs)
LAZYCLEARLIST(calculated_turfs)
LAZYCLEARLIST(unsafe_turfs)
return ..()
/datum/controller/subsystem/explosion/proc/GatherTurfs(datum/explosion/E)
var/turf/epicenter = E.epicenter
var/x0 = epicenter.x
var/y0 = epicenter.y
var/z0 = epicenter.z
var/c_dist = E.gather_dist
var/dist = E.extent
var/list/L = E.gathered_turfs
if(!c_dist)
L += epicenter
++c_dist
while( c_dist <= dist )
var/y = y0 + c_dist
var/x = x0 - c_dist + 1
for(x in x to x0 + c_dist)
var/turf/T = locate(x, y, z0)
if(T)
L += T
y = y0 + c_dist - 1
x = x0 + c_dist
for(y in y0 - c_dist to y)
var/turf/T = locate(x, y, z0)
if(T)
L += T
y = y0 - c_dist
x = x0 + c_dist - 1
for(x in x0 - c_dist to x)
var/turf/T = locate(x, y, z0)
if(T)
L += T
y = y0 - c_dist + 1
x = x0 - c_dist
for(y in y to y0 + c_dist)
var/turf/T = locate(x, y, z0)
if(T)
L += T
++c_dist
if(MC_TICK_CHECK)
break
if(c_dist > dist)
E.turfs_processed = TRUE
return TRUE
else
E.gather_dist = c_dist
return FALSE
/datum/controller/subsystem/explosion/proc/DensityCalculate(datum/explosion/E, done_gathering_turfs)
var/list/L = E.calculated_turfs
var/cut_to = 1
for(var/I in E.gathered_turfs) // we cache the explosion block rating of every turf in the explosion area
var/turf/T = I
++cut_to
var/current_exp_block = T.density ? T.explosion_block : 0
for(var/obj/machinery/door/D in T)
if(D.density)
current_exp_block += D.explosion_block
for(var/obj/structure/window/W in T)
if(W.reinf && W.fulltile)
current_exp_block += W.explosion_block
for(var/obj/structure/blob/B in T)
current_exp_block += B.explosion_block
L[T] = current_exp_block
if(MC_TICK_CHECK)
E.gathered_turfs.Cut(1, cut_to)
return FALSE
E.gathered_turfs.Cut()
return done_gathering_turfs
/datum/controller/subsystem/explosion/proc/ProcessExplosion(datum/explosion/E, done_calculating_turfs)
//cache shit for speed
var/id = E.explosion_id
var/list/cached_unsafe = E.unsafe_turfs
var/list/cached_exp_block = E.calculated_turfs
var/list/affected_turfs = cached_exp_block ? cached_exp_block : E.gathered_turfs
var/devastation_range = E.devastation
var/heavy_impact_range = E.heavy
var/light_impact_range = E.light
var/flame_range = E.flame
var/throw_range_max = E.extent
var/turf/epi = E.epicenter
var/x0 = epi.x
var/y0 = epi.y
var/cut_to = 1
for(var/TI in affected_turfs)
var/turf/T = TI
++cut_to
var/init_dist = cheap_hypotenuse(T.x, T.y, x0, y0)
var/dist = init_dist
if(cached_exp_block)
var/turf/Trajectory = T
while(Trajectory != epi)
Trajectory = get_step_towards(Trajectory, epi)
dist += cached_exp_block[Trajectory]
var/flame_dist = dist < flame_range
var/throw_dist = dist
if(dist < devastation_range)
dist = 1
else if(dist < heavy_impact_range)
dist = 2
else if(dist < light_impact_range)
dist = 3
else
dist = 0
//------- EX_ACT AND TURF FIRES -------
if(flame_dist && prob(40) && !isspaceturf(T) && !T.density)
new /obj/effect/hotspot(T) //Mostly for ambience!
if(dist > 0)
T.explosion_level = max(T.explosion_level, dist) //let the bigger one have it
T.explosion_id = id
T.ex_act(dist)
cached_unsafe += T
//--- THROW ITEMS AROUND ---
var/throw_dir = get_dir(epi, T)
for(var/obj/item/I in T)
if(!I.anchored)
var/throw_range = rand(throw_dist, throw_range_max)
var/turf/throw_at = get_ranged_target_turf(I, throw_dir, throw_range)
I.throw_speed = 4 //Temporarily change their throw_speed for embedding purposes (Resets when it finishes throwing, regardless of hitting anything)
I.throw_at(throw_at, throw_range, 4)
if(MC_TICK_CHECK)
var/circumference = (PI * (init_dist + 4) * 2) //+4 to radius to prevent shit gaps
if(cached_unsafe.len > circumference) //only do this every revolution
for(var/Unexplode in cached_unsafe)
var/turf/UnexplodeT = Unexplode
UnexplodeT.explosion_level = 0
cached_unsafe.Cut()
done_calculating_turfs = FALSE
break
affected_turfs.Cut(1, cut_to)
if(!done_calculating_turfs)
return FALSE
//unfuck the shit
for(var/Unexplode in cached_unsafe)
var/turf/UnexplodeT = Unexplode
UnexplodeT.explosion_level = 0
cached_unsafe.Cut()
E.finished_at = REALTIMEOFDAY
E.tick_finished = world.time
return TRUE
/client/proc/check_bomb_impacts()
set name = "Check Bomb Impact"
set category = "Debug"
var/newmode = alert("Use reactionary explosions?","Check Bomb Impact", "Yes", "No")
var/turf/epicenter = get_turf(mob)
if(!epicenter)
return
var/x0 = epicenter.x
var/y0 = epicenter.y
var/dev = 0
var/heavy = 0
var/light = 0
var/list/choices = list("Small Bomb","Medium Bomb","Big Bomb","Custom Bomb")
var/choice = input("Bomb Size?") in choices
switch(choice)
if(null)
return 0
if("Small Bomb")
dev = 1
heavy = 2
light = 3
if("Medium Bomb")
dev = 2
heavy = 3
light = 4
if("Big Bomb")
dev = 3
heavy = 5
light = 7
if("Custom Bomb")
dev = input("Devestation range (Tiles):") as num
heavy = input("Heavy impact range (Tiles):") as num
light = input("Light impact range (Tiles):") as num
else
return
var/datum/explosion/E = new(null, epicenter, dev, heavy, light, ignorecap = TRUE)
while(!SSexplosion.GatherTurfs(E))
stoplag()
var/list/turfs
if(newmode)
while(!SSexplosion.DensityCalculate(E, TRUE))
stoplag()
turfs = E.calculated_turfs.Copy()
else
turfs = E.gathered_turfs.Copy()
qdel(E)
for(var/I in turfs)
var/turf/T = I
var/dist = cheap_hypotenuse(T.x, T.y, x0, y0) + turfs[T]
if(dist < dev)
T.color = "red"
T.maptext = "Dev"
else if (dist < heavy)
T.color = "yellow"
T.maptext = "Heavy"
else if (dist < light)
T.color = "blue"
T.maptext = "Light"
CHECK_TICK
sleep(100)
for(var/I in turfs)
var/turf/T = I
T.color = null
T.maptext = null
+2 -2
View File
@@ -164,8 +164,8 @@ SUBSYSTEM_DEF(garbage)
if (time > highest_del_time)
highest_del_time = time
if (time > 10)
log_game("Error: [type]([refID]) took longer then 1 second to delete (took [time/10] seconds to delete)")
message_admins("Error: [type]([refID]) took longer then 1 second to delete (took [time/10] seconds to delete).")
log_game("Error: [type]([refID]) took longer than 1 second to delete (took [time/10] seconds to delete)")
message_admins("Error: [type]([refID]) took longer than 1 second to delete (took [time/10] seconds to delete).")
postpone(time/5)
/datum/controller/subsystem/garbage/proc/HardQueue(datum/A)
+3 -3
View File
@@ -37,11 +37,11 @@ SUBSYSTEM_DEF(machines)
var/seconds = wait * 0.1
while(currentrun.len)
var/datum/thing = currentrun[currentrun.len]
var/obj/machinery/thing = currentrun[currentrun.len]
currentrun.len--
if(thing && thing.process(seconds) != PROCESS_KILL)
if(thing:use_power)
thing:auto_use_power() //add back the power state
if(thing.use_power)
thing.auto_use_power() //add back the power state
else
processing -= thing
if (thing)
+3 -1
View File
@@ -119,7 +119,9 @@ SUBSYSTEM_DEF(mapping)
INIT_ANNOUNCE("Loading [config.map_name]...")
TryLoadZ(config.GetFullMapPath(), FailedZs, ZLEVEL_STATION)
INIT_ANNOUNCE("Loaded station in [(REALTIMEOFDAY - start_time)/10]s!")
SSblackbox.add_details("map_name", config.map_name)
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]")
query_round_map_name.Execute()
if(config.minetype != "lavaland")
INIT_ANNOUNCE("WARNING: A map without lavaland set as it's minetype was loaded! This is being ignored! Update the maploader code!")
+1
View File
@@ -25,6 +25,7 @@ SUBSYSTEM_DEF(shuttle)
var/area/emergencyLastCallLoc
var/emergencyCallAmount = 0 //how many times the escape shuttle was called
var/emergencyNoEscape
var/emergencyNoRecall = FALSE
var/list/hostileEnvironments = list()
//supply shuttle stuff
+20 -7
View File
@@ -60,6 +60,8 @@ SUBSYSTEM_DEF(ticker)
var/round_start_time = 0
var/list/round_start_events
var/mode_result = "undefined"
var/end_state = "undefined"
var/modevoted = FALSE //Have we sent a vote for the gamemode?
@@ -639,9 +641,9 @@ SUBSYSTEM_DEF(ticker)
sleep(50)
if(mode.station_was_nuked)
Reboot("Station destroyed by Nuclear Device.", "end_proper", "nuke")
Reboot("Station destroyed by Nuclear Device.", "nuke")
else
Reboot("Round ended.", "end_proper", "proper completion")
Reboot("Round ended.", "proper completion")
/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
var/m
@@ -744,6 +746,15 @@ SUBSYSTEM_DEF(ticker)
cinematic = SSticker.cinematic
maprotatechecked = SSticker.maprotatechecked
switch (current_state)
if(GAME_STATE_SETTING_UP)
Master.SetRunLevel(RUNLEVEL_SETUP)
if(GAME_STATE_PLAYING)
Master.SetRunLevel(RUNLEVEL_GAME)
if(GAME_STATE_FINISHED)
Master.SetRunLevel(RUNLEVEL_POSTGAME)
modevoted = SSticker.modevoted
/datum/controller/subsystem/ticker/proc/send_news_report()
@@ -833,7 +844,7 @@ SUBSYSTEM_DEF(ticker)
C.Export("##action=load_rsc", round_end_sound)
round_end_sound_sent = TRUE
/datum/controller/subsystem/ticker/proc/Reboot(reason, feedback_c, feedback_r, delay)
/datum/controller/subsystem/ticker/proc/Reboot(reason, end_string, delay)
set waitfor = FALSE
if(usr && !check_rights(R_SERVER, TRUE))
return
@@ -844,18 +855,20 @@ SUBSYSTEM_DEF(ticker)
if(delay_end)
to_chat(world, "<span class='boldannounce'>An admin has delayed the round end.</span>")
return
to_chat(world, "<span class='boldannounce'>Rebooting World in [delay/10] [(delay >= 10 && delay < 20) ? "second" : "seconds"]. [reason]</span>")
var/start_wait = world.time
UNTIL(round_end_sound_sent && (world.time - start_wait) > (delay * 2)) //don't wait forever
UNTIL(round_end_sound_sent || (world.time - start_wait) > (delay * 2)) //don't wait forever
sleep(delay - (world.time - start_wait))
if(delay_end)
to_chat(world, "<span class='boldannounce'>Reboot was cancelled by an admin.</span>")
return
SSblackbox.set_details("[feedback_c]","[feedback_r]")
if(end_string)
end_state = end_string
log_game("<span class='boldannounce'>Rebooting World. [reason]</span>")
+1 -1
View File
@@ -137,7 +137,7 @@ SUBSYSTEM_DEF(vote)
active_admins = 1
break
if(!active_admins)
SSticker.Reboot("Restart vote successful.", "end_error", "restart vote")
SSticker.Reboot("Restart vote successful.", "restart vote")
else
to_chat(world, "<span style='boldannounce'>Notice:Restart vote will not restart the server automatically because there are active admins on.</span>")
message_admins("A restart vote has passed, but there are active admins on with +server, so it has been canceled. If you wish, you may restart the server.")
+2 -2
View File
@@ -32,7 +32,7 @@
var/list/symptoms = list() // The symptoms of the disease.
var/id = ""
var/processing = 0
// The order goes from easy to cure to hard to cure.
var/static/list/advance_cures = list(
"sodiumchloride", "sugar", "orangejuice",
@@ -399,7 +399,7 @@
AD.Refresh()
for(var/mob/living/carbon/human/H in shuffle(GLOB.living_mob_list))
if(H.z != 1)
if(H.z != ZLEVEL_STATION)
continue
if(!H.HasDisease(D))
H.ForceContractDisease(D)
@@ -1,10 +1,48 @@
/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range, silent = 0, smoke = 1)
set waitfor = 0
src = null //so we don't abort once src is deleted
#define EXPLOSION_THROW_SPEED 4
GLOBAL_LIST_EMPTY(explosions)
//Against my better judgement, I will return the explosion datum
//If I see any GC errors for it I will find you
//and I will gib you
/proc/explosion(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = TRUE, ignorecap = FALSE, flame_range = 0 , silent = FALSE, smoke = FALSE)
return new /datum/explosion(epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog, ignorecap, flame_range, silent, smoke)
//This datum creates 3 async tasks
//1 GatherSpiralTurfsProc runs spiral_range_turfs(tick_checked = TRUE) to populate the affected_turfs list
//2 CaculateExplosionBlock adds the blockings to the cached_exp_block list
//3 The main thread explodes the prepared turfs
/datum/explosion
var/explosion_id
var/started_at
var/running = TRUE
var/stopped = 0 //This is the number of threads stopped !DOESN'T COUNT THREAD 2!
var/static/id_counter = 0
#define EX_PREPROCESS_EXIT_CHECK \
if(!running) {\
stopped = 2;\
qdel(src);\
return;\
}
#define EX_PREPROCESS_CHECK_TICK \
if(TICK_CHECK) {\
stoplag();\
EX_PREPROCESS_EXIT_CHECK\
}
/datum/explosion/New(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog, ignorecap, flame_range, silent, smoke)
set waitfor = FALSE
var/id = ++id_counter
explosion_id = id
epicenter = get_turf(epicenter)
if(!epicenter)
return
GLOB.explosions += src
if(isnull(flame_range))
flame_range = light_impact_range
if(isnull(flash_range))
@@ -30,14 +68,13 @@
//I would make this not ex_act the thing that triggered the explosion,
//but everything that explodes gives us their loc or a get_turf()
//and somethings expect us to ex_act them so they can qdel()
sleep(1) //tldr, let the calling proc call qdel(src) before we explode
stoplag() //tldr, let the calling proc call qdel(src) before we explode
var/static/explosionid = 1
var/id = explosionid++
var/start = world.timeofday
EX_PREPROCESS_EXIT_CHECK
started_at = REALTIMEOFDAY
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flame_range)
var/list/cached_exp_block = list()
if(adminlog)
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area: [get_area(epicenter)] [ADMIN_COORDJMP(epicenter)]")
@@ -53,23 +90,27 @@
far_dist += heavy_impact_range * 5
far_dist += devastation_range * 20
var/x0 = epicenter.x
var/y0 = epicenter.y
var/z0 = epicenter.z
if(!silent)
var/frequency = get_rand_frequency()
var/ex_sound = get_sfx("explosion")
for(var/mob/M in GLOB.player_list)
// Double check for client
if(M && M.client)
var/turf/M_turf = get_turf(M)
if(M_turf && M_turf.z == epicenter.z)
var/dist = get_dist(M_turf, epicenter)
// If inside the blast radius + world.view - 2
if(dist <= round(max_range + world.view - 2, 1))
M.playsound_local(epicenter, ex_sound, 100, 1, frequency, falloff = 5)
// You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
else if(dist <= far_dist)
var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
var/turf/M_turf = get_turf(M)
if(M_turf && M_turf.z == z0)
var/dist = get_dist(M_turf, epicenter)
// If inside the blast radius + world.view - 2
if(dist <= round(max_range + world.view - 2, 1))
M.playsound_local(epicenter, ex_sound, 100, 1, frequency, falloff = 5)
// You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
else if(dist <= far_dist)
var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
EX_PREPROCESS_CHECK_TICK
//postpone processing for a bit
var/postponeCycles = max(round(devastation_range/8),1)
@@ -77,66 +118,52 @@
SSmachines.postpone(postponeCycles)
if(heavy_impact_range > 1)
var/datum/effect_system/explosion/E
if(smoke)
var/datum/effect_system/explosion/smoke/E = new/datum/effect_system/explosion/smoke()
E.set_up(epicenter)
E.start()
E = new /datum/effect_system/explosion/smoke
else
var/datum/effect_system/explosion/E = new/datum/effect_system/explosion()
E.set_up(epicenter)
E.start()
E = new
E.set_up(epicenter)
E.start()
var/x0 = epicenter.x
var/y0 = epicenter.y
var/z0 = epicenter.z
var/list/affected_turfs = spiral_range_turfs(max_range, epicenter)
if(config.reactionary_explosions)
for(var/turf/T in affected_turfs) // we cache the explosion block rating of every turf in the explosion area
cached_exp_block[T] = 0
if(T.density && T.explosion_block)
cached_exp_block[T] += T.explosion_block
for(var/obj/machinery/door/D in T)
if(D.density && D.explosion_block)
cached_exp_block[T] += D.explosion_block
for(var/obj/structure/window/W in T)
if(W.reinf && W.fulltile)
cached_exp_block[T] += W.explosion_block
for(var/obj/structure/blob/B in T)
cached_exp_block[T] += B.explosion_block
CHECK_TICK
EX_PREPROCESS_CHECK_TICK
//flash mobs
if(flash_range)
for(var/mob/living/L in viewers(flash_range, epicenter))
L.flash_act()
CHECK_TICK
EX_PREPROCESS_CHECK_TICK
var/list/exploded_this_tick = list() //open turfs that need to be blocked off while we sleep
for(var/turf/T in affected_turfs)
var/list/affected_turfs = GatherSpiralTurfs(max_range, epicenter)
if (!T)
continue
var/reactionary = config.reactionary_explosions
var/list/cached_exp_block
if(reactionary)
cached_exp_block = CaculateExplosionBlock(affected_turfs)
//lists are guaranteed to contain at least 1 turf at this point
var/iteration = 0
var/affTurfLen = affected_turfs.len
var/expBlockLen = cached_exp_block.len
for(var/TI in affected_turfs)
var/turf/T = TI
++iteration
var/init_dist = cheap_hypotenuse(T.x, T.y, x0, y0)
var/dist = init_dist
if(config.reactionary_explosions)
if(reactionary)
var/turf/Trajectory = T
while(Trajectory != epicenter)
Trajectory = get_step_towards(Trajectory, epicenter)
dist += cached_exp_block[Trajectory]
var/flame_dist = 0
var/flame_dist = dist < flame_range
var/throw_dist = dist
if(dist < flame_range)
flame_dist = 1
if(dist < devastation_range)
dist = 1
else if(dist < heavy_impact_range)
@@ -148,27 +175,61 @@
//------- EX_ACT AND TURF FIRES -------
if(T)
if(flame_dist && prob(40) && !isspaceturf(T) && !T.density)
new /obj/effect/hotspot(T) //Mostly for ambience!
if(dist > 0)
T.explosion_level = max(T.explosion_level, dist) //let the bigger one have it
T.explosion_id = id
T.ex_act(dist)
exploded_this_tick += T
if(flame_dist && prob(40) && !isspaceturf(T) && !T.density)
new /obj/effect/hotspot(T) //Mostly for ambience!
if(dist > 0)
T.explosion_level = max(T.explosion_level, dist) //let the bigger one have it
T.explosion_id = id
T.ex_act(dist)
exploded_this_tick += T
//--- THROW ITEMS AROUND ---
var/throw_dir = get_dir(epicenter,T)
for(var/obj/item/I in T)
if(I && !I.anchored)
if(!I.anchored)
var/throw_range = rand(throw_dist, max_range)
var/turf/throw_at = get_ranged_target_turf(I, throw_dir, throw_range)
I.throw_speed = 4 //Temporarily change their throw_speed for embedding purposes (Reset when it finishes throwing, regardless of hitting anything)
I.throw_at(throw_at, throw_range, I.throw_speed)
I.throw_speed = EXPLOSION_THROW_SPEED //Temporarily change their throw_speed for embedding purposes (Reset when it finishes throwing, regardless of hitting anything)
I.throw_at(throw_at, throw_range, EXPLOSION_THROW_SPEED)
if(TICK_CHECK)
//wait for the lists to repop
var/break_condition
if(reactionary)
//If we've caught up to the density checker thread and there are no more turfs to process
break_condition = iteration == expBlockLen && iteration < affTurfLen
else
//If we've caught up to the turf gathering thread and it's still running
break_condition = iteration == affTurfLen && !stopped
if(break_condition || TICK_CHECK)
stoplag()
if(!running)
break
//update the trackers
affTurfLen = affected_turfs.len
expBlockLen = cached_exp_block.len
if(break_condition)
if(reactionary)
//until there are more block checked turfs than what we are currently at
//or the explosion has stopped
UNTIL(iteration < affTurfLen || !running)
else
//until there are more gathered turfs than what we are currently at
//or there are no more turfs to gather/the explosion has stopped
UNTIL(iteration < expBlockLen || stopped)
if(!running)
break
//update the trackers
affTurfLen = affected_turfs.len
expBlockLen = cached_exp_block.len
var/circumference = (PI * (init_dist + 4) * 2) //+4 to radius to prevent shit gaps
if(exploded_this_tick.len > circumference) //only do this every revolution
for(var/Unexplode in exploded_this_tick)
@@ -182,24 +243,67 @@
UnexplodeT.explosion_level = 0
exploded_this_tick.Cut()
var/took = (world.timeofday-start)/10
//You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
var/took = (REALTIMEOFDAY - started_at) / 10
//You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
if(GLOB.Debug2)
log_world("## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds.")
//Machines which report explosions.
for(var/array in GLOB.doppler_arrays)
var/obj/machinery/doppler_array/A = array
A.sense_explosion(epicenter,devastation_range,heavy_impact_range,light_impact_range,took,orig_dev_range,orig_heavy_range,orig_light_range)
if(!stopped) //if we aren't in a hurry
//Machines which report explosions.
for(var/array in GLOB.doppler_arrays)
var/obj/machinery/doppler_array/A = array
A.sense_explosion(epicenter, devastation_range, heavy_impact_range, light_impact_range, took,orig_dev_range, orig_heavy_range, orig_light_range)
return 1
++stopped
qdel(src)
#undef EX_PREPROCESS_EXIT_CHECK
#undef EX_PREPROCESS_CHECK_TICK
//asyncly populate the affected_turfs list
/datum/explosion/proc/GatherSpiralTurfs(range, turf/epicenter)
set waitfor = FALSE
. = list()
spiral_range_turfs(range, epicenter, outlist = ., tick_checked = TRUE)
++stopped
/proc/secondaryexplosion(turf/epicenter, range)
for(var/turf/tile in spiral_range_turfs(range, epicenter))
tile.ex_act(2)
/datum/explosion/proc/CaculateExplosionBlock(list/affected_turfs)
set waitfor = FALSE
. = list()
var/processed = 0
while(!stopped && running)
var/I
for(I in (processed + 1) to affected_turfs.len) // we cache the explosion block rating of every turf in the explosion area
var/turf/T = affected_turfs[I]
var/current_exp_block = T.density ? T.explosion_block : 0
for(var/obj/machinery/door/D in T)
if(D.density)
current_exp_block += D.explosion_block
for(var/obj/structure/window/W in T)
if(W.reinf && W.fulltile)
current_exp_block += W.explosion_block
for(var/obj/structure/blob/B in T)
current_exp_block += B.explosion_block
.[T] = current_exp_block
if(TICK_CHECK)
break
processed = I
stoplag()
/datum/explosion/Destroy()
running = FALSE
if(stopped < 2) //wait for main thread and spiral_range thread
return QDEL_HINT_IWILLGC
GLOB.explosions -= src
return ..()
/client/proc/check_bomb_impacts()
set name = "Check Bomb Impact"
+17 -14
View File
@@ -1,34 +1,37 @@
/datum/getrev
var/parentcommit
var/originmastercommit
var/commit
var/list/testmerge = list()
var/has_pr_details = FALSE //example data in a testmerge entry when this is true: https://api.github.com/repositories/3234987/pulls/22586
var/date
/datum/getrev/New()
var/head_file = file2text(".git/logs/HEAD")
if(SERVERTOOLS && fexists("..\\prtestjob.lk"))
var/list/tmp = world.file2list("..\\prtestjob.lk")
for(var/I in tmp)
if(I)
testmerge |= I
var/testlen = max(testmerge.len - 1, 0)
var/regex/head_log = new("(\\w{40}) .+> (\\d{10}).+(?=(\n.*(\\w{40}).*){[testlen]}\n*\\Z)")
head_log.Find(head_file)
parentcommit = head_log.group[1]
date = unix2date(text2num(head_log.group[2]))
commit = head_log.group[4]
log_world("Running /tg/ revision:")
log_world("[date]")
var/list/logs = world.file2list(".git/logs/HEAD")
if(logs)
logs = splittext(logs[logs.len - 1], " ")
date = unix2date(text2num(logs[5]))
commit = logs[2]
log_world("[date]")
logs = world.file2list(".git/logs/refs/remotes/origin/master")
if(logs)
originmastercommit = splittext(logs[logs.len - 1], " ")[2]
if(testmerge.len)
log_world(commit)
for(var/line in testmerge)
if(line)
log_world("Test merge active of PR #[line]")
SSblackbox.add_details("testmerged_prs","[line]")
log_world("Based off master commit [parentcommit]")
log_world("Based off origin/master commit [originmastercommit]")
else
log_world(parentcommit)
log_world(originmastercommit)
/datum/getrev/proc/DownloadPRDetails()
if(!config.githubrepoid)
@@ -73,13 +76,13 @@
set name = "Show Server Revision"
set desc = "Check the current server code revision"
if(GLOB.revdata.parentcommit)
if(GLOB.revdata.originmastercommit)
to_chat(src, "<b>Server revision compiled on:</b> [GLOB.revdata.date]")
var/prefix = ""
if(GLOB.revdata.testmerge.len)
to_chat(src, GLOB.revdata.GetTestMergeInfo())
prefix = "Based off master commit: "
var/pc = GLOB.revdata.parentcommit
prefix = "Based off origin/master commit: "
var/pc = GLOB.revdata.originmastercommit
to_chat(src, "[prefix]<a href='[config.githuburl]/commit/[pc]'>[copytext(pc, 1, min(length(pc), 7))]</a>")
else
to_chat(src, "Revision unknown")
+3 -2
View File
@@ -44,11 +44,12 @@
//cleans up ALL references :)
/datum/holocall/Destroy()
user.reset_perspective()
if(user.client)
if(!QDELETED(eye) && user.client)
for(var/datum/camerachunk/chunk in eye.visibleCameraChunks)
chunk.remove(eye)
qdel(eye)
eye = null
user.remote_control = null
QDEL_NULL(eye)
user = null
if(hologram)
+2 -2
View File
@@ -11,8 +11,8 @@
var/minetype = "lavaland"
var/list/transition_config = list(MAIN_STATION = CROSSLINKED,
CENTCOMM = SELFLOOPING,
var/list/transition_config = list(CENTCOMM = SELFLOOPING,
MAIN_STATION = CROSSLINKED,
EMPTY_AREA_1 = CROSSLINKED,
EMPTY_AREA_2 = CROSSLINKED,
MINING = SELFLOOPING,
+17
View File
@@ -608,6 +608,23 @@ GLOBAL_LIST_EMPTY(mutations_list)
message = replacetext(message," muh valids "," getting my kicks ")
return trim(message)
/datum/mutation/human/stoner
name = "Stoner"
quality = NEGATIVE
dna_block = NON_SCANNABLE
text_gain_indication = "<span class='notice'>You feel...totally chill, man!</span>"
text_lose_indication = "<span class='notice'>You feel like you have a better sense of time.</span>"
/datum/mutation/human/stoner/on_acquiring(mob/living/carbon/human/owner)
..()
owner.grant_language(/datum/language/beachbum)
owner.remove_language(/datum/language/common)
/datum/mutation/human/stoner/on_losing(mob/living/carbon/human/owner)
..()
owner.grant_language(/datum/language/common)
owner.remove_language(/datum/language/beachbum)
/datum/mutation/human/laser_eyes
name = "Laser Eyes"
quality = POSITIVE
+11 -6
View File
@@ -20,7 +20,8 @@
var/r_hand = null
var/l_hand = null
var/internals_slot = null //ID of slot containing a gas tank
var/list/backpack_contents = list() // In the list(path=count,otherpath=count) format
var/list/backpack_contents = null // In the list(path=count,otherpath=count) format
var/list/implants = null
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overriden for customization depending on client prefs,species etc
@@ -71,11 +72,11 @@
H.equip_to_slot_or_del(new l_pocket(H),slot_l_store)
if(r_pocket)
H.equip_to_slot_or_del(new r_pocket(H),slot_r_store)
for(var/path in backpack_contents)
var/number = backpack_contents[path]
for(var/i=0,i<number,i++)
H.equip_to_slot_or_del(new path(H),slot_in_backpack)
if(backpack_contents)
for(var/path in backpack_contents)
var/number = backpack_contents[path]
for(var/i=0,i<number,i++)
H.equip_to_slot_or_del(new path(H),slot_in_backpack)
if(!H.head && toggle_helmet && istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit))
var/obj/item/clothing/suit/space/hardsuit/HS = H.wear_suit
@@ -88,6 +89,10 @@
if(internals_slot)
H.internal = H.get_item_by_slot(internals_slot)
H.update_action_buttons_icon()
if(implants)
for(var/implant_type in implants)
var/obj/item/weapon/implant/I = new implant_type(H)
I.implant(H, null, silent=TRUE)
H.update_body()
return 1
+59 -116
View File
@@ -1,6 +1,4 @@
/datum/riding
var/generic_pixel_x = 0 //All dirs show this pixel_x for the driver
var/generic_pixel_y = 0 //All dirs show this pixel_y for the driver, use these vars if the pixel shift is stable across all dir, override handle_vehicle_offsets otherwise.
var/next_vehicle_move = 0 //used for move delays
var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower
var/keytype = null
@@ -34,16 +32,29 @@
/datum/riding/proc/force_dismount(mob/living/M)
ridden.unbuckle_mob(M)
//Override this to set your vehicle's various pixel offsets
//if they differ between directions, otherwise use the
//generic variables
/datum/riding/proc/handle_vehicle_offsets()
var/ridden_dir = "[ridden.dir]"
var/passindex = 0
if(ridden.has_buckled_mobs())
for(var/m in ridden.buckled_mobs)
passindex++
var/mob/living/buckled_mob = m
buckled_mob.setDir(ridden.dir)
buckled_mob.pixel_x = generic_pixel_x
buckled_mob.pixel_y = generic_pixel_y
var/list/offsets = get_offsets(passindex)
dir_loop:
for(var/offsetdir in offsets)
if(offsetdir == ridden_dir)
var/list/diroffsets = offsets[offsetdir]
buckled_mob.pixel_x = diroffsets[1]
if(diroffsets.len == 2)
buckled_mob.pixel_y = diroffsets[2]
if(diroffsets.len == 3)
buckled_mob.layer = diroffsets[3]
break dir_loop
//Override this to set your vehicle's various pixel offsets
/datum/riding/proc/get_offsets(pass_index) // list(dir = x, y, layer)
return list("[NORTH]" = list(0, 0), "[SOUTH]" = list(0, 0), "[EAST]" = list(0, 0), "[WEST]" = list(0, 0))
//KEYS
/datum/riding/proc/keycheck(mob/user)
@@ -100,10 +111,12 @@
//atv
/datum/riding/atv
keytype = /obj/item/key
generic_pixel_x = 0
generic_pixel_y = 4
vehicle_move_delay = 1
/datum/riding/atv/get_offsets(pass_index) // list(dir = x, y, layer)
return list("[NORTH]" = list(0, 4), "[SOUTH]" = list(0, 4), "[EAST]" = list(0, 4), "[WEST]" = list( 0, 4))
/datum/riding/atv/handle_vehicle_layer()
if(ridden.dir == SOUTH)
ridden.layer = ABOVE_MOB_LAYER
@@ -150,24 +163,9 @@
keytype = /obj/item/key/janitor
/datum/riding/janicart/handle_vehicle_offsets()
..()
if(ridden.has_buckled_mobs())
for(var/m in ridden.buckled_mobs)
var/mob/living/buckled_mob = m
switch(buckled_mob.dir)
if(NORTH)
buckled_mob.pixel_x = 0
buckled_mob.pixel_y = 4
if(EAST)
buckled_mob.pixel_x = -12
buckled_mob.pixel_y = 7
if(SOUTH)
buckled_mob.pixel_x = 0
buckled_mob.pixel_y = 7
if(WEST)
buckled_mob.pixel_x = 12
buckled_mob.pixel_y = 7
/datum/riding/janicart/get_offsets(pass_index) // list(dir = x, y, layer)
return list("[NORTH]" = list(0, 4), "[SOUTH]" = list(-12, 7), "[EAST]" = list(0, 7), "[WEST]" = list( 12, 7))
//scooter
/datum/riding/scooter/handle_vehicle_layer()
if(ridden.dir == SOUTH)
@@ -175,20 +173,14 @@
else
ridden.layer = OBJ_LAYER
/datum/riding/scooter/get_offsets(pass_index) // list(dir = x, y, layer)
return list("[NORTH]" = list(0), "[SOUTH]" = list(-2), "[EAST]" = list(0), "[WEST]" = list( 2))
/datum/riding/scooter/handle_vehicle_offsets()
..()
if(ridden.has_buckled_mobs())
for(var/m in ridden.buckled_mobs)
var/mob/living/buckled_mob = m
switch(buckled_mob.dir)
if(NORTH)
buckled_mob.pixel_x = 0
if(EAST)
buckled_mob.pixel_x = -2
if(SOUTH)
buckled_mob.pixel_x = 0
if(WEST)
buckled_mob.pixel_x = 2
if(buckled_mob.get_num_legs() > 0)
buckled_mob.pixel_y = 5
else
@@ -209,16 +201,18 @@
//secway
/datum/riding/secway
keytype = /obj/item/key/security
generic_pixel_x = 0
generic_pixel_y = 4
/datum/riding/secway/get_offsets(pass_index) // list(dir = x, y, layer)
return list("[NORTH]" = list(0, 4), "[SOUTH]" = list(0, 4), "[EAST]" = list(0, 4), "[WEST]" = list( 0, 4))
//i want to ride my
/datum/riding/bicycle
keytype = null
generic_pixel_x = 0
generic_pixel_y = 4
vehicle_move_delay = 0
/datum/riding/bicycle/get_offsets(pass_index) // list(dir = x, y, layer)
return list("[NORTH]" = list(0, 4), "[SOUTH]" = list(0, 4), "[EAST]" = list(0, 4), "[WEST]" = list( 0, 4))
//speedbike
/datum/riding/space/speedbike
keytype = null
@@ -233,54 +227,28 @@
ridden.pixel_x = -18
ridden.pixel_y = 0
/datum/riding/space/speedbike/handle_vehicle_offsets()
if(ridden.has_buckled_mobs())
for(var/m in ridden.buckled_mobs)
var/mob/living/buckled_mob = m
buckled_mob.setDir(ridden.dir)
switch(ridden.dir)
if(NORTH)
buckled_mob.pixel_x = 0
buckled_mob.pixel_y = -8
if(SOUTH)
buckled_mob.pixel_x = 0
buckled_mob.pixel_y = 4
if(EAST)
buckled_mob.pixel_x = -10
buckled_mob.pixel_y = 5
if(WEST)
buckled_mob.pixel_x = 10
buckled_mob.pixel_y = 5
/datum/riding/space/speedbike/get_offsets(pass_index) // list(dir = x, y, layer)
return list("[NORTH]" = list(0, -8), "[SOUTH]" = list(0, 4), "[EAST]" = list(-10, 5), "[WEST]" = list( 10, 5))
//SPEEDUWAGON
/datum/riding/space/speedwagon
vehicle_move_delay = 0
/datum/riding/space/speedwagon/handle_vehicle_offsets()
if(ridden.has_buckled_mobs())
for(var/m in ridden.buckled_mobs)
var/mob/living/buckled_mob = m
buckled_mob.setDir(ridden.dir)
ridden.pixel_x = -48
ridden.pixel_y = -48
switch(ridden.dir)
if(NORTH)
buckled_mob.pixel_x = -10
buckled_mob.pixel_y = -3
if(SOUTH)
buckled_mob.pixel_x = 16
buckled_mob.pixel_y = 3
if(EAST)
buckled_mob.pixel_x = -4
buckled_mob.pixel_y = 30
if(WEST)
buckled_mob.pixel_x = 4
buckled_mob.pixel_y = -1
/datum/riding/space/speedwagon/handle_vehicle_layer()
ridden.layer = BELOW_MOB_LAYER
/datum/riding/space/speedwagon/get_offsets(pass_index) // list(dir = x, y, layer)
switch(pass_index)
if(1)
return list("[NORTH]" = list(-10, -4), "[SOUTH]" = list(16, 3), "[EAST]" = list(-4, 30), "[WEST]" = list(4, -3))
if(2)
return list("[NORTH]" = list(19, -5, 4), "[SOUTH]" = list(-13, 3, 4), "[EAST]" = list(-4, -3, 4.1), "[WEST]" = list(4, 28, 3.9))
if(3)
return list("[NORTH]" = list(-10, -18, 4.2), "[SOUTH]" = list(16, 25, 3.9), "[EAST]" = list(-22, 30), "[WEST]" = list(22, -3, 4.1))
if(4)
return list("[NORTH]" = list(19, -18, 4.2), "[SOUTH]" = list(-13, 25, 3.9), "[EAST]" = list(-22, 3, 3.9), "[WEST]" = list(22, 28))
///////////////BOATS////////////
/datum/riding/boat
keytype = /obj/item/weapon/oar
@@ -297,17 +265,15 @@
/datum/riding/boat/dragon
keytype = null
generic_pixel_y = 2
generic_pixel_x = 1
vehicle_move_delay = 1
/datum/riding/boat/dragon/get_offsets(pass_index) // list(dir = x, y, layer)
return list("[NORTH]" = list(1, 2), "[SOUTH]" = list(1, 2), "[EAST]" = list(1, 2), "[WEST]" = list( 1, 2))
///////////////ANIMALS////////////
//general animals
/datum/riding/animal
keytype = null
generic_pixel_x = 0
generic_pixel_y = 4
/datum/riding/animal/handle_ride(mob/user, direction)
if(user.incapacitated())
@@ -335,7 +301,7 @@
/datum/riding/human/ride_check(mob/living/M)
var/mob/living/carbon/human/H = ridden //IF this runtimes I'm blaming the admins.
if(M.incapacitated(FALSE, TRUE) || H.incapacitated(FALSE, TRUE))
M.visible_message("<span class='warning'>[M] falls off [ridden]!</span>")
M.visible_message("<span class='boldwarning'>[M] falls off of [ridden]!</span>")
Unbuckle(M)
return FALSE
if(M.restrained(TRUE))
@@ -345,22 +311,8 @@
if(H.pulling == M)
H.stop_pulling()
/datum/riding/human/handle_vehicle_offsets()
for(var/mob/living/M in ridden.buckled_mobs)
M.setDir(ridden.dir)
switch(ridden.dir)
if(NORTH)
M.pixel_x = 0
M.pixel_y = 6
if(SOUTH)
M.pixel_x = 0
M.pixel_y = 6
if(EAST)
M.pixel_x = -6
M.pixel_y = 4
if(WEST)
M.pixel_x = 6
M.pixel_y = 4
/datum/riding/human/get_offsets(pass_index) // list(dir = x, y, layer)
return list("[NORTH]" = list(0, 6), "[SOUTH]" = list(0, 6), "[EAST]" = list(-6, 4), "[WEST]" = list( 6, 4))
/datum/riding/human/handle_vehicle_layer()
if(ridden.buckled_mobs && ridden.buckled_mobs.len)
@@ -375,7 +327,7 @@
ridden.unbuckle_mob(user)
user.Weaken(3)
user.Stun(3)
user.visible_message("<span class='warning'>[ridden] pushes [user] off of them!</span>")
user.visible_message("<span class='boldwarning'>[ridden] pushes [user] off of them!</span>")
/datum/riding/cyborg
keytype = null
@@ -407,6 +359,9 @@
else
ridden.layer = MOB_LAYER
/datum/riding/cyborg/get_offsets(pass_index) // list(dir = x, y, layer)
return list("[NORTH]" = list(0, 4), "[SOUTH]" = list(0, 4), "[EAST]" = list(-6, 3), "[WEST]" = list( 6, 3))
/datum/riding/cyborg/handle_vehicle_offsets()
if(ridden.has_buckled_mobs())
for(var/mob/living/M in ridden.buckled_mobs)
@@ -417,26 +372,14 @@
M.pixel_x = R.module.ride_offset_x[dir2text(ridden.dir)]
M.pixel_y = R.module.ride_offset_y[dir2text(ridden.dir)]
else
switch(ridden.dir)
if(NORTH)
M.pixel_x = 0
M.pixel_y = 4
if(SOUTH)
M.pixel_x = 0
M.pixel_y = 4
if(EAST)
M.pixel_x = -6
M.pixel_y = 3
if(WEST)
M.pixel_x = 6
M.pixel_y = 3
..()
/datum/riding/cyborg/force_dismount(mob/living/M)
ridden.unbuckle_mob(M)
var/turf/target = get_edge_target_turf(ridden, ridden.dir)
var/turf/targetm = get_step(get_turf(ridden), ridden.dir)
M.Move(targetm)
M.visible_message("<span class='warning'>[M] is thrown clear of [ridden]!</span>")
M.visible_message("<span class='boldwarning'>[M] is thrown clear of [ridden]!</span>")
M.throw_at(target, 14, 5, ridden)
M.Weaken(3)
+1 -1
View File
@@ -134,7 +134,7 @@
area_type = /area
protected_areas = list(/area/maintenance, /area/ai_monitored/turret_protected/ai_upload, /area/ai_monitored/turret_protected/ai_upload_foyer,
/area/ai_monitored/turret_protected/ai, /area/storage/emergency, /area/storage/emergency2, /area/shuttle)
/area/ai_monitored/turret_protected/ai, /area/storage/emergency/starboard, /area/storage/emergency/port, /area/shuttle)
target_z = ZLEVEL_STATION
immunity_type = "rad"
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -57,13 +57,13 @@
name = "Mining Station Communications"
/area/mine/cafeteria
name = "Mining station Cafeteria"
name = "Mining Station Cafeteria"
/area/mine/hydroponics
name = "Mining station Hydroponics"
name = "Mining Station Hydroponics"
/area/mine/sleeper
name = "Mining station Emergency Sleeper"
name = "Mining Station Emergency Sleeper"
/area/mine/north_outpost
name = "North Mining Outpost"
@@ -86,6 +86,7 @@
/area/lavaland
icon_state = "mining"
has_gravity = 1
flags = NONE
/area/lavaland/surface
name = "Lavaland"
@@ -123,4 +124,4 @@
icon_state = "danger"
/area/lavaland/surface/outdoors/explored
name = "Lavaland Labor Camp"
name = "Lavaland Labor Camp"
+14 -3
View File
@@ -115,15 +115,26 @@
/area/prison/solitary
name = "Solitary Confinement"
icon_state = "brig"
/area/prison/execution_room
name = "Prisoner Education Chamber"
icon_state = "armory"
/area/prison/cell_block/A
/area/prison/execution_room
name = "Prisoner Education Chamber"
icon_state = "armory"
/area/prison/cell_block/a
// /area/prison/cell_block/A
name = "Prison Cell Block A"
icon_state = "brig"
/area/prison/cell_block/B
/area/prison/cell_block/b
// /area/prison/cell_block/B
name = "Prison Cell Block B"
icon_state = "brig"
/area/prison/cell_block/C
/area/prison/cell_block/c
// /area/prison/cell_block/C
name = "Prison Cell Block C"
icon_state = "brig"
+48 -7
View File
@@ -5,6 +5,7 @@
icon_state = "away"
has_gravity = 1
hidden = TRUE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/ruin/unpowered
@@ -20,20 +21,48 @@
//Areas
/area/ruin/powered/beach
icon_state = "dk_yellow"
/area/ruin/powered/clownplanet
icon_state = "dk_yellow"
/area/ruin/powered/animal_hospital
icon_state = "dk_yellow"
/area/ruin/powered/snow_biodome
icon_state = "dk_yellow"
/area/ruin/powered/gluttony
icon_state = "dk_yellow"
/area/ruin/powered/golem_ship
name = "Free Golem Ship"
icon_state = "dk_yellow"
/area/ruin/powered/greed
icon_state = "dk_yellow"
/area/ruin/unpowered/hierophant
name = "Hierophant's Arena"
icon_state = "dk_yellow"
/area/ruin/powered/pride
icon_state = "dk_yellow"
/area/ruin/powered/seedvault
icon_state = "dk_yellow"
/area/ruin/powered/syndicate_lava_base
name = "Secret Base"
icon_state = "dk_yellow"
/area/ruin/unpowered/no_grav/way_home
name = "\improper Salvation"
icon_state = "away"
/area/ruin/powered/snow_biodome
/area/ruin/powered/golem_ship
name = "Free Golem Ship"
/area/ruin/powered/syndicate_lava_base
name = "Secret Base"
// Ruins of "onehalf" ship
@@ -199,3 +228,15 @@
/area/ruin/abandonedzoo
name = "Abandoned Zoo"
icon_state = "green"
//Xeno Nest
/area/ruin/xenonest
name = "The Hive"
always_unpowered = 1
power_environ = 0
power_equip = 0
power_light = 0
poweralm = 0
+36 -33
View File
@@ -28,8 +28,8 @@
var/list/our_overlays //our local copy of (non-priority) overlays without byond magic. Use procs in SSoverlays to manipulate
var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
var/datum/proximity_monitor/proximity_monitor
var/datum/proximity_monitor/proximity_monitor
/atom/New(loc, ...)
//atom creation method that preloads variables at creation
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
@@ -39,21 +39,21 @@
var/do_initialize = SSatoms.initialized
if(do_initialize > INITIALIZATION_INSSATOMS)
args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD
if(SSatoms.InitAtom(src, args))
//we were deleted
return
var/list/created = SSatoms.created_atoms
if(created)
created += src
args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD
if(SSatoms.InitAtom(src, args))
//we were deleted
return
var/list/created = SSatoms.created_atoms
if(created)
created += src
//Called after New if the map is being loaded. mapload = TRUE
//Called from base of New if the map is being loaded. mapload = FALSE
//This base must be called or derivatives must set initialized to TRUE
//must not sleep
//This base must be called or derivatives must set initialized to TRUE
//must not sleep
//Other parameters are passed from New (excluding loc), this does not happen if mapload is TRUE
//Must return an Initialize hint. Defined in __DEFINES/subsystems.dm
//Must return an Initialize hint. Defined in __DEFINES/subsystems.dm
//Note: the following functions don't call the base for optimization and must copypasta:
// /turf/Initialize
@@ -76,23 +76,23 @@
if (opacity && isturf(loc))
var/turf/T = loc
T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways.
return INITIALIZE_HINT_NORMAL
return INITIALIZE_HINT_NORMAL
//called if Initialize returns INITIALIZE_HINT_LATELOAD
//This version shouldn't be called
/atom/proc/LateInitialize()
var/static/list/warned_types = list()
if(!warned_types[type])
WARNING("Old style LateInitialize behaviour detected in [type]!")
warned_types[type] = TRUE
Initialize(FALSE)
//called if Initialize returns INITIALIZE_HINT_LATELOAD
//This version shouldn't be called
/atom/proc/LateInitialize()
var/static/list/warned_types = list()
if(!warned_types[type])
WARNING("Old style LateInitialize behaviour detected in [type]!")
warned_types[type] = TRUE
Initialize(FALSE)
/atom/Destroy()
if(alternate_appearances)
for(var/K in alternate_appearances)
var/datum/atom_hud/alternate_appearance/AA = alternate_appearances[K]
AA.remove_from_hud(src)
for(var/K in alternate_appearances)
var/datum/atom_hud/alternate_appearance/AA = alternate_appearances[K]
AA.remove_from_hud(src)
if(reagents)
qdel(reagents)
@@ -100,10 +100,13 @@
LAZYCLEARLIST(priority_overlays)
//SSoverlays.processing -= src //we COULD do this, but it's better to just let it fall out of the processing queue
QDEL_NULL(light)
QDEL_NULL(light)
return ..()
/atom/proc/handle_ricochet(obj/item/projectile/P)
return
/atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5)
return (!density || !height)
@@ -274,7 +277,7 @@
return
/atom/proc/ex_act(severity, target)
set waitfor = FALSE
set waitfor = FALSE
contents_explosion(severity, target)
/atom/proc/blob_act(obj/structure/blob/B)
@@ -506,10 +509,10 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
/atom/proc/mech_melee_attack(obj/mecha/M)
return
//If a mob logouts/logins in side of an object you can use this proc
/atom/proc/on_log(login)
if(loc)
loc.on_log(login)
//If a mob logouts/logins in side of an object you can use this proc
/atom/proc/on_log(login)
if(loc)
loc.on_log(login)
/*
+9
View File
@@ -0,0 +1,9 @@
diff a/code/game/atoms.dm b/code/game/atoms.dm (rejected hunks)
@@ -274,6 +274,7 @@
return
/atom/proc/ex_act(severity, target)
+ set waitfor = FALSE
contents_explosion(severity, target)
/atom/proc/blob_act(obj/structure/blob/B)
+1 -1
View File
@@ -236,7 +236,7 @@
/obj/item/weapon/antag_spawner/slaughter_demon/attack_self(mob/user)
if(user.z != 1)
if(user.z != ZLEVEL_STATION)
to_chat(user, "<span class='notice'>You should probably wait until you reach the station.</span>")
return
if(used)
+3 -3
View File
@@ -20,7 +20,7 @@
if(round_converted) //So badmin blobs later don't step on the dead natural blobs metaphorical toes
..()
if(blobwincount <= GLOB.blobs_legit.len)
SSblackbox.set_details("round_end_result","win - blob took over")
SSticker.mode_result = "win - blob took over"
to_chat(world, "<FONT size = 3><B>The blob has taken over the station!</B></FONT>")
to_chat(world, "<B>The entire station was eaten by the Blob!</B>")
log_game("Blob mode completed with a blob victory.")
@@ -28,7 +28,7 @@
SSticker.news_report = BLOB_WIN
else if(station_was_nuked)
SSblackbox.set_details("round_end_result","halfwin - nuke")
SSticker.mode_result = "halfwin - nuke"
to_chat(world, "<FONT size = 3><B>Partial Win: The station has been destroyed!</B></FONT>")
to_chat(world, "<B>Directive 7-12 has been successfully carried out, preventing the Blob from spreading.</B>")
log_game("Blob mode completed with a tie (station destroyed).")
@@ -36,7 +36,7 @@
SSticker.news_report = BLOB_NUKE
else if(!GLOB.blob_cores.len)
SSblackbox.set_details("round_end_result","loss - blob eliminated")
SSticker.mode_result = "loss - blob eliminated"
to_chat(world, "<FONT size = 3><B>The staff has won!</B></FONT>")
to_chat(world, "<B>The alien organism has been eradicated from the station!</B>")
log_game("Blob mode completed with a crew victory.")
+3 -3
View File
@@ -191,7 +191,7 @@ Credit where due:
var/datum/game_mode/clockwork_cult/C = SSticker.mode
if(C.check_clockwork_victory())
text += "<span class='large_brass'><b>Ratvar's servants have succeeded in fulfilling His goals!</b></span>"
SSblackbox.set_details("round_end_result", "win - servants completed their objective (summon ratvar)")
SSticker.mode_result = "win - servants completed their objective (summon ratvar)"
else
var/half_victory = FALSE
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = locate() in GLOB.all_clockwork_objects
@@ -200,10 +200,10 @@ Credit where due:
if(half_victory)
text += "<span class='large_brass'><b>The crew escaped before Ratvar could rise, but the gateway \
was successfully constructed!</b></span>"
SSblackbox.set_details("round_end_result", "halfwin - servants constructed the gateway but their objective was not completed (summon ratvar)")
SSticker.mode_result = "halfwin - servants constructed the gateway but their objective was not completed (summon ratvar)"
else
text += "<span class='userdanger'>Ratvar's servants have failed!</span>"
SSblackbox.set_details("round_end_result", "loss - servants failed their objective (summon ratvar)")
SSticker.mode_result = "loss - servants failed their objective (summon ratvar)"
text += "<br><b>The servants' objective was:</b> <br>[CLOCKCULT_OBJECTIVE]"
text += "<br>Ratvar's servants had <b>[GLOB.clockwork_caches]</b> Tinkerer's Caches."
text += "<br><b>Construction Value(CV)</b> was: <b>[GLOB.clockwork_construction_value]</b>"
+4 -13
View File
@@ -208,12 +208,10 @@
/datum/game_mode/cult/declare_completion()
if(!check_cult_victory())
SSblackbox.set_details("round_end_result","win - cult win")
SSblackbox.set_val("round_end_result",acolytes_survived)
SSticker.mode_result = "win - cult win"
to_chat(world, "<span class='greentext'>The cult has succeeded! Nar-sie has snuffed out another torch in the void!</span>")
else
SSblackbox.set_details("round_end_result","loss - staff stopped the cult")
SSblackbox.set_val("round_end_result",acolytes_survived)
SSticker.mode_result = "loss - staff stopped the cult"
to_chat(world, "<span class='redtext'>The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!</span>")
var/text = ""
@@ -257,22 +255,15 @@
/datum/game_mode/proc/datum_cult_completion()
var/text = ""
var/acolytes_survived = 0
for(var/datum/mind/cult_mind in cult)
if (cult_mind.current && cult_mind.current.stat != DEAD)
if(cult_mind.current.onCentcom() || cult_mind.current.onSyndieBase())
acolytes_survived++
var/cult_fail = 0
cult_fail += eldergod
if(!GLOB.sac_complete)
cult_fail++
if(!cult_fail)
SSblackbox.set_details("round_end_result","win - cult win")
SSblackbox.set_val("round_end_result",acolytes_survived)
SSticker.mode_result = "win - cult win"
to_chat(world, "<span class='greentext'>The cult has succeeded! Nar-sie has snuffed out another torch in the void!</span>")
else
SSblackbox.set_details("round_end_result","loss - staff stopped the cult")
SSblackbox.set_val("round_end_result",acolytes_survived)
SSticker.mode_result = "loss - staff stopped the cult"
to_chat(world, "<span class='redtext'>The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!</span>")
if(cult_objectives.len)
text += "<br><b>The cultists' objectives were:</b>"
+13 -7
View File
@@ -80,11 +80,17 @@
report = config.intercept
addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME)
SSblackbox.set_details("round_start","[time2text(world.realtime)]")
if(SSticker && SSticker.mode)
SSblackbox.set_details("game_mode","[SSticker.mode]")
if(GLOB.revdata.commit)
SSblackbox.set_details("revision","[GLOB.revdata.commit]")
if(SSdbcore.Connect())
var/sql
if(SSticker && SSticker.mode)
sql += "game_mode = '[SSticker.mode]'"
if(sql)
sql += ", "
if(GLOB.revdata.commit)
sql += "commit_hash = '[GLOB.revdata.commit]'"
if(sql)
var/datum/DBQuery/query_round_game_mode = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET [sql] WHERE id = [GLOB.round_id]")
query_round_game_mode.Execute()
if(report)
addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h))
generate_station_goals()
@@ -233,11 +239,11 @@
if(ishuman(M))
if(!M.stat)
surviving_humans++
if(M.z == 2)
if(M.z == ZLEVEL_CENTCOM)
escaped_humans++
if(!M.stat)
surviving_total++
if(M.z == 2)
if(M.z == ZLEVEL_CENTCOM)
escaped_total++
+16 -2
View File
@@ -261,6 +261,20 @@ GLOBAL_LIST_INIT(gang_outfit_pool, list(/obj/item/clothing/suit/jacket/leather,/
gang_bosses += G.bosses
return gang_bosses
/datum/game_mode/proc/shuttle_check()
if(SSshuttle.emergencyNoRecall)
return
var/alive = 0
for(var/mob/living/L in GLOB.player_list)
if(L.stat != DEAD)
alive++
if((alive < (GLOB.joined_player_list.len * 0.4)) && ((SSshuttle.emergency.timeLeft(1) > (SSshuttle.emergencyCallTime * 0.4))))
SSshuttle.emergencyNoRecall = TRUE
SSshuttle.emergency.request(null, set_coefficient = 0.4)
priority_announce("Catastrophic casualties detected: crisis shuttle protocols activated - jamming recall signals across all frequencies.")
/proc/determine_domination_time(var/datum/gang/G)
return max(180,480 - (round((G.territory.len/GLOB.start_state.num_territories)*100, 1) * 9))
@@ -274,12 +288,12 @@ GLOBAL_LIST_INIT(gang_outfit_pool, list(/obj/item/clothing/suit/jacket/leather,/
return
if(!winner)
to_chat(world, "<span class='redtext'>The station was [station_was_nuked ? "destroyed!" : "evacuated before a gang could claim it! The station wins!"]</span><br>")
SSblackbox.set_details("round_end_result","loss - gangs failed takeover")
SSticker.mode_result = "loss - gangs failed takeover"
SSticker.news_report = GANG_LOSS
else
to_chat(world, "<span class='redtext'>The [winner.name] Gang successfully performed a hostile takeover of the station!</span><br>")
SSblackbox.set_details("round_end_result","win - gang domination complete")
SSticker.mode_result = "win - gang domination complete"
SSticker.news_report = GANG_TAKEOVER
+3 -3
View File
@@ -53,7 +53,6 @@
/datum/gang_item/weapon/ammo/uzi_ammo,
/datum/gang_item/equipment/sharpener,
/datum/gang_item/equipment/spraycan,
/datum/gang_item/equipment/sharpener,
/datum/gang_item/equipment/emp,
/datum/gang_item/equipment/c4,
/datum/gang_item/equipment/frag,
@@ -91,7 +90,6 @@
/datum/gang_item/weapon/ammo/uzi_ammo,
/datum/gang_item/equipment/sharpener,
/datum/gang_item/equipment/spraycan,
/datum/gang_item/equipment/sharpener,
/datum/gang_item/equipment/emp,
/datum/gang_item/equipment/c4,
/datum/gang_item/equipment/frag,
@@ -204,7 +202,9 @@
return
var/added_names = ""
var/lost_names = ""
SSticker.mode.shuttle_check() // See if its time to start wrapping things up
//Re-add territories that were reclaimed, so if they got tagged over, they can still earn income if they tag it back before the next status report
var/list/reclaimed_territories = territory_new & territory_lost
territory |= reclaimed_territories
+3 -2
View File
@@ -326,6 +326,7 @@
if(spawn_msg)
to_chat(user, spawn_msg)
/datum/gang_item/equipment/wetwork_boots
name = "Wetwork boots"
id = "wetwork"
@@ -412,7 +413,7 @@
/datum/gang_item/equipment/dominator/purchase(mob/living/carbon/user, datum/gang/gang, obj/item/device/gangtool/gangtool)
var/area/usrarea = get_area(user.loc)
var/usrturf = get_turf(user.loc)
if(initial(usrarea.name) == "Space" || isspaceturf(usrturf) || usr.z != 1)
if(initial(usrarea.name) == "Space" || isspaceturf(usrturf) || usr.z != ZLEVEL_STATION)
to_chat(user, "<span class='warning'>You can only use this on the station!</span>")
return FALSE
@@ -422,7 +423,7 @@
return FALSE
if(dominator_excessive_walls(user))
to_chat(user, "span class='warning'>The <b>dominator</b> will not function here! The <b>dominator</b> requires a sizable open space within three standard units so that walls do not interfere with the signal.</span>")
to_chat(user, "<span class='warning'>The <b>dominator</b> will not function here! The <b>dominator</b> requires a sizable open space within three standard units so that walls do not interfere with the signal.</span>")
return FALSE
if(!(usrarea.type in gang.territory|gang.territory_new))
+5 -2
View File
@@ -167,6 +167,9 @@
if(!can_use(user))
return 0
if(SSshuttle.emergencyNoRecall)
return 0
if(recalling)
to_chat(usr, "<span class='warning'>Error: Recall already in progress.</span>")
return 0
@@ -194,7 +197,7 @@
return 0
var/turf/userturf = get_turf(user)
if(userturf.z != 1) //Shuttle can only be recalled while on station
if(userturf.z != ZLEVEL_STATION) //Shuttle can only be recalled while on station
to_chat(user, "<span class='warning'>\icon[src]Error: Device out of range of station communication arrays.</span>")
recalling = 0
return 0
@@ -212,7 +215,7 @@
log_game("[key_name(user)] has tried to recall the shuttle with a gangtool.")
message_admins("[key_name_admin(user)] has tried to recall the shuttle with a gangtool.", 1)
userturf = get_turf(user)
if(userturf.z == 1) //Check one more time that they are on station.
if(userturf.z == ZLEVEL_STATION) //Check one more time that they are on station.
if(SSshuttle.cancelEvac(user))
gang.recalls -= 1
return 1
+1 -3
View File
@@ -50,8 +50,6 @@
else
to_chat(world, "<span class='boldnotice'>Nobody survived the meteor storm!</span>")
SSblackbox.set_details("round_end_result","end - evacuation")
SSblackbox.set_val("round_end_result",survivors)
SSticker.mode_result = "end - evacuation"
..()
return 1
@@ -70,12 +70,12 @@
origin.vest_mode_action.Remove(C)
origin.vest_disguise_action.Remove(C)
origin.set_droppoint_action.Remove(C)
remote_eye.eye_user = null
C.reset_perspective(null)
if(C.client)
C.client.images -= remote_eye.user_image
for(var/datum/camerachunk/chunk in remote_eye.visibleCameraChunks)
chunk.remove(remote_eye)
remote_eye.eye_user = null
C.remote_control = null
C.unset_machine()
Remove(C)
@@ -181,6 +181,7 @@
to_chat(H, "<span class='warning'>You feel intensely watched.</span>")
sleep(5)
to_chat(H, "<span class='warning'><b>Your mind snaps!</b></span>")
to_chat(H, "<big><span class='warning'><b>You can't remember how you got here...</b></span></big>")
var/objtype = pick(subtypesof(/datum/objective/abductee/))
var/datum/objective/abductee/O = new objtype()
SSticker.mode.abductees += H.mind
@@ -107,10 +107,8 @@
/datum/game_mode/monkey/declare_completion()
if(check_monkey_victory())
SSblackbox.set_details("round_end_result","win - monkey win")
SSblackbox.set_val("round_end_result",escaped_monkeys)
SSticker.mode_result = "win - monkey win"
to_chat(world, "<span class='userdanger'>The monkeys have overthrown their captors! Eeek eeeek!!</span>")
else
SSblackbox.set_details("round_end_result","loss - staff stopped the monkeys")
SSblackbox.set_val("round_end_result",escaped_monkeys)
SSticker.mode_result = "loss - staff stopped the monkeys"
to_chat(world, "<span class='userdanger'>The staff managed to contain the monkey infestation!</span>")
@@ -15,7 +15,7 @@
var/icon_stun = "revenant_stun"
var/icon_drain = "revenant_draining"
var/stasis = FALSE
incorporeal_move = 3
incorporeal_move = INCORPOREAL_MOVE_JAUNT
invisibility = INVISIBILITY_REVENANT
health = INFINITY //Revenants don't use health, they use essence instead
maxHealth = INFINITY
@@ -102,7 +102,7 @@
if(unreveal_time && world.time >= unreveal_time)
unreveal_time = 0
revealed = FALSE
incorporeal_move = 3
incorporeal_move = INCORPOREAL_MOVE_JAUNT
invisibility = INVISIBILITY_REVENANT
to_chat(src, "<span class='revenboldnotice'>You are once more concealed.</span>")
if(unstun_time && world.time >= unstun_time)
@@ -222,7 +222,7 @@
R.essence = max(reforming_essence - 15 * perfectsouls, 75) //minus any perfect souls
R.client_to_revive = client //If the essence reforms, the old revenant is put back in the body
R.revenant = src
invisibility = INVISIBILITY_ABSTRACT
invisibility = INVISIBILITY_ABSTRACT
revealed = FALSE
ghostize(0)//Don't re-enter invisible corpse
return
@@ -236,7 +236,7 @@
return
revealed = TRUE
invisibility = 0
incorporeal_move = 0
incorporeal_move = FALSE
if(!unreveal_time)
to_chat(src, "<span class='revendanger'>You have been revealed!</span>")
unreveal_time = world.time + time
@@ -309,12 +309,12 @@
/mob/living/simple_animal/revenant/proc/death_reset()
revealed = FALSE
unreveal_time = 0
unreveal_time = 0
notransform = 0
unstun_time = 0
inhibited = FALSE
draining = FALSE
incorporeal_move = 3
incorporeal_move = INCORPOREAL_MOVE_JAUNT
invisibility = INVISIBILITY_REVENANT
alpha=255
stasis = FALSE
+10 -10
View File
@@ -201,70 +201,70 @@
if(nuke_off_station == NUKE_SYNDICATE_BASE)
SSblackbox.set_details("round_end_result","loss - syndicate nuked - disk secured")
SSticker.mode_result = "loss - syndicate nuked - disk secured"
to_chat(world, "<FONT size = 3><B>Humiliating Syndicate Defeat</B></FONT>")
to_chat(world, "<B>The crew of [station_name()] gave [syndicate_name()] operatives back their bomb! The syndicate base was destroyed!</B> Next time, don't lose the nuke!")
SSticker.news_report = NUKE_SYNDICATE_BASE
else if(!disk_rescued && station_was_nuked && !syndies_didnt_escape)
SSblackbox.set_details("round_end_result","win - syndicate nuke")
SSticker.mode_result = "win - syndicate nuke"
to_chat(world, "<FONT size = 3><B>Syndicate Major Victory!</B></FONT>")
to_chat(world, "<B>[syndicate_name()] operatives have destroyed [station_name()]!</B>")
SSticker.news_report = STATION_NUKED
else if (!disk_rescued && station_was_nuked && syndies_didnt_escape)
SSblackbox.set_details("round_end_result","halfwin - syndicate nuke - did not evacuate in time")
SSticker.mode_result = "halfwin - syndicate nuke - did not evacuate in time"
to_chat(world, "<FONT size = 3><B>Total Annihilation</B></FONT>")
to_chat(world, "<B>[syndicate_name()] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion.</B> Next time, don't lose the disk!")
SSticker.news_report = STATION_NUKED
else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape)
SSblackbox.set_details("round_end_result","halfwin - blew wrong station")
SSticker.mode_result = "halfwin - blew wrong station"
to_chat(world, "<FONT size = 3><B>Crew Minor Victory</B></FONT>")
to_chat(world, "<B>[syndicate_name()] operatives secured the authentication disk but blew up something that wasn't [station_name()].</B> Next time, don't do that!")
SSticker.news_report = NUKE_MISS
else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape)
SSblackbox.set_details("round_end_result","halfwin - blew wrong station - did not evacuate in time")
SSticker.mode_result = "halfwin - blew wrong station - did not evacuate in time"
to_chat(world, "<FONT size = 3><B>[syndicate_name()] operatives have earned Darwin Award!</B></FONT>")
to_chat(world, "<B>[syndicate_name()] operatives blew up something that wasn't [station_name()] and got caught in the explosion.</B> Next time, don't do that!")
SSticker.news_report = NUKE_MISS
else if ((disk_rescued || SSshuttle.emergency.mode != SHUTTLE_ENDGAME) && are_operatives_dead())
SSblackbox.set_details("round_end_result","loss - evacuation - disk secured - syndi team dead")
SSticker.mode_result = "loss - evacuation - disk secured - syndi team dead"
to_chat(world, "<FONT size = 3><B>Crew Major Victory!</B></FONT>")
to_chat(world, "<B>The Research Staff has saved the disk and killed the [syndicate_name()] Operatives</B>")
SSticker.news_report = OPERATIVES_KILLED
else if (disk_rescued)
SSblackbox.set_details("round_end_result","loss - evacuation - disk secured")
SSticker.mode_result = "loss - evacuation - disk secured"
to_chat(world, "<FONT size = 3><B>Crew Major Victory</B></FONT>")
to_chat(world, "<B>The Research Staff has saved the disk and stopped the [syndicate_name()] Operatives!</B>")
SSticker.news_report = OPERATIVES_KILLED
else if (!disk_rescued && are_operatives_dead())
SSblackbox.set_details("round_end_result","halfwin - evacuation - disk not secured")
SSticker.mode_result = "halfwin - evacuation - disk not secured"
to_chat(world, "<FONT size = 3><B>Neutral Victory!</B></FONT>")
to_chat(world, "<B>The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name()] Operatives!</B>")
SSticker.news_report = OPERATIVE_SKIRMISH
else if (!disk_rescued && crew_evacuated)
SSblackbox.set_details("round_end_result","halfwin - detonation averted")
SSticker.mode_result = "halfwin - detonation averted"
to_chat(world, "<FONT size = 3><B>Syndicate Minor Victory!</B></FONT>")
to_chat(world, "<B>[syndicate_name()] operatives survived the assault but did not achieve the destruction of [station_name()].</B> Next time, don't lose the disk!")
SSticker.news_report = OPERATIVE_SKIRMISH
else if (!disk_rescued && !crew_evacuated)
SSblackbox.set_details("round_end_result","halfwin - interrupted")
SSticker.mode_result = "halfwin - interrupted"
to_chat(world, "<FONT size = 3><B>Neutral Victory</B></FONT>")
to_chat(world, "<B>Round was mysteriously interrupted!</B>")
+1 -1
View File
@@ -459,7 +459,7 @@
var/datum/game_mode/nuclear/NM = SSticker.mode
NM.nukes_left --
if(!SSticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is
SSticker.Reboot("Station destroyed by Nuclear Device.", "end_error", "nuke - unhandled ending")
SSticker.Reboot("Station destroyed by Nuclear Device.", "nuke - unhandled ending")
/*
+2 -2
View File
@@ -345,13 +345,13 @@
//////////////////////////////////////////////////////////////////////
/datum/game_mode/revolution/declare_completion()
if(finished == 1)
SSblackbox.set_details("round_end_result","win - heads killed")
SSticker.mode_result = "win - heads killed"
to_chat(world, "<span class='redtext'>The heads of staff were killed or exiled! The revolutionaries win!</span>")
SSticker.news_report = REVS_WIN
else if(finished == 2)
SSblackbox.set_details("round_end_result","loss - rev heads killed")
SSticker.mode_result = "loss - rev heads killed"
to_chat(world, "<span class='redtext'>The heads of staff managed to stop the revolution!</span>")
SSticker.news_report = REVS_LOSE
+28 -7
View File
@@ -1,6 +1,8 @@
#define PINPOINTER_MINIMUM_RANGE 15
#define PINPOINTER_EXTRA_RANDOM_RANGE 10
#define PINPOINTER_PING_TIME 40
#define PROB_ACTUAL_TRAITOR 20
#define TRAITOR_AGENT_ROLE "Syndicate External Affairs Agent"
/datum/game_mode/traitor/internal_affairs
name = "Internal Affairs"
@@ -171,7 +173,10 @@
if(!objective.check_completion())
traitored = FALSE
return
to_chat(owner.current,"<span class='userdanger'> All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.</span>")
if(owner.special_role == TRAITOR_AGENT_ROLE)
to_chat(owner.current,"<span class='userdanger'> All the loyalist agents are dead, and no more is required of you. Die a glorious death, agent. </span>")
else
to_chat(owner.current,"<span class='userdanger'> All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.</span>")
replace_escape_objective(owner)
@@ -194,7 +199,10 @@
if(objective.stolen)
var/fail_msg = "<span class='userdanger'>Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! </span>"
if(traitored)
fail_msg += "<span class='userdanger'> The truth could still slip out!</font><B><font size=5 color=red> Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated.</span>"
if(owner.special_role == TRAITOR_AGENT_ROLE)
fail_msg += "<span class='userdanger'> You no longer have permission to die. </span>"
else
fail_msg += "<span class='userdanger'> The truth could still slip out!</font><B><font size=5 color=red> Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated.</span>"
reinstate_escape_objective(owner)
traitored = FALSE
to_chat(owner.current, fail_msg)
@@ -238,6 +246,10 @@
state.add_steal_targets_timer()
if(!issilicon(traitor.current))
give_pinpointer(traitor)
//Optional traitor objective
if(prob(PROB_ACTUAL_TRAITOR))
traitor.special_role = TRAITOR_AGENT_ROLE
forge_single_objective(traitor)
else
..() // Give them standard objectives.
@@ -289,11 +301,18 @@
/datum/game_mode/traitor/internal_affairs/greet_traitor(datum/mind/traitor)
var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "recieving bribes", "malpractice", "worship of prohbited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
to_chat(traitor.current, "<span class='userdanger'>You are the [traitor_name].</span>")
to_chat(traitor.current, "<span class='userdanger'>Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.</span>")
to_chat(traitor.current, "<B><font size=5 color=red>While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.</font></B>")
to_chat(traitor.current, "<span class='userdanger'>For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.</span>")
to_chat(traitor.current, "<span class='userdanger'>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</span>")
if(traitor.special_role == TRAITOR_AGENT_ROLE)
to_chat(traitor.current, "<span class='userdanger'>You are the [TRAITOR_AGENT_ROLE].</span>")
to_chat(traitor.current, "<span class='userdanger'>Your target has been framed for [crime], and you have been tasked with eliminating them to prevent them defending themselves in court.</span>")
to_chat(traitor.current, "<B><font size=5 color=red>Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.</font></B>")
to_chat(traitor.current, "<span class='userdanger'> You have been provided with a standard uplink to accomplish your task. </span>")
to_chat(traitor.current, "<span class='userdanger'>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</span>")
else
to_chat(traitor.current, "<span class='userdanger'>You are the [traitor_name].</span>")
to_chat(traitor.current, "<span class='userdanger'>Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.</span>")
to_chat(traitor.current, "<B><font size=5 color=red>While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.</font></B>")
to_chat(traitor.current, "<span class='userdanger'>For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.</span>")
to_chat(traitor.current, "<span class='userdanger'>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</span>")
traitor.announce_objectives()
@@ -301,6 +320,8 @@
/datum/game_mode/traitor/internal_affairs/give_codewords(mob/living/traitor_mob)
return
#undef PROB_ACTUAL_TRAITOR
#undef PINPOINTER_EXTRA_RANDOM_RANGE
#undef PINPOINTER_MINIMUM_RANGE
#undef PINPOINTER_PING_TIME
+55 -51
View File
@@ -85,40 +85,65 @@
character.make_Traitor()
/datum/game_mode/proc/forge_single_objective(datum/mind/traitor) //Returns how many objectives are added
.=1
if(issilicon(traitor.current))
var/special_pick = rand(1,4)
switch(special_pick)
if(1)
var/datum/objective/block/block_objective = new
block_objective.owner = traitor
traitor.objectives += block_objective
if(2)
var/datum/objective/purge/purge_objective = new
purge_objective.owner = traitor
traitor.objectives += purge_objective
if(3)
var/datum/objective/robot_army/robot_objective = new
robot_objective.owner = traitor
traitor.objectives += robot_objective
if(4) //Protect and strand a target
var/datum/objective/protect/yandere_one = new
yandere_one.owner = traitor
traitor.objectives += yandere_one
yandere_one.find_target()
var/datum/objective/maroon/yandere_two = new
yandere_two.owner = traitor
yandere_two.target = yandere_one.target
yandere_two.update_explanation_text() // normally called in find_target()
traitor.objectives += yandere_two
.=2
else
if(prob(50))
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = traitor
destroy_objective.find_target()
traitor.objectives += destroy_objective
else if(prob(30))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = traitor
maroon_objective.find_target()
traitor.objectives += maroon_objective
else
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = traitor
kill_objective.find_target()
traitor.objectives += kill_objective
else
var/datum/objective/steal/steal_objective = new
steal_objective.owner = traitor
steal_objective.find_target()
traitor.objectives += steal_objective
/datum/game_mode/proc/forge_traitor_objectives(datum/mind/traitor)
if(issilicon(traitor.current))
var/objective_count = 0
if(prob(30))
var/special_pick = rand(1,4)
switch(special_pick)
if(1)
var/datum/objective/block/block_objective = new
block_objective.owner = traitor
traitor.objectives += block_objective
objective_count++
if(2)
var/datum/objective/purge/purge_objective = new
purge_objective.owner = traitor
traitor.objectives += purge_objective
objective_count++
if(3)
var/datum/objective/robot_army/robot_objective = new
robot_objective.owner = traitor
traitor.objectives += robot_objective
objective_count++
if(4) //Protect and strand a target
var/datum/objective/protect/yandere_one = new
yandere_one.owner = traitor
traitor.objectives += yandere_one
yandere_one.find_target()
objective_count++
var/datum/objective/maroon/yandere_two = new
yandere_two.owner = traitor
yandere_two.target = yandere_one.target
yandere_two.update_explanation_text() // normally called in find_target()
traitor.objectives += yandere_two
objective_count++
objective_count+=forge_single_objective(traitor)
for(var/i = objective_count, i < config.traitor_objectives_amount, i++)
var/datum/objective/assassinate/kill_objective = new
@@ -142,29 +167,8 @@
assign_exchange_role(exchange_red)
assign_exchange_role(exchange_blue)
objective_count += 1 //Exchange counts towards number of objectives
var/list/active_ais = active_ais()
for(var/i = objective_count, i < config.traitor_objectives_amount, i++)
if(prob(50))
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = traitor
destroy_objective.find_target()
traitor.objectives += destroy_objective
else if(prob(30))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = traitor
maroon_objective.find_target()
traitor.objectives += maroon_objective
else
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = traitor
kill_objective.find_target()
traitor.objectives += kill_objective
else
var/datum/objective/steal/steal_objective = new
steal_objective.owner = traitor
steal_objective.find_target()
traitor.objectives += steal_objective
forge_single_objective(traitor)
if(is_hijacker && objective_count <= config.traitor_objectives_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
if (!(locate(/datum/objective/hijack) in traitor.objectives))
+1 -1
View File
@@ -133,7 +133,7 @@
/datum/game_mode/wizard/raginmages/declare_completion()
if(finished)
SSblackbox.set_details("round_end_result","loss - wizard killed")
SSticker.mode_result = "loss - wizard killed"
to_chat(world, "<FONT size=3><B>The crew has managed to hold off the wizard attack! The Space Wizards Federation has been taught a lesson they will not soon forget!</B></FONT>")
..(1)
+1 -1
View File
@@ -180,7 +180,7 @@
/datum/game_mode/wizard/declare_completion()
if(finished)
SSblackbox.set_details("round_end_result","loss - wizard killed")
SSticker.mode_result = "loss - wizard killed"
to_chat(world, "<span class='userdanger'>The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!</span>")
SSticker.news_report = WIZARD_KILLED
+14 -8
View File
@@ -44,8 +44,8 @@
"corazone", // prevents cardiac arrest damage
"mimesbane") // stops them gasping from lack of air.
/obj/machinery/clonepod/New()
..()
/obj/machinery/clonepod/Initialize()
. = ..()
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/clonepod(null)
B.apply_default_parts(src)
@@ -358,8 +358,12 @@
/obj/machinery/clonepod/proc/go_out()
countdown.stop()
var/mob/living/mob_occupant = occupant
var/turf/T = get_turf(src)
if(mess) //Clean that mess and dump those gibs!
for(var/obj/fl in unattached_flesh)
fl.forceMove(T)
unattached_flesh.Cut()
mess = FALSE
new /obj/effect/gibspawner/generic(loc)
audible_message("<span class='italics'>You hear a splat.</span>")
@@ -375,10 +379,12 @@
to_chat(occupant, "<span class='notice'><b>There is a bright flash!</b><br><i>You feel like a new being.</i></span>")
mob_occupant.flash_act()
var/turf/T = get_turf(src)
occupant.forceMove(T)
icon_state = "pod_0"
mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
for(var/fl in unattached_flesh)
qdel(fl)
unattached_flesh.Cut()
occupant = null
@@ -389,8 +395,7 @@
SPEAK("Critical error! Please contact a Thinktronic Systems \
technician, as your warranty may be affected.")
mess = TRUE
for(var/obj/item/O in unattached_flesh)
qdel(O)
maim_clone(mob_occupant) //Remove every bit that's grown back so far to drop later, also destroys bits that haven't grown yet
icon_state = "pod_g"
if(mob_occupant.mind != clonemind)
clonemind.transfer_to(mob_occupant)
@@ -450,9 +455,10 @@
var/static/list/zones = list("r_arm", "l_arm", "r_leg", "l_leg")
for(var/zone in zones)
var/obj/item/bodypart/BP = H.get_bodypart(zone)
BP.drop_limb()
BP.forceMove(src)
unattached_flesh += BP
if(BP)
BP.drop_limb()
BP.forceMove(src)
unattached_flesh += BP
for(var/o in H.internal_organs)
var/obj/item/organ/organ = o
+9 -5
View File
@@ -1056,17 +1056,21 @@
/obj/effect/mob_spawn/human/corpse/orionsecurity
name = "Spaceport Security"
id_job = "Officer"
id_access_list = list(GLOB.access_syndicate)
outfit = /datum/outfit/orionsecurity
/datum/outfit/orionsecurity
name = "Orion Spaceport Security"
uniform = /obj/item/clothing/under/syndicate
suit = /obj/item/clothing/suit/armor/vest
shoes = /obj/item/clothing/shoes/combat
gloves = /obj/item/clothing/gloves/combat
radio = /obj/item/device/radio/headset
ears = /obj/item/device/radio/headset
mask = /obj/item/clothing/mask/gas
helmet = /obj/item/clothing/head/helmet/swat
head = /obj/item/clothing/head/helmet/swat
back = /obj/item/weapon/storage/backpack
has_id = 1
id_job = "Officer"
id_access_list = list(GLOB.access_syndicate)
id = /obj/item/weapon/card/id
/obj/item/weapon/orion_ship
name = "model settler ship"
@@ -178,7 +178,7 @@
/obj/item/weapon/circuitboard/computer/xenobiology
name = "circuit board (Xenobiology Console)"
build_path = /obj/machinery/computer/camera_advanced/xenobio
origin_tech = "programming=3;bio=3"
origin_tech = "programming=3;biotech=3"
/obj/item/weapon/circuitboard/computer/base_construction
name = "circuit board (Aux Mining Base Construction Console)"
build_path = /obj/machinery/computer/camera_advanced/base_construction
@@ -151,13 +151,13 @@ obj/machinery/computer/camera_advanced/attack_ai(mob/user)
var/mob/camera/aiEye/remote/remote_eye = C.remote_control
remote_eye.origin.current_user = null
remote_eye.origin.jump_action.Remove(C)
remote_eye.eye_user = null
if(C.client)
C.reset_perspective(null)
if(remote_eye.visible_icon)
C.client.images -= remote_eye.user_image
for(var/datum/camerachunk/chunk in remote_eye.visibleCameraChunks)
chunk.remove(remote_eye)
remote_eye.eye_user = null
C.remote_control = null
C.unset_machine()
Remove(C)
@@ -54,7 +54,7 @@
/obj/machinery/computer/communications/Topic(href, href_list)
if(..())
return
if (src.z > ZLEVEL_CENTCOM) //Can only use on centcom and SS13
if (z != ZLEVEL_STATION && z != ZLEVEL_CENTCOM) //Can only use on centcom and SS13
to_chat(usr, "<span class='boldannounce'>Unable to establish a connection</span>: \black You're too far away from the station!")
return
usr.set_machine(src)
+1 -1
View File
@@ -317,7 +317,7 @@
/obj/machinery/disco/proc/dance(var/mob/living/M) //Show your moves
set waitfor = FALSE
switch(rand(0,9))
if(0 to 1)
dance2(M)
+10 -14
View File
@@ -97,7 +97,14 @@
var/static/list/airlock_overlays = list()
/obj/machinery/door/airlock/Initialize()
..()
. = ..()
if (cyclelinkeddir)
cyclelinkairlock()
if(frequency)
set_frequency(frequency)
update_icon()
wires = new /datum/wires/airlock(src)
if(src.closeOtherId != null)
spawn (5)
@@ -120,14 +127,6 @@
diag_hud.add_to_hud(src)
diag_hud_set_electrified()
/obj/machinery/door/airlock/Initialize()
..()
if (cyclelinkeddir)
cyclelinkairlock()
if(frequency)
set_frequency(frequency)
update_icon()
/obj/machinery/door/airlock/proc/cyclelinkairlock()
if (cyclelinkedairlock)
cyclelinkedairlock.cyclelinkedairlock = null
@@ -199,14 +198,11 @@
qdel(src)
/obj/machinery/door/airlock/Destroy()
qdel(wires)
wires = null
QDEL_NULL(wires)
if(charge)
qdel(charge)
charge = null
if(electronics)
qdel(electronics)
electronics = null
QDEL_NULL(electronics)
if (cyclelinkedairlock)
if (cyclelinkedairlock.cyclelinkedairlock == src)
cyclelinkedairlock.cyclelinkedairlock = null
+4 -4
View File
@@ -1,5 +1,5 @@
GLOBAL_LIST_EMPTY(doppler_arrays)
GLOBAL_LIST_EMPTY(doppler_arrays)
/obj/machinery/doppler_array
name = "tachyon-doppler array"
desc = "A highly precise directional sensor array which measures the release of quants from decaying tachyons. The doppler shifting of the mirror-image formed by these quants can reveal the size, location and temporal affects of energetic disturbances within a large radius ahead of the array.\n<span class='notice'>Alt-click to rotate it clockwise.</span>"
@@ -13,10 +13,10 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
/obj/machinery/doppler_array/New()
..()
GLOB.doppler_arrays += src
GLOB.doppler_arrays += src
/obj/machinery/doppler_array/Destroy()
GLOB.doppler_arrays -= src
GLOB.doppler_arrays -= src
return ..()
/obj/machinery/doppler_array/process()
+11 -1
View File
@@ -51,7 +51,7 @@ Possible to do for anyone motivated enough:
var/static/list/holopads = list()
/obj/machinery/holopad/Initialize()
..()
. = ..()
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/holopad(null)
B.apply_default_parts(src)
holopads += src
@@ -112,6 +112,10 @@ Possible to do for anyone motivated enough:
return ..()
/obj/machinery/holopad/AltClick(mob/living/carbon/human/user)
if(isAI(user))
hangup_all_calls()
return
if(!CheckCallClose())
interact(user)
@@ -157,6 +161,12 @@ Possible to do for anyone motivated enough:
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
//Stop ringing the AI!!
/obj/machinery/holopad/proc/hangup_all_calls()
for(var/I in holo_calls)
var/datum/holocall/HC = I
HC.Disconnect(src)
/obj/machinery/holopad/Topic(href, href_list)
if(..() || isAI(usr))
return
@@ -87,7 +87,9 @@
if(has_cover)
cover = new /obj/machinery/porta_turret_cover(loc)
cover.parent_turret = src
underlays += image('icons/obj/turrets.dmi',icon_state = "basedark")
var/mutable_appearance/base = mutable_appearance('icons/obj/turrets.dmi', "basedark")
base.layer = NOT_HIGH_OBJ_LAYER
underlays += base
if(!has_cover)
INVOKE_ASYNC(src, .proc/popUp)
+1 -1
View File
@@ -154,7 +154,7 @@
M.forceMove(loc)
if(prob(30))
explosion(get_turf(loc), 0, 0, 1, 3)
explosion(get_turf(loc), 0, 0, 1, 3)
if(wreckage)
var/obj/structure/mecha_wreckage/WR = new wreckage(loc, AI)
+1 -1
View File
@@ -39,7 +39,7 @@
var/range_flash = 3
/obj/effect/mine/explosive/mineEffect(mob/victim)
explosion(loc, range_devastation, range_heavy, range_light, range_flash)
explosion(loc, range_devastation, range_heavy, range_light, range_flash)
/obj/effect/mine/stun
+10 -3
View File
@@ -632,7 +632,14 @@ GLOBAL_LIST_EMPTY(PDAs)
L = get(src, /mob/living/silicon)
if(L && L.stat != UNCONSCIOUS)
to_chat(L, "\icon[src] <b>Message from [source.owner] ([source.ownjob]), </b>\"[msg.message]\"[msg.get_photo_ref()] (<a href='byond://?src=\ref[src];choice=Message;skiprefresh=1;target=\ref[source]'>Reply</a>)")
var/hrefstart
var/hrefend
if (isAI(L))
hrefstart = "<a href='?src=\ref[L];track=[html_encode(source.owner)]'>"
hrefend = "</a>"
to_chat(L, "\icon[src.icon] <b>Message from [hrefstart][source.owner] ([source.ownjob])[hrefend], </b>\"[msg.message]\"[msg.get_photo_ref()] (<a href='byond://?src=\ref[src];choice=Message;skiprefresh=1;target=\ref[source]'>Reply</a>)")
update_icon()
add_overlay(icon_alert)
@@ -890,9 +897,9 @@ GLOBAL_LIST_EMPTY(PDAs)
if(T)
T.hotspot_expose(700,125)
if(istype(cartridge, /obj/item/weapon/cartridge/syndicate))
explosion(T, -1, 1, 3, 4)
explosion(T, -1, 1, 3, 4)
else
explosion(T, -1, -1, 2, 3)
explosion(T, -1, -1, 2, 3)
qdel(src)
return
+8 -9
View File
@@ -10,15 +10,14 @@
resistance_flags = FIRE_PROOF | ACID_PROOF | INDESTRUCTIBLE
/obj/item/device/paicard/Initialize()
..()
SSpai.pai_card_list += src
add_overlay("pai-off")
return ..()
/obj/item/device/paicard/Destroy()
//Will stop people throwing friend pAIs into the singularity so they can respawn
SSpai.pai_card_list -= src
if(!isnull(pai))
pai.death(0)
QDEL_NULL(pai)
return ..()
/obj/item/device/paicard/attack_self(mob/user)
@@ -26,9 +25,9 @@
return
user.set_machine(src)
var/dat = "<TT><B>Personal AI Device</B><BR>"
if(pai && (!pai.master_dna || !pai.master))
dat += "<a href='byond://?src=\ref[src];setdna=1'>Imprint Master DNA</a><br>"
if(pai)
if(!pai.master_dna || !pai.master)
dat += "<a href='byond://?src=\ref[src];setdna=1'>Imprint Master DNA</a><br>"
dat += "Installed Personality: [pai.name]<br>"
dat += "Prime directive: <br>[pai.laws.zeroth]<br>"
for(var/slaws in pai.laws.supplied)
@@ -86,7 +85,7 @@
to_chat(pai, "<span class='danger'>Byte by byte you lose your sense of self.</span>")
to_chat(pai, "<span class='userdanger'>Your mental faculties leave you.</span>")
to_chat(pai, "<span class='rose'>oblivion... </span>")
pai.death(0)
removePersonality()
if(href_list["wires"])
var/wire = text2num(href_list["wires"])
if(pai.radio)
@@ -119,9 +118,9 @@
audible_message("\The [src] plays a cheerful startup noise!")
/obj/item/device/paicard/proc/removePersonality()
src.pai = null
src.cut_overlays()
src.add_overlay("pai-off")
QDEL_NULL(pai)
cut_overlays()
add_overlay("pai-off")
/obj/item/device/paicard/proc/setEmotion(emotion)
if(pai)
+1 -1
View File
@@ -141,5 +141,5 @@
if(power_drained >= max_power)
STOP_PROCESSING(SSobj, src)
explosion(src.loc, 4,8,16,32)
explosion(src.loc, 4,8,16,32)
qdel(src)
+16 -11
View File
@@ -504,6 +504,8 @@
S.change_head_color(color2)
dropped = TRUE
#define PKBORG_DAMPEN_CYCLE_DELAY 20
//Peacekeeper Cyborg Projectile Dampenening Field
/obj/item/borg/projectile_dampen
name = "Hyperkinetic Dampening projector"
@@ -526,6 +528,7 @@
var/image/projectile_effect
var/field_radius = 3
var/active = FALSE
var/cycle_delay = 0
/obj/item/borg/projectile_dampen/debug
maxenergy = 50000
@@ -545,29 +548,31 @@
return ..()
/obj/item/borg/projectile_dampen/attack_self(mob/user)
if(!istype(dampening_field))
activate_field()
active = TRUE
if(cycle_delay > world.time)
to_chat(user, "<span class='boldwarning'>\the [src] is still recycling its projectors!</span>")
return
cycle_delay = world.time + PKBORG_DAMPEN_CYCLE_DELAY
active = !active
if(active)
activate_field(user)
else
deactivate_field()
active = FALSE
update_icon()
to_chat(user, "<span class='boldnotice'>You [active? "activate":"deactivate"] the [src].</span>")
/obj/item/borg/projectile_dampen/update_icon()
. = ..()
icon_state = "[initial(icon_state)][active]"
/obj/item/borg/projectile_dampen/proc/activate_field()
if(!istype(dampening_field))
dampening_field = make_field(/datum/proximity_monitor/advanced/peaceborg_dampener, list("current_range" = field_radius, "host" = src, "projector" = src))
update_icon()
if(istype(dampening_field))
QDEL_NULL(dampening_field)
dampening_field = make_field(/datum/proximity_monitor/advanced/peaceborg_dampener, list("current_range" = field_radius, "host" = src, "projector" = src))
/obj/item/borg/projectile_dampen/proc/deactivate_field()
QDEL_NULL(dampening_field)
visible_message("<span class='warning'>The [src] shuts off!</span>")
for(var/obj/item/projectile/P in tracked)
visible_message("<span class='warning'>\The [src] shuts off!</span>")
for(var/P in tracked)
restore_projectile(P)
update_icon()
/obj/item/borg/projectile_dampen/dropped()
. = ..()
@@ -22,6 +22,11 @@ Mineral Sheets
/obj/item/stack/sheet/mineral
icon = 'icons/obj/mining.dmi'
/obj/item/stack/sheet/mineral/Initialize(mapload)
pixel_x = rand(-4, 4)
pixel_y = rand(-4, 4)
. = ..()
/*
* Sandstone
*/
@@ -31,9 +36,7 @@ GLOBAL_LIST_INIT(sandstone_recipes, list ( \
new/datum/stack_recipe("sandstone door", /obj/structure/mineral_door/sandstone, 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("aesthetic volcanic floor tile", /obj/item/stack/tile/basalt, 2, 2, 4, 20), \
new/datum/stack_recipe("Assistant Statue", /obj/structure/statue/sandstone/assistant, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("Breakdown into sand", /obj/item/weapon/ore/glass, 1, one_per_turf = 0, on_floor = 1), \
/* new/datum/stack_recipe("sandstone wall", ???), \
new/datum/stack_recipe("sandstone floor", ???),\ */
new/datum/stack_recipe("Breakdown into sand", /obj/item/weapon/ore/glass, 1, one_per_turf = 0, on_floor = 1) \
))
/obj/item/stack/sheet/mineral/sandstone
@@ -49,9 +52,7 @@ GLOBAL_LIST_INIT(sandstone_recipes, list ( \
/obj/item/stack/sheet/mineral/sandstone/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.sandstone_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
. = ..()
/obj/item/stack/sheet/mineral/sandstone/thirty
amount = 30
@@ -74,9 +75,24 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \
/obj/item/stack/sheet/mineral/sandbags/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.sandbag_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
. = ..()
/obj/item/weapon/emptysandbag
name = "empty sandbag"
desc = "A bag to be filled with sand."
icon = 'icons/obj/items.dmi'
icon_state = "sandbag"
w_class = WEIGHT_CLASS_TINY
/obj/item/weapon/emptysandbag/attackby(obj/item/W, mob/user, params)
if(istype(W,/obj/item/weapon/ore/glass))
to_chat(user, "<span class='notice'>You fill the sandbag.</span>")
var/obj/item/stack/sheet/mineral/sandbags/I = new /obj/item/stack/sheet/mineral/sandbags
qdel(src)
user.put_in_hands(I)
qdel(W)
else
return ..()
/*
* Diamond
@@ -99,9 +115,7 @@ GLOBAL_LIST_INIT(diamond_recipes, list ( \
/obj/item/stack/sheet/mineral/diamond/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.diamond_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
. = ..()
/*
* Uranium
@@ -123,9 +137,7 @@ GLOBAL_LIST_INIT(uranium_recipes, list ( \
/obj/item/stack/sheet/mineral/uranium/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.uranium_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
. = ..()
/*
* Plasma
@@ -149,9 +161,7 @@ GLOBAL_LIST_INIT(plasma_recipes, list ( \
/obj/item/stack/sheet/mineral/plasma/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.plasma_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
. = ..()
/obj/item/stack/sheet/mineral/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
@@ -190,9 +200,7 @@ GLOBAL_LIST_INIT(gold_recipes, list ( \
/obj/item/stack/sheet/mineral/gold/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.gold_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
. = ..()
/*
* Silver
@@ -217,9 +225,7 @@ GLOBAL_LIST_INIT(silver_recipes, list ( \
/obj/item/stack/sheet/mineral/silver/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.silver_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
. = ..()
/*
* Clown
@@ -239,9 +245,7 @@ GLOBAL_LIST_INIT(clown_recipes, list ( \
/obj/item/stack/sheet/mineral/bananium/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.clown_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
. = ..()
/*
* Titanium
@@ -265,9 +269,7 @@ GLOBAL_LIST_INIT(titanium_recipes, list ( \
/obj/item/stack/sheet/mineral/titanium/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.titanium_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
. = ..()
/*
@@ -292,9 +294,7 @@ GLOBAL_LIST_INIT(plastitanium_recipes, list ( \
/obj/item/stack/sheet/mineral/plastitanium/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.plastitanium_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
. = ..()
/*
@@ -316,9 +316,7 @@ GLOBAL_LIST_INIT(snow_recipes, list ( \
/obj/item/stack/sheet/mineral/snow/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.snow_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
. = ..()
/****************************** Others ****************************/
@@ -347,7 +345,7 @@ GLOBAL_LIST_INIT(adamantine_recipes, list(
/obj/item/stack/sheet/mineral/adamantine/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.adamantine_recipes
..()
. = ..()
/*
* Mythril
@@ -384,4 +382,4 @@ GLOBAL_LIST_INIT(abductor_recipes, list ( \
/obj/item/stack/sheet/mineral/abductor/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.abductor_recipes
..()
. = ..()
@@ -83,6 +83,14 @@
var/list/access = list()
var/registered_name = null // The name registered_name on the card
var/assignment = null
var/access_txt // mapping aid
/obj/item/weapon/card/id/Initialize(mapload)
. = ..()
if(mapload && access_txt)
access = text2access(access_txt)
/obj/item/weapon/card/id/attack_self(mob/user)
user.visible_message("<span class='notice'>[user] shows you: \icon[src] [src.name].</span>", \
@@ -54,10 +54,10 @@
var/obj/effect/chrono_field/field = null
var/turf/startpos = null
/obj/item/weapon/gun/energy/chrono_gun/New(var/obj/item/weapon/chrono_eraser/T)
/obj/item/weapon/gun/energy/chrono_gun/Initialize()
. = ..()
if(istype(T))
TED = T
if(istype(loc, /obj/item/weapon/chrono_eraser))
TED = loc
else //admin must have spawned it
TED = new(src.loc)
qdel(src)
@@ -622,6 +622,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
icon = 'icons/obj/clothing/masks.dmi'
icon_state = null
item_state = null
w_class = WEIGHT_CLASS_TINY
var/chem_volume = 100
var/vapetime = 0 //this so it won't puff out clouds every tick
var/screw = 0 // kinky
@@ -633,8 +634,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM
return (TOXLOSS|OXYLOSS)
/obj/item/clothing/mask/vape/New(loc, var/param_color = null)
..()
/obj/item/clothing/mask/vape/Initialize(mapload, param_color)
. = ..()
create_reagents(chem_volume)
reagents.set_reacting(FALSE) // so it doesn't react until you light it
reagents.add_reagent("nicotine", 50)
+8 -8
View File
@@ -23,14 +23,14 @@
var/combat = 0 //can we revive through space suits?
var/grab_ghost = FALSE // Do we pull the ghost back into their body?
/obj/item/weapon/defibrillator/New() //starts without a cell for rnd
..()
/obj/item/weapon/defibrillator/Initialize() //starts without a cell for rnd
. = ..()
paddles = make_paddles()
update_icon()
return
/obj/item/weapon/defibrillator/loaded/New() //starts with hicap
..()
/obj/item/weapon/defibrillator/loaded/Initialize() //starts with hicap
. = ..()
paddles = make_paddles()
bcell = new(src)
update_icon()
@@ -237,8 +237,8 @@
if(slot == user.getBeltSlot())
return 1
/obj/item/weapon/defibrillator/compact/loaded/New()
..()
/obj/item/weapon/defibrillator/compact/loaded/Initialize()
. = ..()
paddles = make_paddles()
bcell = new(src)
update_icon()
@@ -249,8 +249,8 @@
combat = 1
safety = 0
/obj/item/weapon/defibrillator/compact/combat/loaded/New()
..()
/obj/item/weapon/defibrillator/compact/combat/loaded/Initialize()
. = ..()
paddles = make_paddles()
bcell = new /obj/item/weapon/stock_parts/cell/infinite(src)
update_icon()
+66 -72
View File
@@ -14,14 +14,16 @@
origin_tech = "combat=1;plasmatech=2;engineering=2"
resistance_flags = FIRE_PROOF
var/status = 0
var/throw_amount = 100
var/lit = 0 //on or off
var/operating = 0//cooldown
var/obj/item/weapon/weldingtool/weldtool = null
var/obj/item/device/assembly/igniter/igniter = null
var/obj/item/weapon/tank/internals/plasma/ptank = null
var/warned_admins = 0 //for the message_admins() when lit
//variables for prebuilt flamethrowers
var/create_full = FALSE
var/create_with_tank = FALSE
var/igniter_type = /obj/item/device/assembly/igniter
/obj/item/weapon/flamethrower/Destroy()
if(weldtool)
@@ -32,9 +34,8 @@
qdel(ptank)
return ..()
/obj/item/weapon/flamethrower/process()
if(!lit)
if(!lit || !igniter)
STOP_PROCESSING(SSobj, src)
return null
var/turf/location = loc
@@ -43,8 +44,7 @@
if(M.is_holding(src))
location = M.loc
if(isturf(location)) //start a fire if possible
location.hotspot_expose(700, 2)
return
igniter.flamethrower_process(location)
/obj/item/weapon/flamethrower/update_icon()
@@ -58,6 +58,9 @@
item_state = "flamethrower_1"
else
item_state = "flamethrower_0"
if(ismob(loc))
var/mob/M = loc
M.update_inv_hands()
return
/obj/item/weapon/flamethrower/afterattack(atom/target, mob/user, flag)
@@ -82,13 +85,13 @@
if(istype(W, /obj/item/weapon/wrench) && !status)//Taking this apart
var/turf/T = get_turf(src)
if(weldtool)
weldtool.loc = T
weldtool.forceMove(T)
weldtool = null
if(igniter)
igniter.loc = T
igniter.forceMove(T)
igniter = null
if(ptank)
ptank.loc = T
ptank.forceMove(T)
ptank = null
new /obj/item/stack/rods(T)
qdel(src)
@@ -114,7 +117,10 @@
else if(istype(W,/obj/item/weapon/tank/internals/plasma))
if(ptank)
to_chat(user, "<span class='notice'>There is already a plasma tank loaded in [src]!</span>")
if(user.transferItemToLoc(W,src))
ptank.forceMove(get_turf(src))
ptank = W
to_chat(user, "<span class='notice'>You swap the plasma tank in [src]!</span>")
return
if(!user.transferItemToLoc(W, src))
return
@@ -129,53 +135,26 @@
/obj/item/weapon/flamethrower/attack_self(mob/user)
if(user.stat || user.restrained() || user.lying)
return
user.set_machine(src)
toggle_igniter(user)
/obj/item/weapon/flamethrower/proc/toggle_igniter(mob/user)
if(!ptank)
to_chat(user, "<span class='notice'>Attach a plasma tank first!</span>")
return
var/dat = text("<TT><B>Flamethrower (<A HREF='?src=\ref[src];light=1'>[lit ? "<font color='red'>Lit</font>" : "Unlit"]</a>)</B><BR>\n Tank Pressure: [ptank.air_contents.return_pressure()]<BR>\nAmount to throw: <A HREF='?src=\ref[src];amount=-100'>-</A> <A HREF='?src=\ref[src];amount=-10'>-</A> <A HREF='?src=\ref[src];amount=-1'>-</A> [throw_amount] <A HREF='?src=\ref[src];amount=1'>+</A> <A HREF='?src=\ref[src];amount=10'>+</A> <A HREF='?src=\ref[src];amount=100'>+</A><BR>\n<A HREF='?src=\ref[src];remove=1'>Remove plasmatank</A> - <A HREF='?src=\ref[src];close=1'>Close</A></TT>")
user << browse(dat, "window=flamethrower;size=600x300")
onclose(user, "flamethrower")
return
/obj/item/weapon/flamethrower/Topic(href,href_list[])
if(href_list["close"])
usr.unset_machine()
usr << browse(null, "window=flamethrower")
if(!status)
to_chat(user, "<span class='notice'>Secure the igniter first!</span>")
return
if(usr.stat || usr.restrained() || usr.lying)
return
usr.set_machine(src)
if(href_list["light"])
if(!ptank)
return
if(!status)
return
lit = !lit
if(lit)
START_PROCESSING(SSobj, src)
if(!warned_admins)
message_admins("[ADMIN_LOOKUPFLW(usr)] has lit a flamethrower.")
warned_admins = 1
if(href_list["amount"])
throw_amount = throw_amount + text2num(href_list["amount"])
throw_amount = max(50, min(5000, throw_amount))
if(href_list["remove"])
if(!ptank)
return
usr.put_in_hands(ptank)
ptank = null
lit = 0
usr.unset_machine()
usr << browse(null, "window=flamethrower")
for(var/mob/M in viewers(1, loc))
if((M.client && M.machine == src))
attack_self(M)
to_chat(user, "<span class='notice'>You ignite [src]!</span>")
lit = !lit
if(lit)
START_PROCESSING(SSobj, src)
if(!warned_admins)
message_admins("[ADMIN_LOOKUPFLW(user)] has lit a flamethrower.")
warned_admins = 1
else
STOP_PROCESSING(SSobj,src)
update_icon()
return
/obj/item/weapon/flamethrower/CheckParts(list/parts_list)
..()
@@ -195,19 +174,22 @@
for(var/turf/T in turflist)
if(T == previousturf)
continue //so we don't burn the tile we be standin on
if(!T.atmos_adjacent_turfs || !T.atmos_adjacent_turfs[previousturf])
var/list/turfs_sharing_with_prev = previousturf.GetAtmosAdjacentTurfs(alldir=1)
if(!(T in turfs_sharing_with_prev))
break
ignite_turf(T)
if(igniter)
igniter.ignite_turf(src,T)
else
default_ignite(T)
sleep(1)
previousturf = T
operating = 0
for(var/mob/M in viewers(1, loc))
if((M.client && M.machine == src))
attack_self(M)
return
/obj/item/weapon/flamethrower/proc/ignite_turf(turf/target, release_amount = 0.05)
/obj/item/weapon/flamethrower/proc/default_ignite(turf/target, release_amount = 0.05)
//TODO: DEFERRED Consider checking to make sure tank pressure is high enough before doing this...
//Transfer 5% of current tank air contents to turf
var/datum/gas_mixture/air_transfer = ptank.air_contents.remove_ratio(release_amount)
@@ -218,30 +200,42 @@
target.hotspot_expose((ptank.air_contents.temperature*2) + 380,500)
//location.hotspot_expose(1000,500,1)
SSair.add_to_active(target, 0)
return
/obj/item/weapon/flamethrower/full/New(var/loc)
..()
if(!weldtool)
weldtool = new /obj/item/weapon/weldingtool(src)
weldtool.status = 0
if(!igniter)
igniter = new /obj/item/device/assembly/igniter(src)
igniter.secured = 0
status = 1
update_icon()
/obj/item/weapon/flamethrower/Initialize(mapload)
. = ..()
if(create_full)
if(!weldtool)
weldtool = new /obj/item/weapon/weldingtool(src)
weldtool.status = 0
if(!igniter)
igniter = new igniter_type(src)
igniter.secured = 0
status = 1
if(create_with_tank)
ptank = new /obj/item/weapon/tank/internals/plasma/full(src)
update_icon()
/obj/item/weapon/flamethrower/full/tank/New(var/loc)
..()
ptank = new /obj/item/weapon/tank/internals/plasma/full(src)
update_icon()
/obj/item/weapon/flamethrower/full/tank
create_full = TRUE
/obj/item/weapon/flamethrower/full/tank
create_with_tank = TRUE
/obj/item/weapon/flamethrower/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance, damage, attack_type)
if(ptank && damage && attack_type == PROJECTILE_ATTACK && prob(15))
owner.visible_message("<span class='danger'>[attack_text] hits the fueltank on [owner]'s [src], rupturing it! What a shot!</span>")
var/target_turf = get_turf(owner)
ignite_turf(target_turf, 100)
igniter.ignite_turf(src,target_turf, release_amount = 100)
qdel(ptank)
return 1 //It hit the flamethrower, not them
/obj/item/device/assembly/igniter/proc/flamethrower_process(turf/open/location)
location.hotspot_expose(700,2)
/obj/item/device/assembly/igniter/cold/flamethrower_process(turf/open/location)
return
/obj/item/device/assembly/igniter/proc/ignite_turf(obj/item/weapon/flamethrower/F,turf/open/location,release_amount = 0.05)
F.default_ignite(location,release_amount)
@@ -59,7 +59,7 @@
/obj/item/weapon/grenade/iedcasing/prime() //Blowing that can up
update_mob()
explosion(src.loc,-1,-1,2, flame_range = 4) // small explosion, plus a very large fireball.
explosion(src.loc,-1,-1,2, flame_range = 4) // small explosion, plus a very large fireball.
qdel(src)
/obj/item/weapon/grenade/iedcasing/examine(mob/user)
@@ -235,7 +235,7 @@
to_chat(user, "<span class='notice'>You start planting the bomb...</span>")
if(do_after(user, 50, target = AM))
if(do_after(user, 30, target = AM))
if(!user.temporarilyRemoveItemFromInventory(src))
return
src.target = AM
@@ -9,7 +9,7 @@
/obj/item/weapon/grenade/syndieminibomb/prime()
update_mob()
explosion(src.loc,1,2,4,flame_range = 2)
explosion(src.loc,1,2,4,flame_range = 2)
qdel(src)
/obj/item/weapon/grenade/syndieminibomb/concussion
@@ -20,7 +20,7 @@
/obj/item/weapon/grenade/syndieminibomb/concussion/prime()
update_mob()
explosion(src.loc,0,2,3,flame_range = 3)
explosion(src.loc,0,2,3,flame_range = 3)
qdel(src)
/obj/item/weapon/grenade/syndieminibomb/concussion/frag
+3 -1
View File
@@ -65,6 +65,7 @@
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
sharpness = IS_SHARP_ACCURATE
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 50)
var/bayonet = FALSE //Can this be attached to a gun?
/obj/item/weapon/kitchen/knife/attack(mob/living/carbon/M, mob/living/carbon/user)
if(user.zone_selected == "eyes")
@@ -107,7 +108,7 @@
throwforce = 20
origin_tech = "materials=3;combat=4"
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "cut")
bayonet = TRUE
/obj/item/weapon/kitchen/knife/combat/survival
name = "survival knife"
@@ -115,6 +116,7 @@
desc = "A hunting grade survival knife."
force = 15
throwforce = 15
bayonet = TRUE
/obj/item/weapon/kitchen/knife/combat/bone
name = "bone dagger"
@@ -270,4 +270,4 @@
/obj/item/weapon/pneumatic_cannon/pie/selfcharge/process()
if(++charge_tick >= charge_ticks)
fill_with_type(/obj/item/weapon/reagent_containers/food/snacks/pie, charge_amount)
fill_with_type(/obj/item/weapon/reagent_containers/food/snacks/pie/cream, charge_amount)
@@ -83,7 +83,7 @@
/obj/item/weapon/storage/backpack/holding/singularity_act(current_size)
var/dist = max((current_size - 2),1)
explosion(src.loc,(dist),(dist*2),(dist*4))
explosion(src.loc,(dist),(dist*2),(dist*4))
return
+6 -8
View File
@@ -21,10 +21,9 @@
user.visible_message("<span class='suicide'>[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return (FIRELOSS)
/obj/item/weapon/melee/baton/New()
..()
/obj/item/weapon/melee/baton/Initialize()
. = ..()
update_icon()
return
/obj/item/weapon/melee/baton/throw_impact(atom/hit_atom)
..()
@@ -32,10 +31,9 @@
if(status && prob(throw_hit_chance) && iscarbon(hit_atom))
baton_stun(hit_atom)
/obj/item/weapon/melee/baton/loaded/New() //this one starts with a cell pre-installed.
..()
/obj/item/weapon/melee/baton/loaded/Initialize() //this one starts with a cell pre-installed.
bcell = new(src)
update_icon()
. = ..()
/obj/item/weapon/melee/baton/proc/deductcharge(chrgdeductamt)
if(bcell)
@@ -188,8 +186,8 @@
slot_flags = SLOT_BACK
var/obj/item/device/assembly/igniter/sparkler = 0
/obj/item/weapon/melee/baton/cattleprod/New()
..()
/obj/item/weapon/melee/baton/cattleprod/Initialize()
. = ..()
sparkler = new (src)
/obj/item/weapon/melee/baton/cattleprod/baton_stun()
@@ -140,7 +140,7 @@
item_state = "plasmaman_tank_belt"
slot_flags = SLOT_BELT
force = 5
volume = 3
volume = 6
w_class = WEIGHT_CLASS_SMALL //thanks i forgot this
/obj/item/weapon/tank/internals/plasmaman/belt/full/New()
+2 -2
View File
@@ -5,7 +5,7 @@
/obj/structure/easel
name = "easel"
desc = "only for the finest of art!"
desc = "Only for the finest of art!"
icon = 'icons/obj/artstuff.dmi'
icon_state = "easel"
density = 1
@@ -49,7 +49,7 @@ GLOBAL_LIST_INIT(globalBlankCanvases, new(AMT_OF_CANVASES))
/obj/item/weapon/canvas
name = "canvas"
desc = "draw out your soul on this canvas!"
desc = "Draw out your soul on this canvas!"
icon = 'icons/obj/artstuff.dmi'
icon_state = "11x11"
resistance_flags = FLAMMABLE
@@ -161,7 +161,16 @@
anchored = 0
buildstacktype = /obj/item/stack/sheet/mineral/wood
buildstackamount = 10
var/mob/living/owner = null
/obj/structure/bed/dogbed/proc/update_owner(mob/living/M)
owner = M
name = "[M]'s bed"
desc = "[M]'s bed! Looks comfy."
/obj/structure/bed/dogbed/buckle_mob(mob/living/M, force, check_loc)
. = ..()
update_owner(M)
/obj/structure/bed/alien
name = "resting contraption"
@@ -38,7 +38,7 @@
log_game("[key_name(user)] has detonated [src.name].")
for(var/atom/movable/AM in src)
qdel(AM)
explosion(get_turf(src), 0, 1, 5, 5)
explosion(get_turf(src), 0, 1, 5, 5)
qdel(src)
/obj/structure/closet/crate/secure/weapon
@@ -29,6 +29,7 @@
return ..()
//Ash walker eggs: Spawns in ash walker dens in lavaland. Ghosts become unbreathing lizards that worship the Necropolis and are advised to retrieve corpses to create more ash walkers.
/obj/effect/mob_spawn/human/ash_walker
name = "ash walker egg"
desc = "A man-sized yellow egg, spawned from some unfathomable creature. A humanoid silhouette lurks within."
@@ -36,8 +37,7 @@
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "large_egg"
mob_species = /datum/species/lizard/ashwalker
helmet = /obj/item/clothing/head/helmet/gladiator
uniform = /obj/item/clothing/under/gladiator/ash_walker
outfit = /datum/outfit/ashwalker
roundstart = FALSE
death = FALSE
anchored = 0
@@ -58,12 +58,18 @@
H.underwear = "Nude"
H.update_body()
/obj/effect/mob_spawn/human/ash_walker/New()
..()
/obj/effect/mob_spawn/human/ash_walker/Initialize(mapload)
. = ..()
var/area/A = get_area(src)
if(A)
notify_ghosts("An ash walker egg is ready to hatch in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE)
/datum/outfit/ashwalker
name ="Ashwalker"
head = /obj/item/clothing/head/helmet/gladiator
uniform = /obj/item/clothing/under/gladiator/ash_walker
//Timeless prisons: Spawns in Wish Granter prisons in lavaland. Ghosts become age-old users of the Wish Granter and are advised to seek repentance for their past.
/obj/effect/mob_spawn/human/exile
name = "timeless prison"
@@ -188,38 +194,38 @@
conditions of your makeshift shelter, the hostile creatures, and the ash drakes swooping down from the cloudless skies, all you can wish for is the feel of soft grass between your toes and \
the fresh air of Earth. These thoughts are dispelled by yet another recollection of how you got here... "
/obj/effect/mob_spawn/human/hermit/New()
/obj/effect/mob_spawn/human/hermit/Initialize(mapload)
. = ..()
var/arrpee = rand(1,4)
switch(arrpee)
if(1)
flavour_text += "you were a [pick("arms dealer", "shipwright", "docking manager")]'s assistant on a small trading station several sectors from here. Raiders attacked, and there was \
only one pod left when you got to the escape bay. You took it and launched it alone, and the crowd of terrified faces crowding at the airlock door as your pod's engines burst to \
life and sent you to this hell are forever branded into your memory.</b>"
uniform = /obj/item/clothing/under/assistantformal
shoes = /obj/item/clothing/shoes/sneakers/black
back = /obj/item/weapon/storage/backpack
outfit.uniform = /obj/item/clothing/under/assistantformal
outfit.shoes = /obj/item/clothing/shoes/sneakers/black
outfit.back = /obj/item/weapon/storage/backpack
if(2)
flavour_text += "you're an exile from the Tiger Cooperative. Their technological fanaticism drove you to question the power and beliefs of the Exolitics, and they saw you as a \
heretic and subjected you to hours of horrible torture. You were hours away from execution when a high-ranking friend of yours in the Cooperative managed to secure you a pod, \
scrambled its destination's coordinates, and launched it. You awoke from stasis when you landed and have been surviving - barely - ever since.</b>"
uniform = /obj/item/clothing/under/rank/prisoner
shoes = /obj/item/clothing/shoes/sneakers/orange
back = /obj/item/weapon/storage/backpack
outfit.uniform = /obj/item/clothing/under/rank/prisoner
outfit.shoes = /obj/item/clothing/shoes/sneakers/orange
outfit.back = /obj/item/weapon/storage/backpack
if(3)
flavour_text += "you were a doctor on one of Nanotrasen's space stations, but you left behind that damn corporation's tyranny and everything it stood for. From a metaphorical hell \
to a literal one, you find yourself nonetheless missing the recycled air and warm floors of what you left behind... but you'd still rather be here than there.</b>"
uniform = /obj/item/clothing/under/rank/medical
suit = /obj/item/clothing/suit/toggle/labcoat
back = /obj/item/weapon/storage/backpack/medic
shoes = /obj/item/clothing/shoes/sneakers/black
outfit.uniform = /obj/item/clothing/under/rank/medical
outfit.suit = /obj/item/clothing/suit/toggle/labcoat
outfit.back = /obj/item/weapon/storage/backpack/medic
outfit.shoes = /obj/item/clothing/shoes/sneakers/black
if(4)
flavour_text += "you were always joked about by your friends for \"not playing with a full deck\", as they so <i>kindly</i> put it. It seems that they were right when you, on a tour \
at one of Nanotrasen's state-of-the-art research facilities, were in one of the escape pods alone and saw the red button. It was big and shiny, and it caught your eye. You pressed \
it, and after a terrifying and fast ride for days, you landed here. You've had time to wisen up since then, and you think that your old friends wouldn't be laughing now.</b>"
uniform = /obj/item/clothing/under/color/grey/glorf
shoes = /obj/item/clothing/shoes/sneakers/black
back = /obj/item/weapon/storage/backpack
..()
outfit.uniform = /obj/item/clothing/under/color/grey/glorf
outfit.shoes = /obj/item/clothing/shoes/sneakers/black
outfit.back = /obj/item/weapon/storage/backpack
/obj/effect/mob_spawn/human/hermit/Destroy()
new/obj/structure/fluff/empty_cryostasis_sleeper(get_turf(src))
@@ -241,10 +247,7 @@
mob_name = "an escaped prisoner"
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "sleeper_s"
uniform = /obj/item/clothing/under/rank/prisoner
mask = /obj/item/clothing/mask/breath
shoes = /obj/item/clothing/shoes/sneakers/orange
pocket1 = /obj/item/weapon/tank/internals/emergency_oxygen
outfit = /datum/outfit/lavalandprisoner
roundstart = FALSE
death = FALSE
flavour_text = "<font size=3><b>G</b></font><b>ood. It seems as though your ship crashed. You're a prisoner, sentenced to hard work in one of Nanotrasen's labor camps, but it seems as \
@@ -254,12 +257,20 @@
L.real_name = "NTP #LL-0[rand(111,999)]" //Nanotrasen Prisoner #Lavaland-(numbers)
L.name = L.real_name
/obj/effect/mob_spawn/human/prisoner_transport/New()
/obj/effect/mob_spawn/human/prisoner_transport/Initialize(mapload)
. = ..()
var/list/crimes = list("murder", "larceny", "embezzlement", "unionization", "dereliction of duty", "kidnapping", "gross incompetence", "grand theft", "collaboration with the Syndicate", \
"worship of a forbidden deity", "interspecies relations", "mutiny")
flavour_text += "[pick(crimes)]. but regardless of that, it seems like your crime doesn't matter now. You don't know where you are, but you know that it's out to kill you, and you're not going \
to lose this opportunity. Find a way to get out of this mess and back to where you rightfully belong - your [pick("house", "apartment", "spaceship", "station")]</b>."
..()
/datum/outfit/lavalandprisoner
name = "Lavaland Prisoner"
uniform = /obj/item/clothing/under/rank/prisoner
mask = /obj/item/clothing/mask/breath
shoes = /obj/item/clothing/shoes/sneakers/orange
r_pocket = /obj/item/weapon/tank/internals/emergency_oxygen
/obj/effect/mob_spawn/human/prisoner_transport/Destroy()
new/obj/structure/fluff/empty_sleeper/syndicate(get_turf(src))
@@ -272,31 +283,39 @@
mob_name = "hotel staff member"
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "sleeper_s"
uniform = /obj/item/clothing/under/assistantformal
shoes = /obj/item/clothing/shoes/laceup
pocket1 = /obj/item/device/radio/off
back = /obj/item/weapon/storage/backpack
objectives = "Cater to visiting guests with your fellow staff. Do not leave your assigned hotel and always remember: The customer is always right!"
implants = list(/obj/item/weapon/implant/mindshield)
death = FALSE
roundstart = FALSE
random = TRUE
outfit = /datum/outfit/hotelstaff
flavour_text = "You are a staff member of a top-of-the-line space hotel! Cater to guests and <font size=6><b>DON'T</b></font> leave the hotel, lest the manager fire you for\
dereliction of duty!"
/datum/outfit/hotelstaff
name = "Hotel Staff"
uniform = /obj/item/clothing/under/assistantformal
shoes = /obj/item/clothing/shoes/laceup
r_pocket = /obj/item/device/radio/off
back = /obj/item/weapon/storage/backpack
implants = list(/obj/item/weapon/implant/mindshield)
/obj/effect/mob_spawn/human/hotel_staff/security
name = "hotel security sleeper"
mob_name = "hotel security memeber"
uniform = /obj/item/clothing/under/rank/security/blueshirt
shoes = /obj/item/clothing/shoes/jackboots
suit = /obj/item/clothing/suit/armor/vest/blueshirt
helmet = /obj/item/clothing/head/helmet/blueshirt
back = /obj/item/weapon/storage/backpack/security
belt = /obj/item/weapon/storage/belt/security/full
outfit = /datum/outfit/hotelstaff/security
flavour_text = "You are a peacekeeper assigned to this hotel to protect the intrests of the company while keeping the peace between \
guests and the staff.Do <font size=6><b>NOT</b></font> leave the hotel, as that is grounds for contract termination."
objectives = "Do not leave your assigned hotel. Try and keep the peace between staff and guests, non-lethal force heavily advised if possible."
/datum/outfit/hotelstaff/security
name = "Hotel Secuirty"
uniform = /obj/item/clothing/under/rank/security/blueshirt
shoes = /obj/item/clothing/shoes/jackboots
suit = /obj/item/clothing/suit/armor/vest/blueshirt
head = /obj/item/clothing/head/helmet/blueshirt
back = /obj/item/weapon/storage/backpack/security
belt = /obj/item/weapon/storage/belt/security/full
/obj/effect/mob_spawn/human/hotel_staff/Destroy()
new/obj/structure/fluff/empty_sleeper/syndicate(get_turf(src))
..()
@@ -307,22 +326,17 @@
mob_name = "Demonic friend"
icon = 'icons/obj/cardboard_cutout.dmi'
icon_state = "cutout_basic"
uniform = /obj/item/clothing/under/assistantformal
shoes = /obj/item/clothing/shoes/laceup
pocket1 = /obj/item/device/radio/off
back = /obj/item/weapon/storage/backpack
implants = list(/obj/item/weapon/implant/mindshield) //No revolutionaries, he's MY friend.
outfit = /datum/outfit/demonic_friend
death = FALSE
roundstart = FALSE
random = TRUE
has_id = TRUE
id_job = "SuperFriend"
id_access = "assistant"
var/obj/effect/proc_holder/spell/targeted/summon_friend/spell
var/datum/mind/owner
/obj/effect/mob_spawn/human/demonic_friend/Initialize(mapload, datum/mind/owner_mind, obj/effect/proc_holder/spell/targeted/summon_friend/summoning_spell)
..()
. = ..()
owner = owner_mind
flavour_text = "You have been given a reprieve from your eternity of torment, to be [owner.name]'s friend for their short mortal coil. Be aware that if you do not live up to [owner.name]'s expectations, they can send you back to hell with a single thought. [owner.name]'s death will also return you to hell."
var/area/A = get_area(src)
@@ -349,3 +363,11 @@
to_chat(L, "<span class='userdanger'>Your owner is already dead! You will soon perish.</span>")
addtimer(CALLBACK(L, /mob.proc/dust, 150)) //Give em a few seconds as a mercy.
/datum/outfit/demonic_friend
name = "Demonic Friend"
uniform = /obj/item/clothing/under/assistantformal
shoes = /obj/item/clothing/shoes/laceup
r_pocket = /obj/item/device/radio/off
back = /obj/item/weapon/storage/backpack
implants = list(/obj/item/weapon/implant/mindshield) //No revolutionaries, he's MY friend.
id = /obj/item/weapon/card/id
+10 -10
View File
@@ -146,49 +146,49 @@
/obj/structure/sign/biohazard
name = "\improper BIOHAZARD"
desc = "A warning sign which reads 'BIOHAZARD'"
desc = "A warning sign which reads 'BIOHAZARD'."
icon_state = "bio"
/obj/structure/sign/electricshock
name = "\improper HIGH VOLTAGE"
desc = "A warning sign which reads 'HIGH VOLTAGE'"
desc = "A warning sign which reads 'HIGH VOLTAGE'."
icon_state = "shock"
/obj/structure/sign/examroom
name = "\improper EXAM ROOM"
desc = "A guidance sign which reads 'EXAM ROOM'"
desc = "A guidance sign which reads 'EXAM ROOM'."
icon_state = "examroom"
/obj/structure/sign/vacuum
name = "\improper HARD VACUUM AHEAD"
desc = "A warning sign which reads 'HARD VACUUM AHEAD'"
desc = "A warning sign which reads 'HARD VACUUM AHEAD'."
icon_state = "space"
/obj/structure/sign/deathsposal
name = "\improper DISPOSAL: LEADS TO SPACE"
desc = "A warning sign which reads 'DISPOSAL: LEADS TO SPACE'"
desc = "A warning sign which reads 'DISPOSAL: LEADS TO SPACE'."
icon_state = "deathsposal"
/obj/structure/sign/pods
name = "\improper ESCAPE PODS"
desc = "A warning sign which reads 'ESCAPE PODS'"
desc = "A warning sign which reads 'ESCAPE PODS'."
icon_state = "pods"
/obj/structure/sign/fire
name = "\improper DANGER: FIRE"
desc = "A warning sign which reads 'DANGER: FIRE'"
desc = "A warning sign which reads 'DANGER: FIRE'."
icon_state = "fire"
/obj/structure/sign/nosmoking_1
name = "\improper NO SMOKING"
desc = "A warning sign which reads 'NO SMOKING'"
desc = "A warning sign which reads 'NO SMOKING'."
icon_state = "nosmoking"
/obj/structure/sign/nosmoking_2
name = "\improper NO SMOKING"
desc = "A warning sign which reads 'NO SMOKING'"
desc = "A warning sign which reads 'NO SMOKING'."
icon_state = "nosmoking2"
/obj/structure/sign/radiation
@@ -223,7 +223,7 @@
/obj/structure/sign/nanotrasen
name = "\improper NanoTrasen Logo "
desc = "A sign with the Nanotrasen Logo on it. Glory to Nanotrasen!"
desc = "A sign with the Nanotrasen Logo on it. Glory to Nanotrasen!"
icon_state = "nanotrasen"
/obj/structure/sign/science //These 3 have multiple types, just var-edit the icon_state to whatever one you want on the map
+8 -3
View File
@@ -5,6 +5,9 @@
density = 1
blocks_air = 1
/turf/closed/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
return FALSE
/turf/closed/indestructible
name = "wall"
icon = 'icons/turf/walls.dmi'
@@ -24,9 +27,6 @@
/turf/closed/indestructible/oldshuttle/corner
icon_state = "corner"
/turf/closed/indestructible/splashscreen
name = "Space Station 13"
icon = 'config/title_screens/images/blank.png'
@@ -111,6 +111,11 @@
explosion_block = 50
baseturf = /turf/closed/indestructible/necropolis
/turf/closed/indestructible/necropolis/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/floors.dmi'
underlay_appearance.icon_state = "necro1"
return TRUE
/turf/closed/indestructible/riveted/hierophant
name = "wall"
desc = "A wall made out of a strange metal. The squares on it pulse in a predictable pattern."
+3
View File
@@ -45,6 +45,9 @@
/turf/open/indestructible/hierophant/two
/turf/open/indestructible/hierophant/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
return FALSE
/turf/open/indestructible/paper
name = "notebook floor"
desc = "A floor made of invulnerable notebook paper."

Some files were not shown because too many files have changed in this diff Show More