Merge branch 'master' into AllMapChangesInOne

This commit is contained in:
LetterJay
2017-05-30 23:08:32 -05:00
committed by GitHub
364 changed files with 135665 additions and 22023 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)
+18
View File
@@ -0,0 +1,18 @@
//Investigate logging defines
#define INVESTIGATE_ATMOS "atmos"
#define INVESTIGATE_BOTANY "botany"
#define INVESTIGATE_CARGO "cargo"
#define INVESTIGATE_EXPERIMENTOR "experimentor"
#define INVESTIGATE_GRAVITY "gravity"
#define INVESTIGATE_RECORDS "records"
#define INVESTIGATE_SINGULO "singulo"
#define INVESTIGATE_SUPERMATTER "supermatter"
#define INVESTIGATE_TELESCI "telesci"
#define INVESTIGATE_WIRES "wires"
//Individual logging defines
#define INDIVIDUAL_ATTACK_LOG "Attack log"
#define INDIVIDUAL_SAY_LOG "Say log"
#define INDIVIDUAL_EMOTE_LOG "Emote log"
#define INDIVIDUAL_OOC_LOG "OOC log"
#define INDIVIDUAL_SHOW_ALL_LOG "All logs"
+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
+19
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
@@ -411,3 +424,9 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define NO_FIELD 0
#define FIELD_TURF 1
#define FIELD_EDGE 2
//gibtonite state defines
#define GIBTONITE_UNSTRUCK 0
#define GIBTONITE_ACTIVE 1
#define GIBTONITE_STABLE 2
#define GIBTONITE_DETONATE 3
+5 -7
View File
@@ -114,13 +114,6 @@
#define SNPC_MARTYR 3
#define SNPC_PSYCHO 4
//Individual logging defines
#define INDIVIDUAL_ATTACK_LOG "Attack log"
#define INDIVIDUAL_SAY_LOG "Say log"
#define INDIVIDUAL_EMOTE_LOG "Emote log"
#define INDIVIDUAL_OOC_LOG "OOC log"
#define INDIVIDUAL_SHOW_ALL_LOG "All logs"
#define TK_MAXRANGE 15
#define NO_SLIP_WHEN_WALKING 1
@@ -131,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
+2 -1
View File
@@ -39,6 +39,7 @@
// 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_SERVER_MAINT 16
@@ -71,4 +72,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)
+5 -6
View File
@@ -92,7 +92,7 @@
if(next_move > world.time) // in the year 2000...
return
if(A.IsObscured())
if(!modifiers["catcher"] && A.IsObscured())
return
if(istype(loc,/obj/mecha))
@@ -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)
@@ -325,8 +325,6 @@
/mob/living/carbon/human/CtrlClick(mob/user)
if(ishuman(user) && Adjacent(user))
if(world.time < user.next_move)
return FALSE
var/mob/living/carbon/human/H = user
H.dna.species.grab(H, src, H.mind.martial_art)
H.changeNext_move(CLICK_CD_MELEE)
@@ -448,6 +446,7 @@
C.swap_hand()
else
var/turf/T = params2turf(modifiers["screen-loc"], get_turf(usr))
params += "&catcher=1"
if(T)
T.Click(location, control, params)
. = 1
@@ -466,4 +465,4 @@
view = -1
else
view = 1
add_view_range(view)
add_view_range(view)
+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)
+1 -2
View File
@@ -271,8 +271,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
/obj/screen/alert/bloodsense/Initialize()
. = ..()
if(!narnar)
narnar = new('icons/mob/screen_alert.dmi', "mini_nar")
narnar = new('icons/mob/screen_alert.dmi', "mini_nar")
START_PROCESSING(SSprocessing, src)
/obj/screen/alert/bloodsense/Destroy()
+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)
+4 -5
View File
@@ -1,8 +1,8 @@
SUBSYSTEM_DEF(blackbox)
name = "Blackbox"
wait = 6000
flags = SS_NO_TICK_CHECK | SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
flags = SS_NO_TICK_CHECK | SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/msg_common = list()
var/list/msg_science = list()
@@ -86,12 +86,11 @@ SUBSYSTEM_DEF(blackbox)
if (!SSdbcore.Connect())
return
var/list/sqlrowlist = list()
for (var/datum/feedback_variable/FV in feedback)
sqlrowlist += list("time" = "Now()", "round_id" = GLOB.round_id, "var_name" = "'[sanitizeSQL(FV.get_variable())]'", "var_value" = FV.get_value(), "details" = "'[sanitizeSQL(FV.get_details())]'")
sqlrowlist += list(list("time" = "Now()", "round_id" = GLOB.round_id, "var_name" = "'[sanitizeSQL(FV.get_variable())]'", "var_value" = FV.get_value(), "details" = "'[sanitizeSQL(FV.get_details())]'"))
if (!length(sqlrowlist))
return
+2 -1
View File
@@ -23,7 +23,8 @@ SUBSYSTEM_DEF(dbcore)
var/failed_connections = 0
/datum/controller/subsystem/dbcore/PreInit()
_db_con = _dm_db_new_con()
if(!_db_con)
_db_con = _dm_db_new_con()
/datum/controller/subsystem/dbcore/Recover()
_db_con = SSdbcore._db_con
+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)
+8 -7
View File
@@ -15,14 +15,15 @@ SUBSYSTEM_DEF(lighting)
/datum/controller/subsystem/lighting/Initialize(timeofday)
if (config.starlight)
for(var/I in GLOB.sortedAreas)
var/area/A = I
if (A.dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT)
A.luminosity = 0
if(!initialized)
if (config.starlight)
for(var/I in GLOB.sortedAreas)
var/area/A = I
if (A.dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT)
A.luminosity = 0
create_all_lighting_objects()
initialized = TRUE
create_all_lighting_objects()
initialized = TRUE
fire(FALSE, TRUE)
+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
+12 -3
View File
@@ -744,6 +744,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()
@@ -844,17 +853,17 @@ 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]")
log_game("<span class='boldannounce'>Rebooting World. [reason]</span>")
+2 -3
View File
@@ -55,9 +55,8 @@
else if(isbrain(current) || isclockmob(current))
to_chat(current, "<span class='nezbere'>You can communicate with other servants by using the Hierophant Network action button in the upper left.</span>")
..()
if(istype(SSticker.mode, /datum/game_mode/clockwork_cult))
var/datum/game_mode/clockwork_cult/C = SSticker.mode
C.present_tasks(owner) //Memorize the objectives
to_chat(current, "<b>This is Ratvar's will:</b> [CLOCKCULT_OBJECTIVE]")
owner.memory += "<b>Ratvar's will:</b> [CLOCKCULT_OBJECTIVE]<br>" //Memorize the objectives
/datum/antagonist/clockcult/apply_innate_effects(mob/living/mob_override)
. = ..()
+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")
+4 -3
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)
user.client.images -= chunk.obscured
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
View File
@@ -181,6 +181,7 @@
marked_underlay.pixel_x = -owner.pixel_x
marked_underlay.pixel_y = -owner.pixel_y
owner.underlays += marked_underlay
return TRUE
return FALSE
/datum/status_effect/crusher_mark/Destroy()
+1 -1
View File
@@ -1557,4 +1557,4 @@ GLOBAL_LIST_INIT(the_station_areas, list (
/area/ai_monitored/turret_protected/ai_upload, //do not try to simplify to "/area/ai_monitored/turret_protected" --rastaf0
/area/ai_monitored/turret_protected/ai_upload_foyer,
/area/ai_monitored/turret_protected/ai,
))
))
+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)
@@ -171,14 +171,6 @@ Credit where due:
return TRUE
return FALSE
/datum/game_mode/clockwork_cult/proc/present_tasks(mob/living/L) //Memorizes and displays the clockwork cult's objective
if(!L || !istype(L) || !L.mind)
return 0
var/datum/mind/M = L.mind
to_chat(M.current, "<b>This is Ratvar's will:</b> [CLOCKCULT_OBJECTIVE]")
M.memory += "<b>Ratvar's will:</b> [CLOCKCULT_OBJECTIVE]<br>"
return 1
/datum/game_mode/clockwork_cult/proc/check_clockwork_victory()
if(GLOB.clockwork_gateway_activated)
SSticker.news_report = CLOCK_PROSELYTIZATION //failure, technically, but we have the station
+2 -2
View File
@@ -375,8 +375,8 @@
desc = "Used by veteran cultists to instantly transport items to their needful bretheren."
w_class = WEIGHT_CLASS_SMALL
brightness_on = 1
icon_state = "torch-on"
item_state = "torch-on"
icon_state = "torch"
item_state = "torch"
color = "#ff0000"
on_damage = 15
slot_flags = null
+2 -2
View File
@@ -233,11 +233,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++
+14
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))
+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
@@ -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)
C.client.images -= chunk.obscured
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
@@ -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
+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))
+3 -2
View File
@@ -3,6 +3,7 @@
icon = 'icons/obj/wizard.dmi'
icon_state = "soulstone"
item_state = "electronic"
layer = HIGH_OBJ_LAYER
desc = "A fragment of the legendary treasure known simply as the 'Soul Stone'. The shard still flickers with a fraction of the full artefact's power."
w_class = WEIGHT_CLASS_TINY
slot_flags = SLOT_BELT
@@ -213,12 +214,12 @@
var/obj/screen/alert/bloodsense/BS
if(newstruct.mind && ((stoner && iscultist(stoner)) || cultoverride) && SSticker && SSticker.mode)
SSticker.mode.add_cultist(newstruct.mind, 0)
BS = newstruct.alerts.Find("bloodsense")
if(iscultist(stoner) || cultoverride)
to_chat(newstruct, "<b>You are still bound to serve the cult[stoner ? " and [stoner]":""], follow their orders and help them complete their goals at all costs.</b>")
else if(stoner)
to_chat(newstruct, "<b>You are still bound to serve your creator, [stoner], follow their orders and help them complete their goals at all costs.</b>")
BS = newstruct.throw_alert("bloodsense", /obj/screen/alert/bloodsense)
newstruct.clear_alert("bloodsense")
BS = newstruct.throw_alert("bloodsense", /obj/screen/alert/bloodsense)
if(BS)
BS.Cviewer = newstruct
newstruct.cancel_camera()
+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)
C.client.images -= chunk.obscured
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)
+2 -2
View File
@@ -292,7 +292,7 @@
src.temp = text("Are you sure you wish to delete all records?<br>\n\t<A href='?src=\ref[];temp=1;del_all2=1'>Yes</A><br>\n\t<A href='?src=\ref[];temp=1'>No</A><br>", src, src)
else if(href_list["del_all2"])
investigate_log("[usr.name] ([usr.key]) has deleted all medical records.", "records")
investigate_log("[usr.name] ([usr.key]) has deleted all medical records.", INVESTIGATE_RECORDS)
GLOB.data_core.medical.Cut()
src.temp = "All records deleted."
@@ -458,7 +458,7 @@
src.temp = text("Are you sure you wish to delete the record (Medical Portion Only)?<br>\n\t<A href='?src=\ref[];temp=1;del_r2=1'>Yes</A><br>\n\t<A href='?src=\ref[];temp=1'>No</A><br>", src, src)
else if(href_list["del_r2"])
investigate_log("[usr.name] ([usr.key]) has deleted the medical records for [active1.fields["name"]].", "records")
investigate_log("[usr.name] ([usr.key]) has deleted the medical records for [active1.fields["name"]].", INVESTIGATE_RECORDS)
if(active2)
qdel(active2)
active2 = null
+4 -4
View File
@@ -452,7 +452,7 @@ What a mess.*/
temp += "<a href='?src=\ref[src];choice=Clear Screen'>No</a>"
if("Purge All Records")
investigate_log("[usr.name] ([usr.key]) has purged all the security records.", "records")
investigate_log("[usr.name] ([usr.key]) has purged all the security records.", INVESTIGATE_RECORDS)
for(var/datum/data/record/R in GLOB.data_core.security)
qdel(R)
GLOB.data_core.security.Cut()
@@ -696,18 +696,18 @@ What a mess.*/
active2.fields["criminal"] = "Parolled"
if("released")
active2.fields["criminal"] = "Discharged"
investigate_log("[active1.fields["name"]] has been set from [old_field] to [active2.fields["criminal"]] by [usr.name] ([usr.key]).", "records")
investigate_log("[active1.fields["name"]] has been set from [old_field] to [active2.fields["criminal"]] by [usr.name] ([usr.key]).", INVESTIGATE_RECORDS)
for(var/mob/living/carbon/human/H in GLOB.mob_list) //thanks for forcing me to do this, whoever wrote this shitty records system
H.sec_hud_set_security_status()
if("Delete Record (Security) Execute")
investigate_log("[usr.name] ([usr.key]) has deleted the security records for [active1.fields["name"]].", "records")
investigate_log("[usr.name] ([usr.key]) has deleted the security records for [active1.fields["name"]].", INVESTIGATE_RECORDS)
if(active2)
qdel(active2)
active2 = null
if("Delete Record (ALL) Execute")
if(active1)
investigate_log("[usr.name] ([usr.key]) has deleted all records for [active1.fields["name"]].", "records")
investigate_log("[usr.name] ([usr.key]) has deleted all records for [active1.fields["name"]].", INVESTIGATE_RECORDS)
for(var/datum/data/record/R in GLOB.data_core.medical)
if((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"]))
qdel(R)
+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
+1 -1
View File
@@ -143,7 +143,7 @@
else
log_msg += "nothing"
log_msg += " [sending ? "to" : "from"] [target_x], [target_y], [z] ([A ? A.name : "null area"])"
investigate_log(log_msg.Join(), "telesci")
investigate_log(log_msg.Join(), INVESTIGATE_TELESCI)
updateDialog()
//Starts in the briefcase. Don't spawn this directly, or it will runtime when closing.
@@ -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)
@@ -227,7 +229,6 @@
update_icon()
/obj/machinery/porta_turret/attackby(obj/item/I, mob/user, params)
if(stat & BROKEN)
if(istype(I, /obj/item/weapon/crowbar))
@@ -553,6 +554,7 @@
use_power = 0
has_cover = 0
scan_range = 9
req_access = list(GLOB.access_syndicate)
stun_projectile = /obj/item/projectile/bullet
lethal_projectile = /obj/item/projectile/bullet
lethal_projectile_sound = 'sound/weapons/Gunshot.ogg'
@@ -569,6 +571,8 @@
return 10 //Syndicate turrets shoot everything not in their faction
/obj/machinery/porta_turret/syndicate/pod
max_integrity = 40
integrity_failure = 20
obj_integrity = 40
stun_projectile = /obj/item/projectile/bullet/weakbullet3
lethal_projectile = /obj/item/projectile/bullet/weakbullet3
@@ -944,6 +948,7 @@
var/atom/target
var/turf/target_turf
var/warned = FALSE
var/mouseparams
//BUCKLE HOOKS
@@ -987,8 +992,8 @@
icon = 'icons/obj/weapons.dmi'
icon_state = "offhand"
w_class = WEIGHT_CLASS_HUGE
flags = ABSTRACT | NODROP
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF | NOBLUDGEON
flags = ABSTRACT | NODROP | NOBLUDGEON
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/obj/machinery/manned_turret/turret
/obj/item/gun_control/New(obj/machinery/manned_turret/MT)
@@ -1000,11 +1005,22 @@
/obj/item/gun_control/CanItemAutoclick()
return 1
/obj/item/gun_control/afterattack(atom/targeted_atom, mob/user)
/obj/item/gun_control/attack_obj(obj/O, mob/living/user)
user.changeNext_move(CLICK_CD_MELEE)
O.attacked_by(src, user)
/obj/item/gun_control/attack(mob/living/M, mob/living/user)
user.lastattacked = M
M.lastattacker = user
M.attacked_by(src, user)
add_fingerprint(user)
/obj/item/gun_control/afterattack(atom/targeted_atom, mob/user, flag, params)
..()
var/obj/machinery/manned_turret/E = user.buckled
E.setDir(get_dir(E,targeted_atom))
user.setDir(E.dir)
E.mouseparams = params
switch(E.dir)
if(NORTH)
E.layer = BELOW_MOB_LAYER
@@ -1052,15 +1068,15 @@
else
cooldown = world.time + cooldown_duration
warned = FALSE
INVOKE_ASYNC(src, /obj/machinery/manned_turret/.proc/volley)
volley(user)
/obj/machinery/manned_turret/proc/volley()
/obj/machinery/manned_turret/proc/volley(mob/user)
target_turf = get_turf(target)
for(var/i in 1 to number_of_shots)
addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper), i*rate_of_fire)
addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper, user), i*rate_of_fire)
/obj/machinery/manned_turret/proc/fire_helper()
/obj/machinery/manned_turret/proc/fire_helper(mob/user)
if(!src)
return
var/turf/targets_from = get_turf(src)
@@ -1069,11 +1085,10 @@
var/obj/item/projectile/P = new projectile_type(targets_from)
P.current = targets_from
P.starting = targets_from
P.firer = src
P.firer = user
P.original = target
playsound(src, 'sound/weapons/Gunshot_smg.ogg', 75, 1)
P.yo = target.y - targets_from.y + rand(-1,1)
P.xo = target.x - targets_from.x + rand(-1,1)
P.preparePixelProjectile(target, target_turf, user, mouseparams, rand(-9, 9))
P.fire()
/obj/machinery/manned_turret/ultimate // Admin-only proof of concept for autoclicker automatics
+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
View File
@@ -10,6 +10,7 @@
/obj/effect/forcefield/cult
desc = "An unholy shield that blocks all attacks."
name = "glowing wall"
icon = 'icons/effects/cult_effects.dmi'
icon_state = "cultshield"
///////////Mimewalls///////////
+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()
. = ..()
@@ -196,13 +196,6 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
user.visible_message("[user] starts cutting hair off \the [src].", "<span class='notice'>You start cutting the hair off \the [src]...</span>", "<span class='italics'>You hear the sound of a knife rubbing against flesh.</span>")
if(do_after(user,50, target = src))
to_chat(user, "<span class='notice'>You cut the hair from this [src.singular_name].</span>")
//Try locating an exisitng stack on the tile and add to there if possible
for(var/obj/item/stack/sheet/hairlesshide/HS in user.loc)
if(HS.amount < 50)
HS.amount++
use(1)
break
//If it gets to here it means it did not find a suitable stack on the tile.
var/obj/item/stack/sheet/hairlesshide/HS = new(user.loc)
HS.amount = 1
use(1)
@@ -230,3 +223,9 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
HS.amount = 1
wetness = initial(wetness)
src.use(1)
/obj/item/stack/sheet/wetleather/microwave_act(obj/machinery/microwave/MW)
..()
var/obj/item/stack/sheet/leather/L = new(loc)
L.amount = amount
qdel(src)
@@ -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)
@@ -69,7 +69,7 @@
var/safety = alert(user, "Doing this will have extremely dire consequences for the station and its crew. Be sure you know what you're doing.", "Put in [name]?", "Proceed", "Abort")
if(safety == "Abort" || !in_range(src, user) || !src || !W || user.incapacitated())
return
investigate_log("has become a singularity. Caused by [user.key]","singulo")
investigate_log("has become a singularity. Caused by [user.key]", INVESTIGATE_SINGULO)
to_chat(user, "<span class='danger'>The Bluespace interfaces of the two devices catastrophically malfunction!</span>")
qdel(W)
var/obj/singularity/singulo = new /obj/singularity (get_turf(src))
@@ -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()
+3 -1
View File
@@ -48,6 +48,8 @@
take_damage(tforce, BRUTE, "melee", 1, get_dir(src, AM))
/obj/ex_act(severity, target)
if(resistance_flags & INDESTRUCTIBLE)
return
..() //contents explosion
if(target == src)
qdel(src)
@@ -256,4 +258,4 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
if(can_break && integrity_failure && current_integrity <= integrity_failure)
obj_break(damage_type)
return TRUE
return FALSE
return FALSE
+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
+16 -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
@@ -246,6 +246,12 @@
desc = "A sign labelling an area as a place where xenobiological entities are researched."
icon_state = "xenobio"
/obj/structure/sign/xeno_warning_mining
name = "DANGEROUS ALIEN LIFE"
desc = "A sign that warns would-be travellers of hostile alien life in the vicinity."
icon = 'icons/obj/mining.dmi'
icon_state = "xeno_warning"
/obj/structure/sign/enginesafety
name = "\improper ENGINEERING SAFETY"
desc = "A sign detailing the various safety protocols when working on-site to ensure a safe shift."
+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."

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