Tg 2 11 sync (#215)

* first series of updates

* datums

* games folder

* admin and atmosia stuffs

* moar

* mob updates borg riding

* sprites and stuff

* fixes for various things

* oops. some missed fixes
This commit is contained in:
Poojawa
2017-02-12 03:56:14 -06:00
committed by GitHub
parent 30b3dff395
commit 6674f9fc15
153 changed files with 1651 additions and 1368 deletions

View File

@@ -349,21 +349,3 @@ CREATE TABLE `messages` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Mentor stufs
--
DROP TABLE IF EXISTS `mentor`;
CREATE TABLE `mentor` (
`ckey` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `mentor_memo`;
CREATE TABLE `mentor_memo` (
`ckey` varchar(32) NOT NULL,
`memotext` text NOT NULL,
`timestamp` datetime NOT NULL,
`last_editor` varchar(32) DEFAULT NULL,
`edits` text,
PRIMARY KEY (`ckey`)

View File

@@ -20993,6 +20993,7 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 5
},
/obj/structure/chair/stool,
/turf/open/floor/plasteel/redyellow,
/area/crew_quarters/bar/atrium)
"aMI" = (
@@ -24027,6 +24028,7 @@
/area/crew_quarters/bar/atrium)
"aRI" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/structure/chair/stool,
/turf/open/floor/plasteel/redyellow,
/area/crew_quarters/bar/atrium)
"aRJ" = (
@@ -78208,7 +78210,7 @@
/turf/closed/wall,
/area/maintenance/electrical)
"cHL" = (
/obj/machinery/atmospherics/pipe/manifold/supply/visible{
/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
tag = "icon-manifold (NORTH)";
icon_state = "manifold";
dir = 1
@@ -107878,15 +107880,6 @@
pixel_y = 3
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/doorButtons/access_button{
dir = 1;
idDoor = "virology_airlock_exterior";
idSelf = "virology_airlock_control";
name = "Virology Access Button";
pixel_x = 0;
pixel_y = -24;
req_access_txt = "39"
},
/turf/open/floor/plasteel/whitegreen/corner{
dir = 8
},
@@ -108190,6 +108183,15 @@
name = "Virology Exterior Airlock";
req_access_txt = "39"
},
/obj/machinery/doorButtons/access_button{
dir = 1;
idDoor = "virology_airlock_exterior";
idSelf = "virology_airlock_control";
name = "Virology Access Button";
pixel_x = -24;
pixel_y = -2;
req_access_txt = "39"
},
/turf/open/floor/plasteel{
tag = "icon-plasteel_warn_side (EAST)"
},
@@ -108660,6 +108662,12 @@
/turf/open/floor/plating,
/area/medical/virology)
"dKi" = (
/obj/item/weapon/twohanded/required/kirbyplants{
icon_state = "plant-21";
layer = 4.1;
pixel_x = -3;
pixel_y = 3
},
/turf/open/floor/plasteel/whitegreen/corner{
dir = 1
},
@@ -109068,6 +109076,14 @@
name = "Virology Interior Airlock";
req_access_txt = "39"
},
/obj/machinery/doorButtons/access_button{
idDoor = "virology_airlock_interior";
idSelf = "virology_airlock_control";
name = "Virology Access Button";
pixel_x = 0;
pixel_y = 22;
req_access_txt = "39"
},
/turf/open/floor/plasteel,
/area/medical/virology)
"dKZ" = (
@@ -118113,8 +118129,8 @@
},
/area/crew_quarters/electronic_marketing_den)
"ecc" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/closed/wall,
/obj/structure/closet/wardrobe/grey,
/turf/open/floor/plasteel/neutral,
/area/crew_quarters/electronic_marketing_den)
"ecd" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
@@ -118148,23 +118164,29 @@
/turf/open/floor/plasteel,
/area/hydroponics/Abandoned_Garden)
"ech" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/components/unary/vent_scrubber{
dir = 4;
on = 1;
scrub_Toxins = 0
/obj/machinery/button/door{
id = "Dorm2";
name = "Dormitory Door Lock";
normaldoorcontrol = 1;
pixel_x = -26;
pixel_y = 7;
req_access_txt = "0";
specialfunctions = 4
},
/turf/open/floor/plasteel/hydrofloor,
/area/hydroponics/Abandoned_Garden)
/turf/open/floor/wood,
/area/crew_quarters/sleep)
"eci" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
tag = "icon-manifold (EAST)";
icon_state = "manifold";
dir = 4
/obj/machinery/button/door{
id = "Dorm4";
name = "Dormitory Door Lock";
normaldoorcontrol = 1;
pixel_x = -26;
pixel_y = 7;
req_access_txt = "0";
specialfunctions = 4
},
/turf/open/floor/plasteel/hydrofloor,
/area/hydroponics/Abandoned_Garden)
/turf/open/floor/wood,
/area/crew_quarters/sleep)
"ecj" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel/hydrofloor,
@@ -118500,102 +118522,51 @@
/obj/machinery/deepfryer,
/turf/open/floor/plasteel/red,
/area/crew_quarters/kitchen)
"ecc" = (
/obj/structure/closet/wardrobe/green,
/turf/open/floor/plasteel/neutral/side,
/area/shuttle/arrival)
"ecd" = (
/obj/machinery/doorButtons/access_button{
"edc" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/closed/wall,
/area/crew_quarters/electronic_marketing_den)
"edd" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/components/unary/vent_scrubber{
dir = 4;
idDoor = "virology_airlock_interior";
idSelf = "virology_airlock_control";
name = "Virology Access Button";
pixel_x = -10;
pixel_y = 0;
req_access_txt = "39"
on = 1;
scrub_Toxins = 0
},
/turf/closed/wall/r_wall,
/area/medical/virology)
"ece" = (
/obj/structure/cable/white{
d2 = 2;
icon_state = "0-2";
tag = "icon-0-2"
},
/turf/closed/wall/r_wall,
/area/medical/virology)
"ecf" = (
/obj/structure/cable/white{
tag = "icon-4-8";
icon_state = "4-8"
},
/obj/structure/cable/white{
tag = "icon-2-4";
icon_state = "2-4"
},
/obj/structure/cable/white{
tag = "icon-1-4";
icon_state = "1-4"
},
/obj/effect/turf_decal/stripes/line{
dir = 2
/turf/open/floor/plasteel/hydrofloor,
/area/hydroponics/Abandoned_Garden)
"ede" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
tag = "icon-manifold (EAST)";
icon_state = "manifold";
dir = 4
},
/turf/open/floor/plasteel/hydrofloor,
/area/hydroponics/Abandoned_Garden)
"edf" = (
/obj/structure/table/wood,
/obj/item/clothing/head/hardhat/cakehat,
/turf/open/floor/plasteel/redyellow,
/area/crew_quarters/bar/atrium)
"edg" = (
/obj/machinery/doorButtons/airlock_controller{
idExterior = "virology_airlock_exterior";
idInterior = "virology_airlock_interior";
idSelf = "virology_airlock_control";
name = "Virology Access Console";
pixel_x = 0;
pixel_y = 22;
pixel_x = -10;
pixel_y = 24;
req_access_txt = "39"
},
/obj/structure/cable/white{
tag = "icon-4-8";
icon_state = "4-8"
},
/turf/open/floor/plasteel{
tag = "icon-plasteel_warn_side (WEST)"
},
/area/medical/virology)
"ecg" = (
/obj/structure/cable/white,
/turf/closed/wall/r_wall,
/area/medical/virology)
"ech" = (
/obj/machinery/button/door{
id = "Dorm2";
name = "Dormitory Door Lock";
normaldoorcontrol = 1;
pixel_x = -26;
pixel_y = 7;
req_access_txt = "0";
specialfunctions = 4
},
/turf/open/floor/wood,
/area/crew_quarters/sleep)
"eci" = (
/obj/machinery/button/door{
id = "Dorm4";
name = "Dormitory Door Lock";
normaldoorcontrol = 1;
pixel_x = -26;
pixel_y = 7;
req_access_txt = "0";
specialfunctions = 4
},
/turf/open/floor/wood,
/area/crew_quarters/sleep)
"ecj" = (
/obj/item/weapon/reagent_containers/food/condiment/saltshaker{
pixel_x = -8;
pixel_y = 5
},
/obj/item/weapon/reagent_containers/food/condiment/peppermill{
pixel_x = -8
},
/obj/structure/table/wood,
/obj/item/clothing/head/hardhat/cakehat{
pixel_x = 4;
pixel_y = 3
},
/turf/open/floor/plasteel/redyellow,
/area/crew_quarters/bar/atrium)
(1,1,1) = {"
aaa
@@ -149776,7 +149747,7 @@ aic
awb
awX
ayh
ech
edd
azo
azo
aCw
@@ -150024,7 +149995,7 @@ alb
amb
anl
aoj
ecc
edc
aUJ
ecd
asz
@@ -150033,7 +150004,7 @@ auT
awc
ecf
ecg
eci
ede
ecj
eck
aCx
@@ -155695,7 +155666,7 @@ aEf
aFB
aGX
aGY
aGY
aJA
aKZ
aMI
aGY
@@ -155950,7 +155921,7 @@ aBF
aCP
aEg
aFC
aGY
aGX
aGY
aJA
aLa
@@ -156213,9 +156184,9 @@ aJA
aLb
aMK
aGY
ecj
edf
aRH
aGY
aJA
aGY
aGZ
aYv
@@ -165305,7 +165276,7 @@ dGR
cKs
cKs
dJl
ecd
dJp
dKY
dJp
dJp
@@ -165562,9 +165533,9 @@ dGS
cDe
aaa
aaa
ece
ecf
ecg
dJp
edg
dJp
aaa
aaa
dJp
@@ -168866,8 +168837,8 @@ cEq
cGb
cHs
cvP
cCg
eci
cCg
cNS
cxw
cvP

View File

@@ -87,9 +87,9 @@ var/global/list/all_scripture = list() //a list containing scripture instances;
#define CLOCKCULT_ESCAPE "escape"
#define CLOCKCULT_SILICONS "silicons"
//misc clockcult stuff
#define MARAUDER_EMERGE_THRESHOLD 65 //marauders cannot emerge unless host is at this% or less health
#define SIGIL_ACCESS_RANGE 2 //range at which transmission sigils can access power
#define PROSELYTIZER_REPAIR_PER_TICK 4 //how much a proselytizer repairs each tick, and also how many deciseconds each tick is

View File

@@ -408,4 +408,4 @@ var/global/list/ghost_others_options = list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define TURF_DECAL_PAINT "paint"
#define TURF_DECAL_DAMAGE "damage"
#define TURF_DECAL_DIRT "dirt"
#define TURF_DECAL_DIRT "dirt"

View File

@@ -35,4 +35,4 @@
#define MONKEY_HUNT_FRUSTRATION_LIMIT 8 // Chase after an enemy before giving up
#define MONKEY_DISPOSE_FRUSTRATION_LIMIT 16 // Dispose of a body before giving up
#define MONKEY_AGGRESSIVE_MVM_PROB 1 // If you mass edit monkies to be aggressive. there is a small chance of in-fighting
#define MONKEY_AGGRESSIVE_MVM_PROB 0 // If you mass edit monkies to be aggressive. there is a small chance of in-fighting

View File

@@ -465,3 +465,4 @@
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= L.len ? L[I] : null) : L[I]) : null)
#define LAZYLEN(L) length(L)
#define LAZYCLEARLIST(L) if(L) L.Cut()

View File

@@ -38,6 +38,8 @@
var/turf_visible
if(pixel_turf)
turf_visible = cameranet.checkTurfVis(pixel_turf)
if(istype(loc, /obj/item/device/aicard) && (pixel_turf in view(client.view, loc)))
turf_visible = TRUE
if(!turf_visible)
log_admin("[key_name_admin(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([COORD(pixel_turf)])")
message_admins("[key_name_admin(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([ADMIN_COORDJMP(pixel_turf)]))")
@@ -184,4 +186,4 @@
//
/mob/living/silicon/ai/TurfAdjacent(var/turf/T)
return (cameranet && cameranet.checkTurfVis(T))
return (cameranet && cameranet.checkTurfVis(T))

View File

@@ -20,8 +20,8 @@
var/name = "Configuration" // datum name
var/server_name = null // server name (the name of the game window)
var/server_sql_name = null // short form server name used for the DB
var/station_name = null // station name (the name of the station in-game)
var/server_suffix = 0 // generate numeric suffix based on server port
var/lobby_countdown = 120 // In between round countdown.
var/round_end_countdown = 25 // Post round murder death kill countdown
var/hub = 0
@@ -78,8 +78,7 @@
var/forbid_singulo_possession = 0
var/useircbot = 0
var/announce_watchlist = 0
var/announce_adminhelps = 0
var/check_randomizer = 0
var/allow_panic_bunker_bounce = 0 //Send new players somewhere else
@@ -95,6 +94,11 @@
var/mentors_mobname_only = 0 // Only display mob name to mentors in mentorhelps
var/mentor_legacy_system = 0 // Whether to use the legacy mentor system (flat file) instead of SQL
// Discord crap.
var/discord_url = "hfdksjhfa.com"
var/discord_password
var/announce_watchlist = 0
var/announce_adminhelps = 0
var/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt
var/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt
@@ -242,10 +246,6 @@
var/list/gamemode_cache = null
// Discord crap.
var/discord_url = "hfdksjhfa.com"
var/discord_password
var/minutetopiclimit
var/secondtopiclimit
@@ -359,10 +359,10 @@
config.respawn = 0
if("servername")
config.server_name = value
if("serversqlname")
config.server_sql_name = 1
if("stationname")
config.station_name = value
if("serversuffix")
config.server_suffix = 1
if("hostedby")
config.hostedby = value
if("server")
@@ -499,16 +499,16 @@
config.client_error_version = text2num(value)
if("client_error_message")
config.client_error_message = value
if("minute_topic_limit")
config.minutetopiclimit = text2num(value)
if("second_topic_limit")
config.secondtopiclimit = text2num(value)
if("announce_adminhelps")
config.announce_adminhelps = 1
if("discord_url")
config.discord_url = value
if("discord_password")
config.discord_password = value
if("minute_topic_limit")
config.minutetopiclimit = text2num(value)
if("second_topic_limit")
config.secondtopiclimit = text2num(value)
else
diary << "Unknown setting in configuration: '[name]'"

View File

@@ -322,6 +322,7 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
SS_flags = SS.flags
if (SS_flags & SS_NO_FIRE)
subsystemstocheck -= SS
continue
if (!(SS_flags & SS_TICKER) && (SS_flags & SS_KEEP_TIMING) && SS.last_fire + (SS.wait * 0.75) > world.time)
continue
SS.enqueue()

View File

@@ -39,28 +39,34 @@ var/datum/subsystem/air/SSair
var/list/currentrun = list()
var/currentpart = SSAIR_PIPENETS
var/map_loading = TRUE
var/list/queued_for_activation
/datum/subsystem/air/New()
NEW_SS_GLOBAL(SSair)
/datum/subsystem/air/stat_entry(msg)
msg += "C:{"
msg += "AT:[round(cost_turfs)]|"
msg += "EG:[round(cost_groups)]|"
msg += "HP:[round(cost_highpressure)]|"
msg += "HS:[round(cost_hotspots)]|"
msg += "SC:[round(cost_superconductivity)]|"
msg += "PN:[round(cost_pipenets)]|"
msg += "AM:[round(cost_atmos_machinery)]"
msg += "AT:[round(cost_turfs,1)]|"
msg += "EG:[round(cost_groups,1)]|"
msg += "HP:[round(cost_highpressure,1)]|"
msg += "HS:[round(cost_hotspots,1)]|"
msg += "SC:[round(cost_superconductivity,1)]|"
msg += "PN:[round(cost_pipenets,1)]|"
msg += "AM:[round(cost_atmos_machinery,1)]"
msg += "} "
msg += "AT:[active_turfs.len]|"
msg += "EG:[excited_groups.len]|"
msg += "HS:[hotspots.len]|"
msg += "AS:[active_super_conductivity.len]"
msg += "AT:[active_turfs.len]|"
msg += "EG:[excited_groups.len]|"
msg += "HS:[hotspots.len]|"
msg += "PN:[networks.len]|"
msg += "HP:[high_pressure_delta.len]|"
msg += "AS:[active_super_conductivity.len]|"
msg += "AT/MS:[round((cost ? active_turfs.len/cost : 0),0.1)]"
..(msg)
/datum/subsystem/air/Initialize(timeofday)
map_loading = FALSE
setup_allturfs()
setup_atmos_machinery()
setup_pipenets()
@@ -244,7 +250,6 @@ var/datum/subsystem/air/SSair
if(T.excited_group)
T.excited_group.garbage_collect()
/datum/subsystem/air/proc/add_to_active(turf/open/T, blockchanges = 1)
if(istype(T) && T.air)
T.excited = 1
@@ -253,10 +258,25 @@ var/datum/subsystem/air/SSair
currentrun |= T
if(blockchanges && T.excited_group)
T.excited_group.garbage_collect()
else
else if(T.initialized)
for(var/turf/S in T.atmos_adjacent_turfs)
add_to_active(S)
else if(map_loading)
if(queued_for_activation)
queued_for_activation[T] = T
return
else
T.requires_activation = TRUE
/datum/subsystem/air/proc/begin_map_load()
LAZYINITLIST(queued_for_activation)
map_loading = TRUE
/datum/subsystem/air/proc/end_map_load()
map_loading = FALSE
for(var/T in queued_for_activation)
add_to_active(T)
queued_for_activation.Cut()
/datum/subsystem/air/proc/setup_allturfs()
var/list/turfs_to_init = block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz))

View File

@@ -27,26 +27,52 @@ var/datum/subsystem/objects/SSobj
/datum/subsystem/objects/proc/InitializeAtoms(list/objects = null)
if(initialized == INITIALIZATION_INSSOBJ)
return
var/list/late_loaders
initialized = INITIALIZATION_INNEW_MAPLOAD
if(objects)
for(var/I in objects)
var/atom/A = I
if(!A.initialized) //this check is to make sure we don't call it twice on an object that was created in a previous Initialize call
var/start_tick = world.time
A.Initialize(TRUE)
if(A.Initialize(TRUE))
LAZYADD(late_loaders, A)
if(start_tick != world.time)
WARNING("[A]: [A.type] slept during it's Initialize!")
CHECK_TICK
testing("Initialized [objects.len] atoms")
else
#ifdef TESTING
var/count = 0
#endif
for(var/atom/A in world)
if(!A.initialized) //this check is to make sure we don't call it twice on an object that was created in a previous Initialize call
var/start_tick = world.time
A.Initialize(TRUE)
if(A.Initialize(TRUE))
LAZYADD(late_loaders, A)
#ifdef TESTING
else
++count
#endif TESTING
if(start_tick != world.time)
WARNING("[A]: [A.type] slept during it's Initialize!")
CHECK_TICK
testing("Roundstart initialized [count] atoms")
initialized = INITIALIZATION_INNEW_REGULAR
if(late_loaders)
for(var/I in late_loaders)
var/atom/A = I
var/start_tick = world.time
A.Initialize(FALSE)
if(start_tick != world.time)
WARNING("[A]: [A.type] slept during it's Initialize!")
CHECK_TICK
testing("Late-initialized [late_loaders.len] atoms")
/datum/subsystem/objects/proc/map_loader_begin()
old_initialized = initialized
initialized = INITIALIZATION_INSSOBJ

View File

@@ -66,11 +66,11 @@ var/datum/subsystem/throwing/SSthrowing
/datum/thrownthing/proc/tick()
var/atom/movable/AM = thrownthing
if (!isturf(AM.loc) || !AM.throwing)
finialize()
finalize()
return
if (dist_travelled && hitcheck()) //to catch sneaky things moving on our tile while we slept
finialize()
finalize()
return
var/atom/step
@@ -79,7 +79,7 @@ var/datum/subsystem/throwing/SSthrowing
var/tilestomove = round(min(((((world.time+world.tick_lag) - start_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait))
while (tilestomove-- > 0)
if ((dist_travelled >= maxrange || AM.loc == target_turf) && AM.has_gravity(AM.loc))
finialize()
finalize()
return
if (dist_travelled <= max(dist_x, dist_y)) //if we haven't reached the target yet we home in on it, otherwise we use the initial direction
@@ -93,47 +93,52 @@ var/datum/subsystem/throwing/SSthrowing
diagonal_error += (diagonal_error < 0) ? dist_x/2 : -dist_y
if (!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
finialize()
finalize()
return
AM.Move(step, get_dir(AM, step))
if (!AM.throwing) // we hit something during our move
finialize(hit = TRUE)
finalize(hit = TRUE)
return
dist_travelled++
if (dist_travelled > MAX_THROWING_DIST)
finialize()
finalize()
return
/datum/thrownthing/proc/finialize(hit = FALSE)
/datum/thrownthing/proc/finalize(hit = FALSE)
set waitfor = 0
SSthrowing.processing -= thrownthing
//done throwing, either because it hit something or it finished moving
thrownthing.throwing = 0
thrownthing.throwing = null
if (!hit)
for (var/thing in get_turf(thrownthing)) //looking for our target on the turf we land on.
var/atom/A = thing
if (A == target)
hit = 1
thrownthing.throw_impact(A)
thrownthing.throw_impact(A, src)
break
if (!hit)
thrownthing.throw_impact(get_turf(thrownthing)) // we haven't hit something yet and we still must, let's hit the ground.
thrownthing.throw_impact(get_turf(thrownthing), src) // we haven't hit something yet and we still must, let's hit the ground.
thrownthing.newtonian_move(init_dir)
else
thrownthing.newtonian_move(init_dir)
if (callback)
callback.Invoke()
/datum/thrownthing/proc/hit_atom(atom/A)
thrownthing.throw_impact(A, src)
thrownthing.newtonian_move(init_dir)
finalize(TRUE)
/datum/thrownthing/proc/hitcheck()
for (var/thing in get_turf(thrownthing))
var/atom/movable/AM = thing
if (AM == thrownthing)
continue
if (AM.density && !(AM.pass_flags & LETPASSTHROW) && !(AM.flags & ON_BORDER))
thrownthing.throwing = 0
thrownthing.throw_impact(AM)
return 1
thrownthing.throwing = null
thrownthing.throw_impact(AM, src)
return TRUE

View File

@@ -9,7 +9,10 @@ var/global/datum/getrev/revdata = new()
/datum/getrev/New()
var/head_file = return_file_text(".git/logs/HEAD")
if(SERVERTOOLS && fexists("..\\prtestjob.lk"))
testmerge = file2list("..\\prtestjob.lk")
var/list/tmp = 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)
@@ -81,4 +84,4 @@ var/global/datum/getrev/revdata = new()
if(config.probabilities[ctag] > 0)
var/percentage = round(config.probabilities[ctag] / sum * 100, 0.1)
src << "[ctag] [percentage]%"
return
return

View File

@@ -31,6 +31,7 @@
for(var/L in block(locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]),
locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ])))
var/turf/B = L
atoms += B
for(var/A in B)
atoms += A
if(istype(A,/obj/structure/cable))
@@ -43,6 +44,7 @@
SSobj.InitializeAtoms(atoms)
SSmachine.setup_template_powernets(cables)
SSair.setup_template_machinery(atmos_machines)
SSair.end_map_load()
/datum/map_template/proc/load(turf/T, centered = FALSE)
if(centered)
@@ -54,8 +56,10 @@
if(T.y+height > world.maxy)
return
SSair.begin_map_load()
var/list/bounds = maploader.load_map(get_file(), T.x, T.y, T.z, cropMap=TRUE)
if(!bounds)
SSair.end_map_load()
return 0
//initialize things that are normally initialized after map load

View File

@@ -297,3 +297,75 @@
handle_vehicle_offsets()
else
user << "<span class='notice'>You'll need something to guide the [ridden.name].</span>"
//CYBORGS. NO, THEY ARE NOT ANIMALS.
/datum/riding/cyborg
keytype = null
vehicle_move_delay = 1
/datum/riding/cyborg/proc/ride_check(mob/user)
if(user.incapacitated())
var/kick = TRUE
if(istype(ridden, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = ridden
if(R.module && R.module.ride_allow_incapacitated)
kick = FALSE
if(kick)
user << "<span class='userdanger'>You fall off of [ridden]!</span>"
ridden.unbuckle_mob(user)
return
if(istype(user, /mob/living/carbon))
var/mob/living/carbon/carbonuser = user
if(!carbonuser.get_num_arms())
ridden.unbuckle_mob(user)
user << "<span class='userdanger'>You can't grab onto [ridden] with no hands!</span>"
return
/datum/riding/cyborg/handle_vehicle_layer()
if(ridden.dir == SOUTH)
ridden.layer = ABOVE_MOB_LAYER
else
ridden.layer = OBJ_LAYER
if(!ridden.buckled_mobs)
ridden.layer = MOB_LAYER
/datum/riding/cyborg/handle_vehicle_offsets()
if(ridden.has_buckled_mobs())
for(var/mob/living/M in ridden.buckled_mobs)
M.setDir(ridden.dir)
if(iscyborg(ridden))
var/mob/living/silicon/robot/R = ridden
if(istype(R.module))
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/proc/on_vehicle_move()
for(var/mob/living/M in ridden.buckled_mobs)
ride_check(M)
handle_vehicle_offsets()
handle_vehicle_layer()
/datum/riding/cyborg/proc/force_dismount()
for(var/mob/living/M in ridden.buckled_mobs)
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='boldwarning'>[M] is thrown clear of [ridden] by rapid spinning!</span>")
M.throw_at(target, 14, 5, ridden)
M.Weaken(3)

View File

@@ -73,6 +73,19 @@
admin_notes = "Due to the limited space for non paying crew, this shuttle may cause a riot."
credit_cost = 10000
/datum/map_template/shuttle/emergency/arena
suffix = "arena"
name = "The Arena"
description = "The crew must pass through an otherworldy arena to board this shuttle. Expect massive casualties. The source of the Bloody Signal must be tracked down and eliminated to unlock this shuttle."
admin_notes = "RIP AND TEAR."
credit_cost = 10000
/datum/map_template/shuttle/emergency/arena/prerequisites_met()
if("bubblegum" in SSshuttle.shuttle_purchase_requirements_met)
return TRUE
return FALSE
/datum/map_template/shuttle/emergency/birdboat
suffix = "birdboat"
name = "Birdboat Station Emergency Shuttle"
@@ -104,7 +117,6 @@
\n\
Contains contraband armory guns, maintenance loot, and abandoned crates!"
admin_notes = "Due to origin as a solo piloted secure vessel, has an active GPS onboard labeled STV5."
credit_cost = -7500
/datum/map_template/shuttle/emergency/meta
suffix = "meta"
@@ -160,8 +172,8 @@
/datum/map_template/shuttle/emergency/goon
suffix = "goon"
name = "NES Port"
description = "The Nanotrasen Emergency Shuttle Port(NES Port for short) is a shuttle used at other less known nanotrasen facilities and has a more open inside for larger crowds."
credit_cost = 3000
description = "The Nanotrasen Emergency Shuttle Port(NES Port for short) is a shuttle used at other less known Nanotrasen facilities and has a more open inside for larger crowds, but fewer onboard shuttle facilities."
credit_cost = 500
/datum/map_template/shuttle/emergency/wabbajack
suffix = "wabbajack"
@@ -219,4 +231,4 @@
name = "Delta Station Emergency Shuttle"
description = "A large shuttle for a large station, this shuttle can comfortably fit all your overpopulation and crowding needs. Complete with all facilities plus additional equipment."
admin_notes = "Go big or go home."
credit_cost = 7500
credit_cost = 7500

View File

@@ -41,11 +41,26 @@
if(luminosity)
light = new(src)
var/initialized = SSobj.initialized
if(initialized > INITIALIZATION_INSSOBJ)
Initialize(initialized == INITIALIZATION_INNEW_MAPLOAD)
var/do_initialize = SSobj.initialized
if(do_initialize > INITIALIZATION_INSSOBJ)
Initialize(do_initialize == INITIALIZATION_INNEW_MAPLOAD)
//. = ..() //uncomment if you are dumb enough to add a /datum/New() proc
//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 to prevent repeat calls
//Derivatives must not sleep
//Returning TRUE while mapload is TRUE will cause the object to be initialized again with mapload = FALSE when everything else is done
//(Useful for things that requires turfs to have air). This base may only be called once, however
//Note: the following functions don't call the base for optimization and must copypasta:
// /turf/Initialize
// /turf/open/space/Initialize
/atom/proc/Initialize(mapload)
if(initialized)
stack_trace("Warning: [src]([type]) initialized multiple times!")
initialized = TRUE
/atom/Destroy()
if(alternate_appearances)
for(var/aakey in alternate_appearances)
@@ -435,17 +450,6 @@ var/list/blood_splatter_icons = list()
sleep(1)
stoplag()
//Called after New if the world is not loaded with TRUE
//Called from base of New if the world is loaded with FALSE
//This base must be called or derivatives must set initialized to TRUE to prevent repeat calls
//Derivatives must not sleep
/atom/proc/Initialize(mapload)
#ifdef TESTING
if(initialized)
stack_trace("Warning: [src]([type]) initialized multiple times!")
#endif
initialized = TRUE
//the vision impairment to give to the mob whose perspective is set to that atom (e.g. an unfocused camera giving you an impaired vision when looking through it)
/atom/proc/get_remote_view_fullscreens(mob/user)
return

View File

@@ -2,7 +2,7 @@
layer = OBJ_LAYER
var/last_move = null
var/anchored = 0
var/throwing = 0
var/datum/thrownthing/throwing = null
var/throw_speed = 2 //How many tiles to move per ds when being thrown. Float values are fully supported
var/throw_range = 7
var/mob/pulledby = null
@@ -130,14 +130,12 @@
/atom/movable/Bump(atom/A, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump().
if((A && yes))
if(throwing)
throwing = 0
throw_impact(A)
throwing.hit_atom(A)
. = 1
if(!A || QDELETED(A))
return
A.Bumped(src)
/atom/movable/proc/forceMove(atom/destination)
if(destination)
if(pulledby)
@@ -222,7 +220,7 @@
/atom/movable/proc/checkpass(passflag)
return pass_flags&passflag
/atom/movable/proc/throw_impact(atom/hit_atom)
/atom/movable/proc/throw_impact(atom/hit_atom, throwingdatum)
return hit_atom.hitby(src)
/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked)
@@ -297,7 +295,7 @@
if(pulledby)
pulledby.stop_pulling()
throwing = 1
throwing = TT
if(spin)
SpinAnimation(5, 1)

View File

@@ -22,6 +22,7 @@
E.sight_flags -= SEE_MOBS
E.flash_protect = 2
user << "We adjust our eyes to protect them from bright lights."
user.update_sight()
else
user << "We can't adjust our eyes if we don't have any!"

View File

@@ -150,7 +150,7 @@
icon = 'icons/obj/weapons.dmi'
icon_state = "arm_blade"
item_state = "arm_blade"
flags = ABSTRACT | NODROP
flags = ABSTRACT | NODROP | DROPDEL
w_class = WEIGHT_CLASS_HUGE
force = 25
throwforce = 0 //Just to be on the safe side
@@ -203,7 +203,6 @@
..()
if(can_drop)
new /obj/item/weapon/melee/synthetic_arm_blade(get_turf(user))
qdel(src)
/***************************************\
|***********COMBAT TENTACLES*************|
@@ -303,11 +302,10 @@
for(var/obj/item/I in H.held_items)
if(I.is_sharp())
C.visible_message("<span class='danger'>[H] impales [C] with [H.p_their()] [I.name]!</span>", "<span class='userdanger'>[H] impales you with [H.p_their()] [I.name]!</span>")
C.apply_damage(I.force*2, BRUTE, "chest")
C.apply_damage(I.force, BRUTE, "chest")
H.do_item_attack_animation(C, used_item = I)
H.add_mob_blood(C)
playsound(get_turf(H),I.hitsound,75,1)
C.Weaken(4)
return
/obj/item/projectile/tentacle/on_hit(atom/target, blocked = 0)
@@ -355,7 +353,6 @@
if(INTENT_HARM)
C.visible_message("<span class='danger'>[L] is thrown towards [H] by a tentacle!</span>","<span class='userdanger'>A tentacle grabs you and throws you towards [H]!</span>")
C.Weaken(3)
C.throw_at(get_step_towards(H,C), 8, 2, callback=CALLBACK(src, .proc/tentacle_stab, H, C))
return 1
else

View File

@@ -84,8 +84,6 @@ Credit where due:
/datum/game_mode
var/list/servants_of_ratvar = list() //The Enlightened servants of Ratvar
var/required_escapees = 0 //How many servants need to escape, if applicable
var/required_silicon_converts = 0 //How many robotic lifeforms need to be converted, if applicable
var/clockwork_objective = CLOCKCULT_GATEWAY //The objective that the servants must fulfill
var/clockwork_explanation = "Construct a Gateway to the Celestial Derelict and free Ratvar." //The description of the current objective
@@ -141,20 +139,12 @@ Credit where due:
/datum/game_mode/clockwork_cult/proc/forge_clock_objectives() //Determine what objective that Ratvar's servants will fulfill
var/list/possible_objectives = list(CLOCKCULT_ESCAPE, CLOCKCULT_GATEWAY)
var/silicons_possible = FALSE
for(var/mob/living/silicon/ai/S in living_mob_list)
silicons_possible = TRUE
if(silicons_possible)
possible_objectives += CLOCKCULT_SILICONS
clockwork_objective = pick(possible_objectives)
switch(clockwork_objective)
if(CLOCKCULT_ESCAPE)
required_escapees = round(max(1, roundstart_player_count / 3)) //33% of the player count must be cultists
clockwork_explanation = "Ensure that [required_escapees] servants of Ratvar escape from [station_name()]."
clockwork_explanation = "Construct a Gateway to the Celestial Derelict and proselytize the entire station."
if(CLOCKCULT_GATEWAY)
clockwork_explanation = "Construct a Gateway to the Celestial Derelict and free Ratvar."
if(CLOCKCULT_SILICONS)
clockwork_explanation = "Ensure that all active silicon-based lifeforms on [station_name()] are servants of Ratvar and Application scripture is unlocked."
return 1
/datum/game_mode/clockwork_cult/proc/greet_servant(mob/M) //Description of their role
@@ -199,27 +189,8 @@ Credit where due:
/datum/game_mode/clockwork_cult/proc/check_clockwork_victory()
switch(clockwork_objective)
if(CLOCKCULT_ESCAPE)
var/surviving_servants = 0
for(var/datum/mind/M in servants_of_ratvar)
if(M.current && M.current.stat != DEAD && (M.current.onCentcom() || M.current.onSyndieBase()))
surviving_servants++
clockwork_explanation = "Ensure that [required_escapees] servant(s) of Ratvar escape from [station_name()].<br><i><b>[surviving_servants]</b> managed to escape!</i>"
if(surviving_servants >= required_escapees)
ticker.news_report = CULT_ESCAPE
return TRUE
if(CLOCKCULT_SILICONS)
var/total_silicons = 0
var/valid_silicons = 0
for(var/mob/living/silicon/S in mob_list) //Only check robots and AIs
if(isAI(S) || iscyborg(S))
total_silicons++
if(is_servant_of_ratvar(S) || S.stat == DEAD)
valid_silicons++
clockwork_explanation = "Ensure that all active silicon-based lifeforms on [station_name()] are servants of Ratvar and Application scripture is unlocked.<br>\
<i><b>[valid_silicons]/[total_silicons]</b> silicons were killed or converted!"
var/list/scripture_states = scripture_unlock_check()
if(valid_silicons >= total_silicons && scripture_states[SCRIPTURE_APPLICATION])
ticker.news_report = CLOCK_SILICONS
if(clockwork_gateway_activated)
ticker.news_report = CLOCK_PROSELYTIZATION
return TRUE
if(CLOCKCULT_GATEWAY)
if(ratvar_awakens)
@@ -241,18 +212,16 @@ Credit where due:
feedback_set_details("round_end_result", "win - servants completed their objective ([clockwork_objective])")
else
var/half_victory = FALSE
if(clockwork_objective == CLOCKCULT_GATEWAY)
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = locate() in all_clockwork_objects
if(G)
half_victory = TRUE
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = locate() in all_clockwork_objects
if(G)
half_victory = TRUE
if(half_victory)
text += "<span class='large_brass'><b>The crew escaped before Ratvar could rise, but the gateway was successfully constructed!</b></span>"
text += "<span class='large_brass'><b>The crew escaped before [clockwork_objective == CLOCKCULT_GATEWAY ? "Ratvar could rise":"the station could be proselytized"], but the gateway \
was successfully constructed!</b></span>"
feedback_set_details("round_end_result", "halfwin - round ended before the gateway finished")
else
text += "<span class='userdanger'>Ratvar's servants have failed!</span>"
feedback_set_details("round_end_result", "loss - servants failed their objective ([clockwork_objective])")
if(clockwork_gateway_activated && clockwork_objective != CLOCKCULT_GATEWAY)
ticker.news_report = CLOCK_PROSELYTIZATION
text += "<br><b>The servants' objective was:</b> <br>[clockwork_explanation]"
text += "<br>Ratvar's servants had <b>[clockwork_caches]</b> Tinkerer's Caches."
text += "<br><b>Construction Value(CV)</b> was: <b>[clockwork_construction_value]</b>"

View File

@@ -159,11 +159,10 @@
/obj/effect/clockwork/sigil/submission/accession/post_channel(mob/living/L)
if(L.isloyal())
var/mob/living/carbon/C = L
delete_on_finish = TRUE
C.visible_message("<span class='warning'>[C] visibly trembles!</span>", \
L.visible_message("<span class='warning'>[L] visibly trembles!</span>", \
"<span class='sevtug'>[text2ratvar("You will be mine and his. This puny trinket will not stop me.")]</span>")
for(var/obj/item/weapon/implant/mindshield/M in C.implants)
for(var/obj/item/weapon/implant/mindshield/M in L.implants)
qdel(M)

View File

@@ -159,7 +159,7 @@
/obj/item/stack/tile/brass/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
if(source)
return FALSE
return list("operation_time" = amount, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "power_cost" = -(amount*POWER_FLOOR), "spawn_dir" = SOUTH)
return list("operation_time" = 0, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "power_cost" = -(amount*POWER_FLOOR), "spawn_dir" = SOUTH)
//Airlock conversion
/obj/machinery/door/airlock/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
@@ -263,42 +263,18 @@
//Hitting a clockwork structure will try to repair it.
/obj/structure/destructible/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
. = TRUE
if(!can_be_repaired)
user << "<span class='warning'>[src] cannot be repaired!</span>"
return
if(obj_integrity >= max_integrity)
user << "<span class='warning'>[src] is at maximum integrity!</span>"
return
var/amount_to_heal = max_integrity - obj_integrity
var/healing_for_cycle = min(amount_to_heal, repair_amount)
var/power_required = round(healing_for_cycle*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)
if(!healing_for_cycle || (!proselytizer.can_use_power(RATVAR_POWER_CHECK) && !proselytizer.can_use_power(power_required)))
user << "<span class='warning'>You need at least <b>[power_required]W</b> power to start repairing [src], and at least \
<b>[round(amount_to_heal*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)]W</b> to fully repair it!</span>"
var/list/repair_values = list()
if(!proselytizer.proselytizer_repair_checks(repair_values, src, user))
return
user.visible_message("<span class='notice'>[user]'s [proselytizer.name] starts covering [src] in glowing orange energy...</span>", \
"<span class='alloy'>You start repairing [src]...</span>")
//hugeass while because we need to re-check after the do_after
proselytizer.repairing = src
while(proselytizer && user && src && obj_integrity < max_integrity)
amount_to_heal = max_integrity - obj_integrity
if(amount_to_heal <= 0)
while(proselytizer && user && src)
if(!do_after(user, repair_values["healing_for_cycle"] * proselytizer.speed_multiplier, target = src, \
extra_checks = CALLBACK(proselytizer, /obj/item/clockwork/clockwork_proselytizer.proc/proselytizer_repair_checks, repair_values, src, user, TRUE)))
break
healing_for_cycle = min(amount_to_heal, repair_amount)
power_required = round(healing_for_cycle*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)
if(!healing_for_cycle || (!proselytizer.can_use_power(RATVAR_POWER_CHECK) && !proselytizer.can_use_power(power_required)) || \
!do_after(user, healing_for_cycle * proselytizer.speed_multiplier, target = src) || \
!proselytizer || (!proselytizer.can_use_power(RATVAR_POWER_CHECK) && !proselytizer.can_use_power(power_required)))
break
amount_to_heal = max_integrity - obj_integrity
if(amount_to_heal <= 0)
break
healing_for_cycle = min(amount_to_heal, repair_amount)
power_required = round(healing_for_cycle*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)
if(!healing_for_cycle || (!proselytizer.can_use_power(RATVAR_POWER_CHECK) && !proselytizer.can_use_power(power_required)))
break
obj_integrity = Clamp(obj_integrity + healing_for_cycle, 0, max_integrity)
proselytizer.modify_stored_power(-power_required)
obj_integrity = Clamp(obj_integrity + repair_values["healing_for_cycle"], 0, max_integrity)
proselytizer.modify_stored_power(-repair_values["power_required"])
playsound(src, 'sound/machines/click.ogg', 50, 1)
if(proselytizer)
@@ -309,42 +285,18 @@
//Proselytizer mob heal proc, to avoid as much copypaste as possible.
/mob/living/proc/proselytizer_heal(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
if(!is_servant_of_ratvar(src))
user << "<span class='warning'>[src] does not serve Ratvar!</span>"
return FALSE
if(health >= maxHealth || (flags & GODMODE))
user << "<span class='warning'>[src == user ? "You" : "[src]"] [src == user ? "are" : "is"] at maximum health!</span>"
return FALSE
var/amount_to_heal = maxHealth - health
var/healing_for_cycle = min(amount_to_heal, 4)
var/power_required = round(healing_for_cycle*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)
if(!healing_for_cycle || (!proselytizer.can_use_power(RATVAR_POWER_CHECK) && !proselytizer.can_use_power(power_required)))
user << "<span class='warning'>You need at least <b>[power_required]W</b> power to start repairing[src == user ? " yourself" : " [src]"], and at least \
<b>[round(amount_to_heal*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)]W</b> to fully repair [src == user ? "yourself" : "[p_them()]"]!</span>"
return FALSE
var/list/repair_values = list()
if(!proselytizer.proselytizer_repair_checks(repair_values, src, user))
return
user.visible_message("<span class='notice'>[user]'s [proselytizer.name] starts coverin[src == user ? "g [user.p_them()]" : "g [src]"] in glowing orange energy...</span>", \
"<span class='alloy'>You start repairin[src == user ? "g yourself" : "g [src]"]...</span>")
//hugeass while because we need to re-check after the do_after
proselytizer.repairing = src
while(proselytizer && user && src && health < maxHealth)
amount_to_heal = maxHealth - health
if(amount_to_heal <= 0)
while(proselytizer && user && src)
if(!do_after(user, repair_values["healing_for_cycle"] * proselytizer.speed_multiplier, target = src, \
extra_checks = CALLBACK(proselytizer, /obj/item/clockwork/clockwork_proselytizer.proc/proselytizer_repair_checks, repair_values, src, user, TRUE)))
break
healing_for_cycle = min(amount_to_heal, 4)
power_required = round(healing_for_cycle*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)
if(!healing_for_cycle || (!proselytizer.can_use_power(RATVAR_POWER_CHECK) && !proselytizer.can_use_power(power_required)) || \
!do_after(user, healing_for_cycle * proselytizer.speed_multiplier, target = src) || \
!proselytizer || (!proselytizer.can_use_power(RATVAR_POWER_CHECK) && !proselytizer.can_use_power(power_required)))
break
amount_to_heal = maxHealth - health
if(amount_to_heal <= 0)
break
healing_for_cycle = min(amount_to_heal, 4)
power_required = round(healing_for_cycle*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)
if(!healing_for_cycle || (!proselytizer.can_use_power(RATVAR_POWER_CHECK) && !proselytizer.can_use_power(power_required)))
break
proselytizer_heal_tick(healing_for_cycle)
proselytizer.modify_stored_power(-power_required)
proselytizer_heal_tick(repair_values["healing_for_cycle"])
proselytizer.modify_stored_power(-repair_values["power_required"])
playsound(src, 'sound/machines/click.ogg', 50, 1)
if(proselytizer)
@@ -382,14 +334,17 @@
if(health < maxHealth && !(flags & GODMODE))
user.visible_message("<span class='notice'>[user]'s [proselytizer.name] starts coverin[src == user ? "g [user.p_them()]" : "g [src]"] in glowing orange energy...</span>", \
"<span class='alloy'>You start repairin[src == user ? "g yourself" : "g [src]"]...</span>")
proselytizer.repairing = src
if(do_after(user,80*proselytizer.speed_multiplier, target=src))
adjustHealth(-maxHealth)
user.visible_message("<span class='notice'>[user]'s [proselytizer.name] stops coverin[src == user ? "g [user.p_them()]" : "g [src]"] with glowing orange energy.</span>", \
"<span class='alloy'>You finish repairin[src == user ? "g yourself" : "g [src]"].</span>")
if(proselytizer)
proselytizer.repairing = null
else
user << "<span class='warning'>[src == user ? "You" : "[src]"] [src == user ? "are" : "is"] at maximum health!</span>"
//Convert shards and replicant alloy directly to power
//Convert shards and gear bits directly to power
/obj/item/clockwork/alloy_shards/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return list("operation_time" = 0, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "power_cost" = -POWER_STANDARD, "spawn_dir" = SOUTH)
@@ -404,6 +359,3 @@
/obj/item/clockwork/alloy_shards/small/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return list("operation_time" = 0, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "power_cost" = -(CLOCKCULT_POWER_UNIT*0.02), "spawn_dir" = SOUTH)
/obj/item/clockwork/component/replicant_alloy/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return list("operation_time" = 0, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "power_cost" = -CLOCKCULT_POWER_UNIT, "spawn_dir" = SOUTH)

View File

@@ -196,22 +196,17 @@
if(proselytize_values["power_cost"] > 0)
proselytize_values["power_cost"] *= 2
if(!can_use_power(proselytize_values["power_cost"]))
if(stored_power - proselytize_values["power_cost"] < 0)
user << "<span class='warning'>You need <b>[proselytize_values["power_cost"]]W</b> power to proselytize [target]!</span>"
else if(stored_power - proselytize_values["power_cost"] > max_power)
user << "<span class='warning'>Your [name] contains too much power to proselytize [target]!</span>"
var/target_type = target.type
if(!proselytize_checks(proselytize_values, target, target_type, user))
return FALSE
proselytize_values["operation_time"] *= speed_multiplier
playsound(target, 'sound/machines/click.ogg', 50, 1)
if(proselytize_values["operation_time"])
var/target_type = target.type
user.visible_message("<span class='warning'>[user]'s [name] begins tearing apart [target]!</span>", "<span class='brass'>You begin proselytizing [target]...</span>")
if(!do_after(user, proselytize_values["operation_time"], target = target))
return FALSE
if(repairing || !can_use_power(proselytize_values["power_cost"]) || !target || target.type != target_type) //Check again to prevent bypassing via spamclick
if(!do_after(user, proselytize_values["operation_time"], target = target, extra_checks = CALLBACK(src, .proc/proselytize_checks, proselytize_values, target, target_type, user, TRUE)))
return FALSE
user.visible_message("<span class='warning'>[user]'s [name] covers [target] in golden energy!</span>", "<span class='brass'>You proselytize [target].</span>")
else
@@ -234,3 +229,64 @@
if(no_table_check)
return TRUE
return FALSE
/obj/item/clockwork/clockwork_proselytizer/proc/proselytize_checks(list/proselytize_values, atom/target, expected_type, mob/user, silent) //checked constantly while proselytizing
if(!islist(proselytize_values) || !target || QDELETED(target) || !user)
return FALSE
if(repairing)
return FALSE
if(target.type != expected_type)
return FALSE
if(can_use_power(RATVAR_POWER_CHECK))
proselytize_values["power_cost"] = 0
if(!can_use_power(proselytize_values["power_cost"]))
if(stored_power - proselytize_values["power_cost"] < 0)
if(!silent)
user << "<span class='warning'>You need <b>[proselytize_values["power_cost"]]W</b> power to proselytize [target]!</span>"
else if(stored_power - proselytize_values["power_cost"] > max_power)
if(!silent)
user << "<span class='warning'>Your [name] contains too much power to proselytize [target]!</span>"
return FALSE
return TRUE
//The repair check proc.
//Is dark magic. Can probably kill you.
/obj/item/clockwork/clockwork_proselytizer/proc/proselytizer_repair_checks(list/repair_values, atom/target, mob/user, silent) //Exists entirely to avoid an otherwise unreadable series of checks.
if(!islist(repair_values) || !target || QDELETED(target) || !user)
return FALSE
if(isliving(target))
var/mob/living/L = target
if(!is_servant_of_ratvar(L))
if(!silent)
user << "<span class='warning'>[L] does not serve Ratvar!</span>"
return FALSE
if(L.health >= L.maxHealth || (L.flags & GODMODE))
if(!silent)
user << "<span class='warning'>[L == user ? "You are" : "[L] is"] at maximum health!</span>"
return FALSE
repair_values["amount_to_heal"] = L.maxHealth - L.health
else if(isobj(target))
if(istype(target, /obj/structure/destructible/clockwork))
var/obj/structure/destructible/clockwork/C = target
if(!C.can_be_repaired)
if(!silent)
user << "<span class='warning'>[C] cannot be repaired!</span>"
return FALSE
var/obj/O = target
if(O.obj_integrity >= O.max_integrity)
if(!silent)
user << "<span class='warning'>[O] is at maximum integrity!</span>"
return FALSE
repair_values["amount_to_heal"] = O.max_integrity - O.obj_integrity
else
return FALSE
if(repair_values["amount_to_heal"] <= 0)
return FALSE
repair_values["healing_for_cycle"] = min(repair_values["amount_to_heal"], PROSELYTIZER_REPAIR_PER_TICK)
repair_values["power_required"] = round(repair_values["healing_for_cycle"]*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)
if(!can_use_power(RATVAR_POWER_CHECK) && !can_use_power(repair_values["power_required"]))
if(!silent)
user << "<span class='warning'>You need at least <b>[repair_values["power_required"]]W</b> power to start repairin[target == user ? "g yourself" : "g [target]"], and at least \
<b>[round(repair_values["amount_to_heal"]*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)]W</b> to fully repair [target == user ? "yourself" : "[target.p_them()]"]!</span>"
return FALSE
return TRUE

View File

@@ -179,7 +179,7 @@ Judgement: 12 servants, 5 caches, 300 CV, and any existing AIs are converted or
if(!channel_time)
return TRUE
for(var/invocation in invocations)
if(!check_special_requirements() || !do_after(invoker, channel_time / invocations.len, target = invoker) || !check_special_requirements())
if(!do_after(invoker, channel_time / invocations.len, target = invoker, extra_checks = CALLBACK(src, .proc/check_special_requirements)))
slab.busy = null
return FALSE
if(multiple_invokers_used)
@@ -206,9 +206,7 @@ Judgement: 12 servants, 5 caches, 300 CV, and any existing AIs are converted or
/datum/clockwork_scripture/channeled/scripture_effects()
for(var/i in 1 to chant_amount)
if(!can_recite())
break
if(!do_after(invoker, chant_interval, target = invoker))
if(!do_after(invoker, chant_interval, target = invoker, extra_checks = CALLBACK(src, .proc/can_recite)))
break
clockwork_say(invoker, text2ratvar(pick(chant_invocations)), whispered)
if(!chant_effects(i))

View File

@@ -3,7 +3,7 @@
///////////////
//Ark of the Clockwork Justiciar: Creates a Gateway to the Celestial Derelict, either summoning ratvar or proselytizing everything.
/datum/clockwork_scripture/ark_of_the_clockwork_justiciar
/datum/clockwork_scripture/create_object/ark_of_the_clockwork_justiciar
descname = "Structure, Win Condition"
name = "Ark of the Clockwork Justiciar"
desc = "Tears apart a rift in spacetime to Reebe, the Celestial Derelict.\n\
@@ -15,19 +15,21 @@
consumed_components = list(BELLIGERENT_EYE = 10, VANGUARD_COGWHEEL = 10, GEIS_CAPACITOR = 10, REPLICANT_ALLOY = 10, HIEROPHANT_ANSIBLE = 10)
invokers_required = 5
multiple_invokers_used = TRUE
object_path = /obj/structure/destructible/clockwork/massive/celestial_gateway
creator_message = null
usage_tip = "The gateway is completely vulnerable to attack during its five-minute duration. It will periodically give indication of its general position to everyone on the station \
as well as being loud enough to be heard throughout the entire sector. Defend it with your life!"
tier = SCRIPTURE_JUDGEMENT
sort_priority = 1
/datum/clockwork_scripture/ark_of_the_clockwork_justiciar/New()
/datum/clockwork_scripture/create_object/ark_of_the_clockwork_justiciar/New()
if(ticker && ticker.mode && ticker.mode.clockwork_objective != CLOCKCULT_GATEWAY)
invocations = list("ARMORER! FRIGHT! AMPERAGE! VANGUARD! I CALL UPON YOU!!", \
"THIS STATION WILL BE A BEACON OF HOPE IN THE DARKNESS OF SPACE!!", \
"HELP US MAKE THIS SHOW ENGINE'S GLORY!!")
..()
/datum/clockwork_scripture/ark_of_the_clockwork_justiciar/check_special_requirements()
/datum/clockwork_scripture/create_object/ark_of_the_clockwork_justiciar/check_special_requirements()
if(!slab.no_cost)
if(ratvar_awakens)
invoker << "<span class='big_brass'>\"I am already here, idiot.\"</span>"
@@ -47,11 +49,4 @@
else
invoker << "<span class='warning'>Ratvar's recent banishment renders him too weak to be wrung forth from Reebe!</span>"
return FALSE
return TRUE
/datum/clockwork_scripture/ark_of_the_clockwork_justiciar/scripture_effects()
var/turf/T = get_turf(invoker)
if(T)
new/obj/structure/destructible/clockwork/massive/celestial_gateway(T)
return TRUE
return FALSE
return ..()

View File

@@ -9,8 +9,7 @@
anchored = 1
density = 1
resistance_flags = FIRE_PROOF | ACID_PROOF
var/repair_amount = 4 //how much a proselytizer can repair each cycle
var/can_be_repaired = TRUE //if a proselytizer can repair it at all
var/can_be_repaired = TRUE //if a proselytizer can repair it
break_message = "<span class='warning'>The frog isn't a meme after all!</span>" //The message shown when a structure breaks
break_sound = 'sound/magic/clockwork/anima_fragment_death.ogg' //The sound played when a structure breaks
debris = list(/obj/item/clockwork/alloy_shards/large = 1, \
@@ -72,9 +71,10 @@
. *= min(max_integrity/max(obj_integrity, 1), 4)
. = round(., 0.01)
/obj/structure/destructible/clockwork/can_be_unfasten_wrench(mob/user)
/obj/structure/destructible/clockwork/can_be_unfasten_wrench(mob/user, silent)
if(anchored && obj_integrity <= round(max_integrity * 0.25, 1))
user << "<span class='warning'>[src] is too damaged to unsecure!</span>"
if(!silent)
user << "<span class='warning'>[src] is too damaged to unsecure!</span>"
return FAILED_UNFASTEN
return ..()
@@ -158,9 +158,10 @@
var/powered = total_accessable_power()
return powered == PROCESS_KILL ? 25 : powered //make sure we don't accidentally return the arbitrary PROCESS_KILL define
/obj/structure/destructible/clockwork/powered/can_be_unfasten_wrench(mob/user)
/obj/structure/destructible/clockwork/powered/can_be_unfasten_wrench(mob/user, silent)
if(active)
user << "<span class='warning'>[src] needs to be disabled before it can be unsecured!</span>"
if(!silent)
user << "<span class='warning'>[src] needs to be disabled before it can be unsecured!</span>"
return FAILED_UNFASTEN
return ..()

View File

@@ -74,8 +74,6 @@
hierophant_message("<span class='large_brass'><b>A gateway to the Celestial Derelict has been created in [gate_area.map_name]!</b></span>", FALSE, src)
if(!objective_is_gateway)
ratvar_portal = FALSE
hierophant_message("<span class='big_brass'>This newly constructed gateway will not free Ratvar, \
and will instead simply proselytize and convert everything and everyone on the station.</span>", TRUE)
SSshuttle.registerHostileEnvironment(src)
START_PROCESSING(SSprocessing, src)
@@ -210,13 +208,14 @@
animate(glow, transform = matrix() * 3, alpha = 0, time = 5)
var/turf/startpoint = get_turf(src)
QDEL_IN(src, 3)
clockwork_gateway_activated = TRUE
if(ratvar_portal)
sleep(3)
clockwork_gateway_activated = TRUE
new/obj/structure/destructible/clockwork/massive/ratvar(startpoint)
else
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 0) //call the shuttle immediately
sleep(3)
clockwork_gateway_activated = TRUE
send_to_playing_players("<span class='ratvar'>\"[text2ratvar("Behold")]!\"</span>\n<span class='inathneq_large'>\"[text2ratvar("See Engine's mercy")]!\"</span>\n\
<span class='sevtug_large'>\"[text2ratvar("Observe Engine's design skills")]!\"</span>\n<span class='nezbere_large'>\"[text2ratvar("Behold Engine's light")]!!\"</span>\n\
<span class='nzcrentr_large'>\"[text2ratvar("Gaze upon Engine's power")]!\"</span>")
@@ -234,13 +233,8 @@
dist = FALSE
T.ratvar_act(dist)
CHECK_TICK
for(var/mob/living/silicon/robot/R in silicon_mobs)
if(R && R.stat != DEAD && !is_servant_of_ratvar(R))
add_servant_of_ratvar(R)
for(var/i in ai_list)
var/mob/living/silicon/ai/A = i
if(A && A.stat != DEAD && !is_servant_of_ratvar(A))
add_servant_of_ratvar(A)
for(var/mob/living/L in living_mob_list)
L.ratvar_act()
for(var/I in all_clockwork_mobs)
var/mob/M = I
if(M.stat == CONSCIOUS)

View File

@@ -25,9 +25,10 @@
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='nzcrentr_small'>It requires <b>[hierophant_cost]W</b> to broadcast over the Hierophant Network, and <b>[gateway_cost]W</b> to open a Spatial Gateway.</span>"
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/can_be_unfasten_wrench(mob/user)
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/can_be_unfasten_wrench(mob/user, silent)
if(active)
user << "<span class='warning'>[src] is currently sustaining a gateway!</span>"
if(!silent)
user << "<span class='warning'>[src] is currently sustaining a gateway!</span>"
return FAILED_UNFASTEN
return ..()

View File

@@ -32,14 +32,16 @@
/obj/structure/destructible/clockwork/ocular_warden/hulk_damage()
return 25
/obj/structure/destructible/clockwork/ocular_warden/can_be_unfasten_wrench(mob/user)
/obj/structure/destructible/clockwork/ocular_warden/can_be_unfasten_wrench(mob/user, silent)
if(anchored)
if(obj_integrity <= max_integrity * 0.25)
user << "<span class='warning'>[src] is too damaged to unsecure!</span>"
if(!silent)
user << "<span class='warning'>[src] is too damaged to unsecure!</span>"
return FAILED_UNFASTEN
else
for(var/obj/structure/destructible/clockwork/ocular_warden/W in orange(3, src))
user << "<span class='neovgre'>You sense another ocular warden too near this location. Activating this one this close would cause them to fight.</span>"
if(!silent)
user << "<span class='neovgre'>You sense another ocular warden too near this location. Activating this one this close would cause them to fight.</span>"
return FAILED_UNFASTEN
return SUCCESSFUL_UNFASTEN

View File

@@ -498,9 +498,9 @@ var/list/teleport_runes = list()
sleep(40)
if(src)
color = "#FF0000"
new /obj/singularity/narsie/large(T) //Causes Nar-Sie to spawn even if the rune has been removed
if(cult_mode)
cult_mode.eldergod = 0
new /obj/singularity/narsie/large(T) //Causes Nar-Sie to spawn even if the rune has been removed
/obj/effect/rune/narsie/attackby(obj/I, mob/user, params) //Since the narsie rune takes a long time to make, add logging to removal.
if((istype(I, /obj/item/weapon/tome) && iscultist(user)))

View File

@@ -196,9 +196,32 @@
/obj/item/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
return S.Integrate(src)
/obj/item/proc/IntegrateAmount() //returns the amount of resources gained when eating this item
if(materials[MAT_METAL] || materials[MAT_GLASS])
return 1
return 0
/obj/item/weapon/gun/swarmer_act()//Stops you from eating the entire armory
return FALSE
/obj/item/clockwork/alloy_shards/IntegrateAmount()
return 10
/obj/item/stack/tile/brass/IntegrateAmount()
return 5
/obj/item/clockwork/alloy_shards/medium/gear_bit/large/IntegrateAmount()
return 4
/obj/item/clockwork/alloy_shards/large/IntegrateAmount()
return 3
/obj/item/clockwork/alloy_shards/medium/IntegrateAmount()
return 2
/obj/item/clockwork/alloy_shards/small/IntegrateAmount()
return 1
/turf/open/floor/swarmer_act()//ex_act() on turf calls it on its contents, this is to prevent attacking mobs by DisIntegrate()'ing the floor
return FALSE
@@ -316,6 +339,10 @@
S << "<span class='warning'>This communications relay should be preserved, it will be a useful resource to our masters in the future. Aborting.</span>"
return FALSE
/obj/machinery/deepfryer/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>This kitchen appliance should be preserved, it will make delicious unhealthy snacks for our masters in the future. Aborting.</span>"
return FALSE
/obj/machinery/power/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>Disrupting the power grid would bring no benefit to us. Aborting.</span>"
return FALSE
@@ -362,6 +389,10 @@
S << "<span class='warning'>This object is receiving unactivated swarmer shells to help us. Aborting.</span>"
return FALSE
/obj/structure/destructible/clockwork/massive/celestial_gateway/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>This object is multiplying existing resources. Aborting.</span>"
return FALSE
/obj/structure/lattice/catwalk/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
. = ..()
var/turf/here = get_turf(src)
@@ -373,13 +404,12 @@
/obj/item/device/unactivated_swarmer/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
if(S.resources + 50 > S.max_resources)
S << "<span class='warning'>We have too many resources to reconsume this shell. Aborting.</span>"
else
..()
S.resources += 49 //refund the whole thing
..()
return FALSE //would logically be TRUE, but we don't want AI swarmers eating player spawn chances.
/obj/item/device/unactivated_swarmer/IntegrateAmount()
return 50
/obj/machinery/hydroponics/soil/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>This object does not contain enough materials to work with.</span>"
return FALSE
@@ -396,13 +426,13 @@
return 0
return new fabrication_object(loc)
/mob/living/simple_animal/hostile/swarmer/proc/Integrate(obj/item/target)
if(resources >= max_resources)
var/resource_gain = target.IntegrateAmount()
if(resources + resource_gain > max_resources)
src << "<span class='warning'>We cannot hold more materials!</span>"
return TRUE
if((target.materials[MAT_METAL]) || (target.materials[MAT_GLASS]))
resources++
if(resource_gain)
resources += resource_gain
do_attack_animation(target)
changeNext_move(CLICK_CD_MELEE)
var/obj/effect/overlay/temp/swarmer/integrate/I = new /obj/effect/overlay/temp/swarmer/integrate(get_turf(target))

View File

@@ -57,6 +57,7 @@
U.hidden_uplink.telecrystals = CHALLENGE_TELECRYSTALS
U.hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
config.shuttle_refuel_delay = max(config.shuttle_refuel_delay, CHALLENGE_SHUTTLE_DELAY)
feedback_set("nuclear_challenge_mode",1)
qdel(src)
/obj/item/device/nuclear_challenge/proc/check_allowed(mob/living/user)

View File

@@ -20,7 +20,7 @@ var/bomb_set
density = 1
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/timer_set = 60
var/timer_set = 90
var/default_timer_set = 90
var/minimum_timer_set = 90
var/maximum_timer_set = 3600

View File

@@ -72,6 +72,7 @@
/obj/machinery/door/firedoor/attack_hand(mob/user)
if(operating || !density)
return
user.changeNext_move(CLICK_CD_MELEE)
user.visible_message("[user] bangs on \the [src].",
"You bang on \the [src].")

View File

@@ -96,7 +96,7 @@
return
var/area/A = get_area(src)
A.firealert(src)
playsound(src.loc, 'sound/ambience/signal.ogg', 75, 0)
playsound(src.loc, 'goon/sound/machinery/FireAlarm.ogg', 75, 0)
/obj/machinery/firealarm/proc/alarm_in(time)
addtimer(CALLBACK(src, .proc/alarm), time)

View File

@@ -356,13 +356,13 @@ Class Procs:
return 1
return 0
/obj/proc/can_be_unfasten_wrench(mob/user)
/obj/proc/can_be_unfasten_wrench(mob/user, silent) //if we can unwrench this object; returns SUCCESSFUL_UNFASTEN and FAILED_UNFASTEN, which are both TRUE, or CANT_UNFASTEN, which isn't.
if(!isfloorturf(loc) && !anchored)
user << "<span class='warning'>[src] needs to be on the floor to be secured!</span>"
return FAILED_UNFASTEN
return SUCCESSFUL_UNFASTEN
/obj/proc/default_unfasten_wrench(mob/user, obj/item/weapon/wrench/W, time = 20)
/obj/proc/default_unfasten_wrench(mob/user, obj/item/weapon/wrench/W, time = 20) //try to unwrench an object in a WONDERFUL DYNAMIC WAY
if(istype(W) && !(flags & NODECONSTRUCT))
var/can_be_unfasten = can_be_unfasten_wrench(user)
if(!can_be_unfasten || can_be_unfasten == FAILED_UNFASTEN)
@@ -372,10 +372,7 @@ Class Procs:
playsound(loc, W.usesound, 50, 1)
var/prev_anchored = anchored
//as long as we're the same anchored state and we're either on a floor or are anchored, toggle our anchored state
if(!time || (do_after(user, time*W.toolspeed, target = src) && anchored == prev_anchored))
can_be_unfasten = can_be_unfasten_wrench(user)
if(!can_be_unfasten || can_be_unfasten == FAILED_UNFASTEN)
return can_be_unfasten
if(!time || do_after(user, time*W.toolspeed, target = src, extra_checks = CALLBACK(src, .proc/unfasten_wrench_check, prev_anchored, user)))
user << "<span class='notice'>You [anchored ? "un" : ""]secure [src].</span>"
anchored = !anchored
playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1)
@@ -383,6 +380,13 @@ Class Procs:
return FAILED_UNFASTEN
return CANT_UNFASTEN
/obj/proc/unfasten_wrench_check(prev_anchored, mob/user) //for the do_after, this checks if unfastening conditions are still valid
if(anchored != prev_anchored)
return FALSE
if(can_be_unfasten_wrench(user, TRUE) != SUCCESSFUL_UNFASTEN) //if we aren't explicitly successful, cancel the fuck out
return FALSE
return TRUE
/obj/machinery/proc/exchange_parts(mob/user, obj/item/weapon/storage/part_replacer/W)
if(!istype(W))
return

View File

@@ -123,6 +123,8 @@
switch(mode)
if(1,2,4,5)
user << "The display says:<br>\t<xmp>[message1]</xmp><br>\t<xmp>[message2]</xmp>"
if(mode == 1 && SSshuttle.emergency)
user << "Current Shuttle: [SSshuttle.emergency.name]"
/obj/machinery/status_display/proc/set_message(m1, m2)

View File

@@ -762,7 +762,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
/obj/machinery/vending/cigarette
name = "\improper ShadyCigs Deluxe"
desc = "If you want to get cancer, might as well do it in style"
desc = "If you want to get cancer, might as well do it in style."
product_slogans = "Space cigs taste good like a cigarette should.;I'd rather toolbox than switch.;Smoke!;Don't believe the reports - smoke today!"
product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs."
icon_state = "cigs"

View File

@@ -358,8 +358,11 @@
occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 3)
else
occupant.clear_alert("mech damage")
if(occupant.loc != src) //something went wrong
var/actual_loc = occupant.loc
if(istype(actual_loc, /obj/item/device/mmi))
var/obj/item/device/mmi/M = actual_loc
actual_loc = M.mecha
if(actual_loc != src) //something went wrong
occupant.clear_alert("charge")
occupant.clear_alert("mech damage")
RemoveActions(occupant, human_occupant=1)
@@ -859,57 +862,58 @@
else
return 0
/obj/mecha/proc/mmi_move_inside(obj/item/device/mmi/mmi_as_oc,mob/user)
/obj/mecha/proc/mmi_move_inside(obj/item/device/mmi/mmi_as_oc, mob/user)
if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client)
user << "<span class='warning'>Consciousness matrix not detected!</span>"
return 0
return FALSE
else if(mmi_as_oc.brainmob.stat)
user << "<span class='warning'>Beta-rhythm below acceptable level!</span>"
return 0
return FALSE
else if(occupant)
user << "<span class='warning'>Occupant detected!</span>"
return 0
else if(dna_lock && (!mmi_as_oc.brainmob.stored_dna || dna_lock!=mmi_as_oc.brainmob.stored_dna.unique_enzymes))
return FALSE
else if(dna_lock && (!mmi_as_oc.brainmob.stored_dna || (dna_lock != mmi_as_oc.brainmob.stored_dna.unique_enzymes)))
user << "<span class='warning'>Access denied. [name] is secured with a DNA lock.</span>"
return 0
return FALSE
visible_message("<span class='notice'>[user] starts to insert an MMI into [name].</span>")
if(do_after(user, 40, target = src))
if(!occupant)
return mmi_moved_inside(mmi_as_oc,user)
return mmi_moved_inside(mmi_as_oc, user)
else
user << "<span class='warning'>Occupant detected!</span>"
else
user << "<span class='notice'>You stop inserting the MMI.</span>"
return 0
return FALSE
/obj/mecha/proc/mmi_moved_inside(obj/item/device/mmi/mmi_as_oc,mob/user)
if(mmi_as_oc && user in range(1))
if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client)
user << "<span class='notice'>Consciousness matrix not detected!</span>"
return 0
else if(mmi_as_oc.brainmob.stat)
user << "<span class='warning'>Beta-rhythm below acceptable level!</span>"
return 0
if(!user.transferItemToLoc(mmi_as_oc, src))
user << "<span class='warning'>\the [mmi_as_oc] is stuck to your hand, you cannot put it in \the [src]!</span>"
return
var/mob/brainmob = mmi_as_oc.brainmob
occupant = brainmob
brainmob.forceMove(src) //should allow relaymove
brainmob.reset_perspective(src)
brainmob.canmove = 1
mmi_as_oc.mecha = src
icon_state = initial(icon_state)
setDir(dir_in)
log_message("[mmi_as_oc] moved in as pilot.")
if(!internal_damage)
occupant << sound('sound/mecha/nominal.ogg',volume=50)
GrantActions(brainmob)
return 1
else
return 0
/obj/mecha/proc/mmi_moved_inside(obj/item/device/mmi/mmi_as_oc, mob/user)
if(!(Adjacent(mmi_as_oc) && Adjacent(user)))
return FALSE
if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client)
user << "<span class='notice'>Consciousness matrix not detected!</span>"
return FALSE
else if(mmi_as_oc.brainmob.stat)
user << "<span class='warning'>Beta-rhythm below acceptable level!</span>"
return FALSE
if(!user.transferItemToLoc(mmi_as_oc, src))
user << "<span class='warning'>\the [mmi_as_oc] is stuck to your hand, you cannot put it in \the [src]!</span>"
return FALSE
var/mob/brainmob = mmi_as_oc.brainmob
mmi_as_oc.mecha = src
occupant = brainmob
brainmob.forceMove(src) //should allow relaymove
brainmob.reset_perspective(src)
brainmob.remote_control = src
brainmob.update_canmove()
icon_state = initial(icon_state)
update_icon()
setDir(dir_in)
log_message("[mmi_as_oc] moved in as pilot.")
if(!internal_damage)
occupant << sound('sound/mecha/nominal.ogg',volume=50)
GrantActions(brainmob)
return TRUE
/obj/mecha/container_resist(mob/living/user)
go_out()
@@ -1046,4 +1050,4 @@ var/year_integer = text2num(year) // = 2013???
/obj/mecha/update_remote_sight(mob/living/user)
if(occupant_sight_flags)
if(user == occupant)
user.sight |= occupant_sight_flags
user.sight |= occupant_sight_flags

View File

@@ -43,10 +43,6 @@
..()
update_icon()
/obj/mecha/working/ripley/mmi_moved_inside(obj/item/device/mmi/mmi_as_oc,mob/user)
..()
update_icon()
/obj/mecha/working/ripley/update_icon()
..()
if (hides)
@@ -178,4 +174,4 @@
cargo -= O
else
if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded.
user << "<span class='warning'>You fail to push [O] out of [src]!</span>"
user << "<span class='warning'>You fail to push [O] out of [src]!</span>"

View File

@@ -104,9 +104,9 @@ list(name = "- Carbon Dioxide", desc = " This informational poster teaches the v
icon = 'icons/obj/contraband.dmi'
force = 0
resistance_flags = FLAMMABLE
var/serial_number = 0
var/serial = 0
var/obj/structure/sign/poster/resulting_poster = null //The poster that will be created is initialised and stored through contraband/poster's constructor
var/official = 0
var/rolled_official = 0
/obj/item/weapon/poster/contraband
@@ -118,20 +118,20 @@ list(name = "- Carbon Dioxide", desc = " This informational poster teaches the v
name = "motivational poster"
icon_state = "rolled_legit"
desc = "An official Nanotrasen-issued poster to foster a compliant and obedient workforce. It comes with state-of-the-art adhesive backing, for easy pinning to any vertical surface."
official = 1
rolled_official = 1
/obj/item/weapon/poster/New(turf/loc, given_serial = 0)
if(given_serial == 0)
if(!official)
serial_number = rand(1, NUM_OF_POSTER_DESIGNS)
resulting_poster = new(serial_number,official)
if(!rolled_official)
serial = rand(1, NUM_OF_POSTER_DESIGNS)
resulting_poster = new(serial,rolled_official)
else
serial_number = rand(1, NUM_OF_POSTER_DESIGNS_LEGIT)
resulting_poster = new(serial_number,official)
serial = rand(1, NUM_OF_POSTER_DESIGNS_LEGIT)
resulting_poster = new(serial,rolled_official)
else
serial_number = given_serial
serial = given_serial
//We don't give it a resulting_poster because if we called it with a given_serial it means that we're rerolling an already used poster.
name += " - No. [serial_number]"
name += " - No. [serial]"
..(loc)
@@ -182,8 +182,10 @@ list(name = "- Carbon Dioxide", desc = " This informational poster teaches the v
var/placespeed = 37 // don't change this, otherwise the animation will not sync to the progress bar
/obj/structure/sign/poster/New(serial,rolled_official)
serial_number = serial
official = rolled_official
if (!serial_number)
serial_number = serial
if(!official)
official = rolled_official
if(serial_number == loc)
if(!official)
serial_number = rand(1, NUM_OF_POSTER_DESIGNS) //This is for the mappers that want individual posters without having to use rolled posters.
@@ -259,7 +261,7 @@ list(name = "- Carbon Dioxide", desc = " This informational poster teaches the v
var/temp_loc = get_turf(user)
flick("poster_being_set",D)
D.loc = src
D.official = P.official
D.official = P.rolled_official
qdel(P) //delete it now to cut down on sanity checks afterwards. Agouri's code supports rerolling it anyway
playsound(D.loc, 'sound/items/poster_being_created.ogg', 100, 1)

View File

@@ -234,7 +234,8 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
var/obj/item/weapon/storage/S = loc
S.remove_from_storage(src, user.loc)
throwing = 0
if(throwing)
throwing.finalize(FALSE)
if(loc == user)
if(!user.dropItemToGround(src))
return
@@ -255,7 +256,8 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
var/obj/item/weapon/storage/S = loc
S.remove_from_storage(src, user.loc)
throwing = 0
if(throwing)
throwing.finalize(FALSE)
if(loc == user)
if(!user.dropItemToGround(src))
return

View File

@@ -1,3 +1,5 @@
#define STATION_RENAME_TIME_LIMIT 3000
/obj/item/station_charter
name = "station charter"
icon = 'icons/obj/wizard.dmi'
@@ -33,7 +35,7 @@
if(used)
user << "This charter has already been used to name the station."
return
if(!ignores_timeout && (world.time-round_start_time > CHALLENGE_TIME_LIMIT)) //5 minutes
if(!ignores_timeout && (world.time-round_start_time > STATION_RENAME_TIME_LIMIT)) //5 minutes
user << "The crew has already settled into the shift. \
It probably wouldn't be good to rename the station right now."
return
@@ -93,3 +95,5 @@
if(!unlimited_uses)
used = TRUE
#undef STATION_RENAME_TIME_LIMIT

View File

@@ -7,7 +7,6 @@
w_class = WEIGHT_CLASS_TINY
origin_tech = "engineering=2;bluespace=1"
var/translate_binary = 0
var/translate_hive = 0
var/syndie = 0
var/centcom = 0
var/list/channels = list()

View File

@@ -273,9 +273,6 @@
if(keyslot2.translate_binary)
src.translate_binary = 1
if(keyslot2.translate_hive)
src.translate_hive = 1
if(keyslot2.syndie)
src.syndie = 1

View File

@@ -17,7 +17,6 @@
var/broadcasting = 0
var/listening = 1
var/translate_binary = 0
var/translate_hive = 0
var/freerange = 0 // 0 - Sanitize frequencies, 1 - Full range
var/list/channels = list() //see communications.dm for full list. First channes is a "default" for :h
var/obj/item/device/encryptionkey/keyslot //To allow the radio to accept encryption keys.
@@ -58,7 +57,6 @@
/obj/item/device/radio/proc/recalculateChannels()
channels = list()
translate_binary = 0
translate_hive = 0
syndie = 0
centcom = 0
@@ -72,9 +70,6 @@
if(keyslot.translate_binary)
translate_binary = 1
if(keyslot.translate_hive)
translate_hive = 1
if(keyslot.syndie)
syndie = 1

View File

@@ -272,12 +272,17 @@
/obj/item/device/tape/attackby(obj/item/I, mob/user, params)
if(ruined && istype(I, /obj/item/weapon/screwdriver))
user << "<span class='notice'>You start winding the tape back in...</span>"
if(do_after(user, 120*I.toolspeed, target = src))
user << "<span class='notice'>You wound the tape back in.</span>"
fix()
if(ruined)
var/delay = -1
if (istype(I, /obj/item/weapon/screwdriver))
delay = 120*I.toolspeed
else if(istype(I, /obj/item/weapon/pen))
delay = 120*1.5
if (delay != -1)
user << "<span class='notice'>You start winding the tape back in...</span>"
if(do_after(user, delay, target = src))
user << "<span class='notice'>You wound the tape back in.</span>"
fix()
//Random colour tapes
/obj/item/device/tape/random/New()

View File

@@ -251,7 +251,7 @@
//get amount from user
var/min = 0
var/max = src.get_amount()
var/stackmaterial = input(user,"How many sheets do you wish to take out of this stack? (Maximum [max]") as num
var/stackmaterial = round(input(user,"How many sheets do you wish to take out of this stack? (Maximum [max]") as num)
if(stackmaterial == null || stackmaterial <= min || stackmaterial >= src.get_amount())
return
else

View File

@@ -522,43 +522,39 @@ var/global/list/RPD_recipes=list(
if(!user.IsAdvancedToolUser() || istype(A,/turf/open/space/transit))
return ..()
//make sure what we're clicking is valid for the current mode
var/is_paintable = (p_class == PAINT_MODE && istype(A, /obj/machinery/atmospherics/pipe))
var/is_consumable = (p_class == EATING_MODE && (istype(A, /obj/item/pipe) || istype(A, /obj/item/pipe_meter) || istype(A, /obj/structure/disposalconstruct)))
var/can_make_pipe = ((p_class == ATMOS_MODE || p_class == METER_MODE || p_class == DISPOSALS_MODE) && isturf(A))
if(!is_paintable && !is_consumable && !can_make_pipe)
return ..()
//So that changing the menu settings doesn't affect the pipes already being built.
var/queued_p_type = p_type
var/queued_p_dir = p_dir
var/queued_p_flipped = p_flipped
. = FALSE
switch(p_class)
if(PAINT_MODE) // Paint pipes
if(!istype(A,/obj/machinery/atmospherics/pipe))
// Avoid spewing errors about invalid mode -2 when clicking on stuff that aren't pipes.
user << "<span class='warning'>\The [src]'s error light flickers! Perhaps you need to only use it on pipes and pipe meters?</span>"
return
switch(p_class) //if we've gotten this var, the target is valid
if(PAINT_MODE) //Paint pipes
var/obj/machinery/atmospherics/pipe/P = A
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
P.add_atom_colour(paint_colors[paint_color], FIXED_COLOUR_PRIORITY)
P.pipe_color = paint_colors[paint_color]
user.visible_message("<span class='notice'>[user] paints \the [P] [paint_color].</span>","<span class='notice'>You paint \the [P] [paint_color].</span>")
//P.update_icon()
P.update_node_icon()
return
if(EATING_MODE) // Eating pipes
// Must click on an actual pipe or meter.
if(!(istype(A,/obj/item/pipe) || istype(A,/obj/item/pipe_meter) || istype(A,/obj/structure/disposalconstruct)))
// Avoid spewing errors about invalid mode -1 when clicking on stuff that aren't pipes.
user << "<span class='warning'>The [src]'s error light flickers! Perhaps you need to only use it on pipes and pipe meters?</span>"
return
user << "<span class='notice'>You start destroying pipe...</span>"
if(EATING_MODE) //Eating pipes
user << "<span class='notice'>You start destroying a pipe...</span>"
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
if(do_after(user, 2, target = A))
activate()
qdel(A)
if(ATMOS_MODE)
if(!isturf(A))
user << "<span class='warning'>The [src]'s error light flickers!</span>"
return
user << "<span class='notice'>You start building pipes...</span>"
if(ATMOS_MODE) //Making pipes
user << "<span class='notice'>You start building a pipe...</span>"
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
if(do_after(user, 2, target = A))
activate()
@@ -567,21 +563,18 @@ var/global/list/RPD_recipes=list(
P.update()
P.add_fingerprint(usr)
if(METER_MODE)
if(!isturf(A))
user << "<span class='warning'>The [src]'s error light flickers!</span>"
return 0
if(METER_MODE) //Making pipe meters
user << "<span class='notice'>You start building a meter...</span>"
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
if(do_after(user, 2, target = A))
activate()
new /obj/item/pipe_meter(A)
if(DISPOSALS_MODE)
if(!isturf(A) || is_anchored_dense_turf(A))
user << "<span class='warning'>The [src]'s error light flickers!</span>"
if(DISPOSALS_MODE) //Making disposals pipes
if(!is_anchored_dense_turf(A))
user << "<span class='warning'>The [src]'s error light flickers; there's something in the way!</span>"
return
user << "<span class='notice'>You start building pipes...</span>"
user << "<span class='notice'>You start building a disposals pipe...</span>"
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
if(do_after(user, 20, target = A))
var/obj/structure/disposalconstruct/C = new (A, queued_p_type ,queued_p_dir)

View File

@@ -172,7 +172,7 @@
user.visible_message("[user] has thrown [src]. It lands on [result]. [comment]", \
"<span class='notice'>You throw [src]. It lands on [result]. [comment]</span>", \
"<span class='italics'>You hear [src] rolling, it sounds like a [fake_result].</span>")
else if(src.throwing == 0) //Dice was thrown and is coming to rest
else if(!src.throwing) //Dice was thrown and is coming to rest
visible_message("<span class='notice'>[src] rolls to a stop, landing on [result]. [comment]</span>")
/obj/item/weapon/dice/d4/Crossed(mob/living/carbon/human/H)

View File

@@ -37,12 +37,11 @@
//What does the implant do upon injection?
//return 1 if the implant injects
//return -1 if the implant fails to inject
//return 0 if there is no room for implant
//return 0 if there is no room for implant / it fails
/obj/item/weapon/implant/proc/implant(mob/living/target, mob/user, silent = 0)
LAZYINITLIST(target.implants)
if(!target.can_be_implanted() || !can_be_implanted_in(target))
return -1
return 0
for(var/X in target.implants)
if(istype(X, type))
var/obj/item/weapon/implant/imp_e = X

View File

@@ -43,7 +43,7 @@
target.visible_message("<span class='warning'>[target] seems to resist the implant!</span>", "<span class='warning'>You feel the influence of your enemies try to invade your mind!</span>")
qdel(src)
return -1
return 0
/obj/item/weapon/implanter/gang
name = "implanter (gang)"

View File

@@ -24,14 +24,14 @@
target.visible_message("<span class='warning'>[target] seems to resist the implant!</span>", "<span class='warning'>You feel something interfering with your mental conditioning, but you resist it!</span>")
removed(target, 1)
qdel(src)
return -1
return 0
if(target.mind in ticker.mode.get_gangsters())
ticker.mode.remove_gangster(target.mind)
if(!silent)
target.visible_message("<span class='warning'>[src] was destroyed in the process!</span>", "<span class='notice'>You feel a sense of peace and security. You are now protected from brainwashing.</span>")
removed(target, 1)
qdel(src)
return -1
return 0
if(target.mind in ticker.mode.revolutionaries)
ticker.mode.remove_revolutionary(target.mind)
if(!silent)

View File

@@ -38,6 +38,8 @@
M.visible_message("[user] has implanted [M].", "<span class='notice'>[user] implants you.</span>")
imp = null
update_icon()
else
user << "<span class='warning'>[src] fails to implant [M].</span>"
/obj/item/weapon/implanter/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/pen))

View File

@@ -574,7 +574,6 @@
user.changeNext_move(CLICK_CD_MELEE)
playsound(loc, "rustle", 50, 1, -5)
user.visible_message("<span class='notice'>[user] hugs \the [src].</span>","<span class='notice'>You hug \the [src].</span>")
return
/obj/item/weapon/storage/box/hug/medical/New()
..()

View File

@@ -34,6 +34,10 @@
new /obj/item/device/flashlight/flare(src)
new /obj/item/device/radio/off(src)
/obj/item/weapon/storage/toolbox/emergency/old
name = "rusty red toolbox"
item_state = "toolbox_red_old"
/obj/item/weapon/storage/toolbox/mechanical
name = "mechanical toolbox"
icon_state = "blue"
@@ -48,6 +52,10 @@
new /obj/item/device/analyzer(src)
new /obj/item/weapon/wirecutters(src)
/obj/item/weapon/storage/toolbox/mechanical/old
name = "rusty blue toolbox"
item_state = "toolbox_blue_old"
/obj/item/weapon/storage/toolbox/electrical
name = "electrical toolbox"
icon_state = "yellow"

View File

@@ -306,3 +306,7 @@
..()
for(var/i in 1 to 3)
new/obj/item/weapon/grenade/chem_grenade/ez_clean(src)
/obj/item/weapon/storage/box/hug/reverse_revolver/New()
..()
new /obj/item/weapon/gun/ballistic/revolver/reverse(src)

View File

@@ -9,6 +9,7 @@
var/gas_type = "o2"
var/on = FALSE
var/stabilizers = FALSE
var/full_speed = TRUE // If the jetpack will have a speedboost in space/nograv or not
var/datum/effect_system/trail_follow/ion/ion_trail
/obj/item/weapon/tank/jetpack/New()
@@ -133,6 +134,7 @@
volume = 1
slot_flags = null
gas_type = null
full_speed = FALSE
var/datum/gas_mixture/temp_air_contents
var/obj/item/weapon/tank/internals/tank = null

View File

@@ -113,7 +113,7 @@
if(throwing) // you keep some momentum when getting out of a thrown closet
step(AM, dir)
if(throwing)
throwing = 0
throwing.finalize(FALSE)
/obj/structure/closet/proc/take_contents()
var/turf/T = get_turf(src)
@@ -438,3 +438,7 @@
for(var/atom/A in contents)
A.ex_act(severity, target)
CHECK_TICK
/obj/structure/closet/singularity_act()
dump_contents()
..()

View File

@@ -107,6 +107,15 @@
cur_acc[cur_note] = "#" // so shift is never required
else
cur_oct[cur_note] = text2num(ni)
if(user.dizziness > 0 && prob(user.dizziness / 2))
cur_note = Clamp(cur_note + rand(round(-user.dizziness / 10), round(user.dizziness / 10)), 1, 7)
if(user.dizziness > 0 && prob(user.dizziness / 5))
if(prob(30))
cur_acc[cur_note] = "#"
else if(prob(42))
cur_acc[cur_note] = "b"
else if(prob(75))
cur_acc[cur_note] = "n"
playnote(cur_note, cur_acc[cur_note], cur_oct[cur_note])
if(notes.len >= 2 && text2num(notes[2]))
sleep(sanitize_tempo(tempo / text2num(notes[2])))

View File

@@ -30,23 +30,20 @@
/turf/closed/indestructible/splashscreen
name = "Space Station 13"
icon = 'icons/misc/fullscreen.dmi'
icon_state = "title1"
icon_state = "title"
layer = FLY_LAYER
var/titlescreen = TITLESCREEN
/turf/closed/indestructible/splashscreen/New()
/turf/closed/indestructible/splashscreen/Initialize()
..()
icon_state = pick("title1","title2","title3","title4","title5")
if(titlescreen)
icon_state = titlescreen
/turf/closed/indestructible/riveted
icon = 'icons/turf/walls/riveted.dmi'
icon_state = "riveted"
smooth = SMOOTH_TRUE
/turf/closed/indestructible/New()
..()
if(smooth)
queue_smooth(src)
/turf/closed/indestructible/riveted/uranium
icon = 'icons/turf/walls/uranium_wall.dmi'
icon_state = "uranium"
@@ -64,7 +61,7 @@
smooth = SMOOTH_TRUE
icon = 'icons/obj/smooth_structures/reinforced_window.dmi'
/turf/closed/indestructible/fakeglass/New()
/turf/closed/indestructible/fakeglass/Initialize()
..()
icon_state = null //set the icon state to null, so our base state isn't visible
var/image/I = image('icons/obj/structures.dmi', loc = src, icon_state = "grille")

View File

@@ -29,22 +29,20 @@
baseturf = /turf/open/indestructible/necropolis
initial_gas_mix = "o2=14;n2=23;TEMP=300"
/turf/open/indestructible/necropolis/New()
/turf/open/indestructible/necropolis/Initialize()
..()
if(prob(12))
icon_state = "necro[rand(2,3)]"
/turf/open/indestructible/necropolis/air
initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
/turf/open/indestructible/hierophant
icon = 'icons/turf/floors/hierophant_floor.dmi'
initial_gas_mix = "o2=14;n2=23;TEMP=300"
baseturf = /turf/open/indestructible/hierophant
smooth = SMOOTH_TRUE
/turf/open/indestructible/hierophant/New()
..()
if(smooth)
queue_smooth(src)
/turf/open/indestructible/hierophant/two
/turf/open/indestructible/paper

View File

@@ -69,7 +69,7 @@
L.adjustBruteLoss(30)
/turf/open/chasm/straight_down/New()
/turf/open/chasm/straight_down/Initialize()
..()
drop_x = x
drop_y = y

View File

@@ -33,7 +33,7 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","
var/list/broken_states
var/list/burnt_states
/turf/open/floor/New()
/turf/open/floor/Initialize(mapload)
if (!broken_states)
broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5")
if (!burnt_states)
@@ -43,6 +43,8 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","
icon_regular_floor = "floor"
else
icon_regular_floor = icon_state
if(mapload)
MakeDirty()
/turf/open/floor/ex_act(severity, target)
var/shielded = is_shielded()
@@ -179,10 +181,5 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","
if(.)
ChangeTurf(/turf/open/floor/clockwork)
/turf/open/floor/Initialize(mapload)
..()
if(mapload)
MakeDirty()
/turf/open/floor/acid_melt()
ChangeTurf(baseturf)

View File

@@ -36,10 +36,9 @@
flags = NONE
var/ore_type = /obj/item/weapon/ore/glass
/turf/open/floor/grass/New()
/turf/open/floor/grass/Initialize()
..()
spawn(1)
update_icon()
update_icon()
/turf/open/floor/grass/attackby(obj/item/C, mob/user, params)
if(istype(C, /obj/item/weapon/shovel) && params)
@@ -76,7 +75,7 @@
initial_gas_mix = "o2=14;n2=23;TEMP=300"
slowdown = 0
/turf/open/floor/grass/snow/basalt/New()
/turf/open/floor/grass/snow/basalt/Initialize()
..()
if(prob(15))
icon_state = "basalt[rand(0, 12)]"
@@ -96,10 +95,9 @@
canSmoothWith = null
flags = NONE
/turf/open/floor/carpet/New()
/turf/open/floor/carpet/Initialize()
..()
spawn(1)
update_icon()
update_icon()
/turf/open/floor/carpet/update_icon()
if(!..())
@@ -131,6 +129,6 @@
broken_states = list("damaged")
plane = PLANE_SPACE
/turf/open/floor/fakespace/New()
/turf/open/floor/fakespace/Initialize()
..()
icon_state = "[rand(0,25)]"

View File

@@ -12,7 +12,7 @@
var/can_modify_colour = TRUE
/turf/open/floor/light/New()
/turf/open/floor/light/Initialize()
..()
update_icon()

View File

@@ -16,7 +16,7 @@
/turf/open/floor/mineral/New()
/turf/open/floor/mineral/Initialize()
broken_states = list("[initial(icon_state)]_dam")
..()
if (!icons)
@@ -221,7 +221,7 @@
floor_tile = /obj/item/stack/tile/mineral/abductor
icons = list("alienpod1", "alienpod2", "alienpod3", "alienpod4", "alienpod5", "alienpod6", "alienpod7", "alienpod8", "alienpod9")
/turf/open/floor/mineral/abductor/New()
/turf/open/floor/mineral/abductor/Initialize()
..()
icon_state = "alienpod[rand(1,9)]"

View File

@@ -13,9 +13,9 @@
icon_state = "bcircuit"
floor_tile = /obj/item/stack/tile/plasteel
/turf/open/floor/bluegrid/New()
..()
/turf/open/floor/bluegrid/Initialize()
SSmapping.nuke_tiles += src
..()
/turf/open/floor/bluegrid/Destroy()
SSmapping.nuke_tiles -= src
@@ -67,7 +67,7 @@
icon_state = "plating"
var/obj/effect/clockwork/overlay/floor/realappearence
/turf/open/floor/clockwork/New()
/turf/open/floor/clockwork/Initialize()
..()
new /obj/effect/overlay/temp/ratvar/floor(src)
new /obj/effect/overlay/temp/ratvar/beam(src)

View File

@@ -13,7 +13,7 @@
icon_state = "plating"
intact = 0
/turf/open/floor/plating/New()
/turf/open/floor/plating/Initialize()
if (!broken_states)
broken_states = list("platingdmg1", "platingdmg2", "platingdmg3")
if (!burnt_states)

View File

@@ -15,7 +15,7 @@
var/sand_type = /obj/item/weapon/ore/glass
var/floor_variance = 20 //probability floor has a different icon state
/turf/open/floor/plating/asteroid/New()
/turf/open/floor/plating/asteroid/Initialize()
var/proper_name = name
..()
name = proper_name
@@ -117,7 +117,7 @@
/turf/open/floor/plating/asteroid/basalt/airless
initial_gas_mix = "TEMP=2.7"
/turf/open/floor/plating/asteroid/basalt/New()
/turf/open/floor/plating/asteroid/basalt/Initialize()
..()
switch(icon_state)
if("basalt1", "basalt2", "basalt3") //5 and 9 are too dark to glow and make the amount of glows in tunnels too high
@@ -176,7 +176,7 @@
/turf/open/floor/plating/asteroid/airless/cave/volcanic/has_data //subtype for producing a tunnel with given data
has_data = TRUE
/turf/open/floor/plating/asteroid/airless/cave/New(loc)
/turf/open/floor/plating/asteroid/airless/cave/Initialize()
if (!mob_spawn_list)
mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goldgrub = 1, /mob/living/simple_animal/hostile/asteroid/goliath = 5, /mob/living/simple_animal/hostile/asteroid/basilisk = 4, /mob/living/simple_animal/hostile/asteroid/hivelord = 3)
if (!megafauna_spawn_list)
@@ -186,7 +186,8 @@
if(!has_data)
produce_tunnel_from_data()
..()
else
..() //do not continue after changeturfing or we will do a double initialize
/turf/open/floor/plating/asteroid/airless/cave/proc/get_cave_data(set_length, exclude_dir = -1)
// If set_length (arg1) isn't defined, get a random length; otherwise assign our length to the length arg.

View File

@@ -7,12 +7,6 @@
baseturf = /turf/open/floor/plating/lava //lava all the way down
slowdown = 2
luminosity = 1
var/static/list/safeties_typecache = list(/obj/structure/lattice/catwalk)
//if anything matching this typecache is found in the lava, we don't burn things
/turf/open/floor/plating/lava/New()
..()
safeties_typecache = typecacheof(safeties_typecache)
/turf/open/floor/plating/lava/ex_act()
return
@@ -51,7 +45,9 @@
/turf/open/floor/plating/lava/proc/is_safe()
var/list/found_safeties = typecache_filter_list(contents, safeties_typecache)
//if anything matching this typecache is found in the lava, we don't burn things
var/static/list/lava_safeties_typecache = typecacheof(list(/obj/structure/lattice/catwalk))
var/list/found_safeties = typecache_filter_list(contents, lava_safeties_typecache)
return LAZYLEN(found_safeties)

View File

@@ -7,7 +7,7 @@
name = "alien floor"
icon_state = "alienpod1"
/turf/open/floor/plating/abductor/New()
/turf/open/floor/plating/abductor/Initialize()
..()
icon_state = "alienpod[rand(1,9)]"
@@ -41,7 +41,7 @@
initial_gas_mix = "o2=14;n2=23;TEMP=300"
planetary_atmos = TRUE
/turf/open/floor/plating/ashplanet/New()
/turf/open/floor/plating/ashplanet/Initialize()
if(smooth)
pixel_y = -4
pixel_x = -4
@@ -72,7 +72,7 @@
icon_state = "wateryrock"
slowdown = 2
/turf/open/floor/plating/ashplanet/wateryrock/New()
/turf/open/floor/plating/ashplanet/wateryrock/Initialize()
icon_state = "[icon_state][rand(1, 9)]"
..()
@@ -113,7 +113,7 @@
name = "iron sand"
desc = "Like sand, but more <i>metal</i>."
/turf/open/floor/plating/ironsand/New()
/turf/open/floor/plating/ironsand/Initialize()
..()
icon_state = "ironsand[rand(1,15)]"

View File

@@ -106,7 +106,7 @@
icon_state = "plating"
var/obj/effect/clockwork/overlay/floor/bloodcult/realappearence
/turf/open/floor/engine/cult/New()
/turf/open/floor/engine/cult/Initialize()
..()
new /obj/effect/overlay/temp/cult/turf/floor(src)
realappearence = new /obj/effect/clockwork/overlay/floor/bloodcult(src)

View File

@@ -24,7 +24,7 @@
var/scan_state = null //Holder for the image we display when we're pinged by a mining scanner
var/defer_change = 0
/turf/closed/mineral/New()
/turf/closed/mineral/Initialize()
if (!canSmoothWith)
canSmoothWith = list(/turf/closed)
pixel_y = -4
@@ -139,7 +139,7 @@
var/mineralChance = 13
var/display_icon_state = "rock"
/turf/closed/mineral/random/New()
/turf/closed/mineral/random/Initialize()
if (!mineralSpawnChanceList)
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium = 5, /turf/closed/mineral/diamond = 1, /turf/closed/mineral/gold = 10,
@@ -385,7 +385,7 @@
var/activated_name = null
var/activated_image = null
/turf/closed/mineral/gibtonite/New()
/turf/closed/mineral/gibtonite/Initialize()
det_time = rand(8,10) //So you don't know exactly when the hot potato will explode
..()

View File

@@ -8,7 +8,7 @@
sheet_amount = 1
girder_type = /obj/structure/girder/cult
/turf/closed/wall/mineral/cult/New()
/turf/closed/wall/mineral/cult/Initialize()
new /obj/effect/overlay/temp/cult/turf(src)
..()
@@ -50,7 +50,7 @@
var/obj/effect/clockwork/overlay/wall/realappearence
var/obj/structure/destructible/clockwork/cache/linkedcache
/turf/closed/wall/clockwork/New()
/turf/closed/wall/clockwork/Initialize()
..()
new /obj/effect/overlay/temp/ratvar/wall(src)
new /obj/effect/overlay/temp/ratvar/beam(src)

View File

@@ -15,15 +15,16 @@
var/global/datum/gas_mixture/space/space_gas = new
plane = PLANE_SPACE
/turf/open/space/New()
/turf/open/space/Initialize()
icon_state = SPACE_ICON_STATE
air = space_gas
if(initialized)
stack_trace("Warning: [src]([type]) initialized multiple times!")
initialized = TRUE
/turf/open/space/Destroy(force)
if(force)
. = ..()
else
return QDEL_HINT_LETMELIVE
if(requires_activation)
SSair.add_to_active(src)
/turf/open/space/attack_ghost(mob/dead/observer/user)
if(destination_z)

View File

@@ -61,14 +61,12 @@
/turf/open/space/transit/attackby()
return
/turf/open/space/transit/New()
/turf/open/space/transit/Initialize()
..()
update_icon()
for(var/atom/movable/AM in src)
throw_atom(AM)
/turf/open/space/transit/proc/update_icon()
var/p = 9
var/angle = 0

View File

@@ -23,14 +23,17 @@
var/explosion_id = 0
var/list/decals
var/requires_activation //add to air processing after initialize?
/turf/SDQL_update(const/var_name, new_value)
if(var_name == "x" || var_name == "y" || var_name == "z")
return FALSE
. = ..()
/turf/New()
..()
/turf/Initialize()
if(initialized)
stack_trace("Warning: [src]([type]) initialized multiple times!")
initialized = TRUE
levelupdate()
if(smooth)
@@ -40,11 +43,17 @@
for(var/atom/movable/AM in src)
Entered(AM)
if(requires_activation)
CalculateAdjacentTurfs()
SSair.add_to_active(src)
/turf/proc/Initalize_Atmos(times_fired)
CalculateAdjacentTurfs()
/turf/Destroy()
visibilityChanged()
initialized = FALSE
requires_activation = FALSE
..()
return QDEL_HINT_HARDDEL_NOW
@@ -454,4 +463,4 @@
/turf/proc/remove_decal(group)
LAZYINITLIST(decals)
overlays -= decals[group]
decals[group] = null
decals[group] = null

View File

@@ -100,44 +100,6 @@
qdel(src)
//Luxury Shuttle Blockers
/obj/effect/forcefield/luxury_shuttle
var/threshhold = 500
var/list/approved_passengers = list()
/obj/effect/forcefield/luxury_shuttle/CanPass(atom/movable/mover, turf/target, height=0)
if(mover in approved_passengers)
return 1
if(!isliving(mover)) //No stowaways
return 0
var/total_cash = 0
var/list/counted_money = list()
for(var/obj/item/weapon/coin/C in mover)
total_cash += C.value
counted_money += C
if(total_cash >= threshhold)
break
for(var/obj/item/stack/spacecash/S in mover)
total_cash += S.value * S.amount
counted_money += S
if(total_cash >= threshhold)
break
if(total_cash >= threshhold)
for(var/obj/I in counted_money)
qdel(I)
mover << "Thank you for your payment! Please enjoy your flight."
approved_passengers += mover
return 1
else
mover << "You don't have enough money to enter the main shuttle. You'll have to fly coach."
return 0
//Shuttle Build
/obj/effect/shuttle_build
@@ -149,4 +111,69 @@
/obj/effect/shuttle_build/New()
SSshuttle.emergency.dock(SSshuttle.getDock("emergency_home"))
qdel(src)
qdel(src)
//Arena
/obj/effect/forcefield/arena_shuttle
name = "portal"
var/list/warp_points = list()
/obj/effect/forcefield/arena_shuttle/Bumped(mob/M as mob|obj)
if(!warp_points.len)
warp_points = get_area_turfs(/area/shuttle/escape)
for(var/turf/T in warp_points)
for(var/atom/movable/AM in T)
if(AM.density && AM.anchored)
warp_points -= T
break
if(!isliving(M))
return
else
var/mob/living/L = M
if(L.pulling && istype(L.pulling, /obj/item/bodypart/head))
L << "Your offering is accepted. You may pass."
qdel(L.pulling)
var/turf/LA = pick(warp_points)
L.forceMove(LA)
L.hallucination = 0
L << "<span class='reallybig redtext'>The battle is won. Your bloodlust subsides.</span>"
for(var/obj/item/weapon/twohanded/required/chainsaw/doomslayer/chainsaw in L)
qdel(chainsaw)
else
L << "You are not yet worthy of passing. Drag a severed head to the barrier to be allowed entry to the hall of champions."
/obj/effect/landmark/shuttle_arena_safe
name = "hall of champions"
desc = "For the winners."
/obj/effect/landmark/shuttle_arena_entrance
name = "the arena"
desc = "A lava filled battlefield."
/obj/effect/forcefield/arena_shuttle_entrance
name = "portal"
var/list/warp_points = list()
/obj/effect/forcefield/arena_shuttle_entrance/Bumped(mob/M as mob|obj)
if(!warp_points.len)
for(var/obj/effect/landmark/shuttle_arena_entrance/S in landmarks_list)
warp_points |= S
if(!isliving(M))
return
var/obj/effect/landmark/LA = pick(warp_points)
M.forceMove(get_turf(LA))
M << "<span class='reallybig redtext'>You're trapped in a deadly arena! To escape, you'll need to drag a severed head to the escape portals.</span>"
spawn()
var/obj/effect/mine/pickup/bloodbath/B = new(M)
B.mineEffect(M)
/area/shuttle_arena
name = "arena"
has_gravity = 1
requires_power = 0

View File

@@ -337,10 +337,40 @@
dat += "Time limit: <a href='?_src_=holder;alter_midround_time_limit=1'>[config.midround_antag_time_check] minutes into round</a><BR>"
dat += "Living crew limit: <a href='?_src_=holder;alter_midround_life_limit=1'>[config.midround_antag_life_check * 100]% of crew alive</a><BR>"
dat += "If limits past: <a href='?_src_=holder;toggle_noncontinuous_behavior=1'>[ticker.mode.round_ends_with_antag_death ? "End The Round" : "Continue As Extended"]</a><BR>"
dat += "<BR>"
dat += "<a href='?_src_=holder;end_round=\ref[usr]'>End Round Now</a><br>"
dat += "<a href='?_src_=holder;delay_round_end=1'>[ticker.delay_end ? "End Round Normally" : "Delay Round End"]</a><br>"
dat += "<a href='?_src_=holder;delay_round_end=1'>[ticker.delay_end ? "End Round Normally" : "Delay Round End"]</a>"
var/connected_players = clients.len
var/lobby_players = 0
var/observers = 0
var/observers_connected = 0
var/living_players = 0
var/living_players_connected = 0
var/living_players_antagonist = 0
var/other_players = 0
for(var/mob/M in mob_list)
if(M.ckey)
if(isnewplayer(M))
lobby_players++
continue
else if(M.stat != DEAD && M.mind && !isbrain(M))
living_players++
if(M.mind.special_role)
living_players_antagonist++
if(M.client)
living_players_connected++
else if((M.stat == DEAD )||(isobserver(M)))
observers++
if(M.client)
observers_connected++
else
other_players++
dat += "<BR><b><font color='blue' size='3'>Players:|[connected_players - lobby_players] ingame|[connected_players] connected|[lobby_players] lobby|</font></b>"
dat += "<BR><b><font color='green'>Living Players:|[living_players_connected] active|[living_players - living_players_connected] disconnected|[living_players_antagonist] antagonists|</font></b>"
dat += "<BR><b><font color='red'>Dead/Observing players:|[observers_connected] active|[observers - observers_connected] disconnected|</font></b>"
if(other_players)
dat += "<BR><span class='userdanger'>[other_players] players in invalid state or the statistics code is bugged!</span>"
dat += "<BR>"
if(ticker.mode.syndicates.len)
dat += "<br><table cellspacing=5><tr><td><B>Syndicates</B></td><td></td></tr>"
for(var/datum/mind/N in ticker.mode.syndicates)

View File

@@ -35,8 +35,8 @@
if(!timestamp)
timestamp = SQLtime()
if(!server)
if (config && config.server_name)
server = config.server_name
if (config && config.server_sql_name)
server = config.server_sql_name
server = sanitizeSQL(server)
if(isnull(secret))
switch(alert("Hide note from being viewed by players?", "Secret note?","Yes","No","Cancel"))
@@ -332,7 +332,7 @@ proc/get_message_output(type, target_ckey)
return
if("watchlist entry")
message_admins("<font color='red'><B>Notice: </B></font><font color='blue'>[key_name_admin(target_ckey)] is on the watchlist and has just connected - Reason: [text]</font>")
// send2irc_adminless_only("Watchlist", "[key_name(target_ckey)] is on the watchlist and has just connected - Reason: [text]")
send2irc_adminless_only("Watchlist", "[key_name(target_ckey)] is on the watchlist and has just connected - Reason: [text]")
if("memo")
output += "<span class='memo'>Memo by <span class='prefix'>[admin_ckey]</span> on [timestamp]"
if(editor_ckey)
@@ -352,8 +352,8 @@ proc/get_message_output(type, target_ckey)
var/notetext
notesfile >> notetext
var/server
if(config && config.server_name)
server = config.server_name
if(config && config.server_sql_name)
server = config.server_sql_name
var/regex/note = new("^(\\d{2}-\\w{3}-\\d{4}) \\| (.+) ~(\\w+)$", "i")
note.Find(notetext)
var/timestamp = note.group[1]

View File

@@ -1,4 +1,4 @@
/proc/keywords_lookup(msg)
/proc/keywords_lookup(msg,irc)
//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE!
var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","alien","as", "i")
@@ -10,9 +10,11 @@
var/list/surnames = list()
var/list/forenames = list()
var/list/ckeys = list()
var/founds = ""
for(var/mob/M in mob_list)
var/list/indexing = list(M.real_name, M.name)
if(M.mind) indexing += M.mind.name
if(M.mind)
indexing += M.mind.name
for(var/string in indexing)
var/list/L = splittext(string, " ")
@@ -52,9 +54,19 @@
mobs_found += found
if(!ai_found && isAI(found))
ai_found = 1
msg += "[original_word]<font size='1' color='black'>(<A HREF='?_src_=holder;adminmoreinfo=\ref[found]'>?</A>|<A HREF='?_src_=holder;adminplayerobservefollow=\ref[found]'>F</A>)</font> "
var/is_antag = 0
if(found.mind && found.mind.special_role)
is_antag = 1
founds += "Name: [found.name]([found.real_name]) Ckey: [found.ckey] [is_antag ? "(Antag)" : null] "
msg += "[original_word]<font size='1' color='[is_antag ? "red" : "black"]'>(<A HREF='?_src_=holder;adminmoreinfo=\ref[found]'>?</A>|<A HREF='?_src_=holder;adminplayerobservefollow=\ref[found]'>F</A>)</font> "
continue
msg += "[original_word] "
if(irc)
if(founds == "")
return "Search Failed"
else
return founds
return msg
@@ -78,7 +90,20 @@
return
if(src.handle_spam_prevention(msg,MUTE_ADMINHELP))
return
var/ref_mob = "\ref[mob]"
//clean the input msg
if(!msg)
return
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
if(!msg) return
var/original_msg = msg
msg = keywords_lookup(msg)
if(!mob)
return //this doesn't happen
var/ref_client = "\ref[src]"
for(var/datum/adminticket/T in admintickets)
if(T.permckey == src.ckey && T.resolved == "No")
@@ -87,7 +112,7 @@
if(T.admin == "N/A")
usr << "<b>Due to the fact your Adminhelp had no assigned admin, admins have been pinged.</b>"
message_admins("[src.ckey] has bumped their adminhelp #[T.ID], still no assigned admin!")
msg = "<span class='adminnotice'><b><font color=red>HELP: </font><A HREF='?priv_msg=[ckey];ahelp_reply=1'>[key_name(src)]</A> [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)] (<A HREF='?_src_=holder;rejectadminhelp=[ref_client]'>REJT</A>) (<A HREF='?_src_=holder;icissue=[ref_client]'>IC</A>) (<A HREF='?_src_=holder;resolve=[T.ID]'>R</a>):</b> [msg]</span>"
msg = "<span class='adminnotice'><b><font color=red>HELP: </font><A HREF='?priv_msg=[ckey];ahelp_reply=1'>[key_name(src)]</A> [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)] (<A HREF='?_src_=holder;rejectadminhelp=[ref_client]'>REJT</A>) (<A HREF='?_src_=holder;icissue=[ref_client]'>IC</A>) (<A HREF='?_src_=ticket;resolve=[T.ID]'>R</a>):</b> [msg]</span>"
for(var/client/X in admins)
if(X.prefs.toggles & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
@@ -104,27 +129,10 @@
src.verbs -= /client/verb/adminhelp
adminhelptimerid = addtimer(CALLBACK(src, .proc/giveadminhelpverb), 1200, TIMER_STOPPABLE)
//clean the input msg
if(!msg) return
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
if(!msg) return
var/original_msg = msg
msg = keywords_lookup(msg)
if(!mob) return //this doesn't happen
for(var/datum/adminticket/T in admintickets)
msg = "<span class='adminnotice'><b><font color=red>HELP: </font><A HREF='?priv_msg=[ckey];ahelp_reply=1'>[key_name(src)]</A> [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)] (<A HREF='?_src_=holder;rejectadminhelp=[ref_client]'>REJT</A>) (<A HREF='?_src_=holder;icissue=[ref_client]'>IC</A>) (<A HREF='?_src_=ticket;resolve=[T.ID]'>R</a>):</b> [msg]</span>"
createticket(src, msg, src.ckey, mob)
var/datum/adminticket/ticket
for(var/datum/adminticket/T in admintickets)
if(T.permckey == src.ckey)
ticket = T
msg = "<span class='adminnotice'><b><font color=red>ADMINHELP: </font><A HREF='?priv_msg=[ckey];ahelp_reply=1'>[key_name(src)]</A> (<A HREF='?_src_=holder;adminmoreinfo=[ref_mob]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=[ref_mob]'>PP</A>) (<A HREF='?_src_=vars;Vars=[ref_mob]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=[ref_mob]'>SM</A>) (<A HREF='?_src_=holder;traitor=[ref_mob]'>TP</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=[ref_mob]'>FLW</A>) (<a href='?src=\ref[ticket];resolve=\ref[ticket]'>R</a>):</b> [msg]</span>"
//send this msg to all admins
for(var/client/X in admins)
@@ -138,88 +146,72 @@
src << "<span class='adminnotice'>PM to-<b>Admins</b>: [original_msg]</span>"
//send it to irc if nobody is on and tell us how many were on
var/admin_number_present = send2irc_admin_notice_handler("adminhelp", ckey, original_msg)
log_admin("ADMINHELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins who have +BAN.")
var/admin_number_present = send2admindiscord(ckey,original_msg)
log_admin("HELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins who have +BAN.")
if(admin_number_present <= 0)
src << "<span class='notice'>No active admins are online, your adminhelp was sent to the admin irc.</span>"
feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/proc/calculate_admins(type, requiredflags = R_BAN)
var/admin_number_total = 0 //Total number of admins
var/admin_number_afk = 0 //Holds the number of admins who are afk
var/admin_number_ignored = 0 //Holds the number of admins without +BAN (so admins who are not really admins)
var/admin_number_decrease = 0 //Holds the number of admins with are afk, ignored or both
/proc/get_admin_counts(requiredflags = R_BAN)
. = list("total" = list(), "noflags" = list(), "afk" = list(), "stealth" = list(), "present" = list())
for(var/client/X in admins)
admin_number_total++;
var/invalid = 0
.["total"] += X
if(requiredflags != 0 && !check_rights_for(X, requiredflags))
admin_number_ignored++
invalid = 1
if(X.is_afk())
admin_number_afk++
invalid = 1
if(X.holder.fakekey)
admin_number_ignored++
invalid = 1
if(invalid)
admin_number_decrease++
switch(type)
if("ignored")
return admin_number_ignored
if("total")
return admin_number_total
if("away")
return admin_number_afk
if("present")
return admin_number_total - admin_number_decrease
return 0
.["noflags"] += X
else if(X.is_afk())
.["afk"] += X
else if(X.holder.fakekey)
.["stealth"] += X
else
.["present"] += X
/proc/send2irc_adminless_only(source, msg, requiredflags = R_BAN)
var/list/adm = get_admin_counts(requiredflags)
var/list/activemins = adm["present"]
. = activemins.len
if(. <= 0)
var/final = ""
var/list/afkmins = adm["afk"]
var/list/stealthmins = adm["stealth"]
var/list/powerlessmins = adm["noflags"]
var/list/allmins = adm["total"]
if(!afkmins.len && !stealthmins.len && !powerlessmins.len)
final = "[msg] - No admins online"
else
final = "[msg] - All admins stealthed\[[english_list(stealthmins)]\], AFK\[[english_list(afkmins)]\], or lacks +BAN\[[english_list(powerlessmins)]\]! Total: [allmins.len] "
send2irc(source,final)
send2admindiscord(source,final)
/proc/send2irc_admin_notice_handler(type, source, msg)
var/afk_admins = calculate_admins("away")
var/total_admins = calculate_admins("total")
var/ignored_admins = calculate_admins("ignored")
var/admin_number_present = calculate_admins("present") //Number of admins who are neither afk nor invalid
var/irc_message_afk = "[msg] - All admins AFK ([afk_admins]/[total_admins]) or skipped ([ignored_admins]/[total_admins])"
var/irc_message_normal = "[msg] - heard by [admin_number_present] non-AFK admins who have +BAN."
var/irc_message_adminless = "[msg] - No admins online"
switch(type)
if("adminhelp")
if(config.announce_adminhelps)
send2irc(source, irc_message_normal)
else
if(admin_number_present <= 0)
if(!afk_admins && !ignored_admins)
send2admindiscord(source, irc_message_adminless)
else if(afk_admins >= 1)
send2admindiscord(source, irc_message_afk)
else
send2admindiscord(source, irc_message_normal)
if("watchlist")
if(config.announce_watchlist)
send2irc(source, irc_message_normal)
else
if(admin_number_present <= 0)
if(!afk_admins && !ignored_admins)
send2admindiscord(source, irc_message_adminless)
else if(afk_admins >= 1)
send2admindiscord(source, irc_message_afk)
else
send2admindiscord(source, irc_message_normal)
if("new_player")
if(config.irc_first_connection_alert)
send2irc(source, irc_message_normal)
else
if(admin_number_present <= 0)
if(!afk_admins && !ignored_admins)
send2admindiscord(source, irc_message_adminless)
else if(afk_admins >= 1)
send2admindiscord(source, irc_message_afk)
else
send2admindiscord(source, irc_message_normal)
return admin_number_present
/proc/send2irc(msg,msg2)
if(config.useircbot)
shell("python nudge.py [msg] \"[msg2]\"")
return
shell("python nudge.py [msg] [msg2]")
return
/proc/send2otherserver(source,msg,type = "Ahelp")
if(global.cross_allowed)
var/list/message = list()
message["message_sender"] = source
message["message"] = msg
message["source"] = "([config.cross_name])"
message["key"] = global.comms_key
message["crossmessage"] = type
world.Export("[global.cross_address]?[list2params(message)]")
/proc/ircadminwho()
var/list/message = list("Admins: ")
var/list/admin_keys = list()
for(var/adm in admins)
var/client/C = adm
admin_keys += "[C][C.holder.fakekey ? "(Stealth)" : ""][C.is_afk() ? "(AFK)" : ""]"
for(var/admin in admin_keys)
if(LAZYLEN(admin_keys) > 1)
message += ", [admin]"
else
message += "[admin]"
return jointext(message, "")

View File

@@ -1,3 +1,5 @@
#define IRCREPLYCOUNT 2
//allows right clicking mobs to send an admin PM to their client, forwards the selected mob's client to cmd_admin_pm
/client/proc/cmd_admin_pm_context(mob/M in mob_list)
set category = null
@@ -5,7 +7,8 @@
if(!holder)
src << "<font color='red'>Error: Admin-PM-Context: Only administrators may use this command.</font>"
return
if( !ismob(M) || !M.client ) return
if( !ismob(M) || !M.client )
return
cmd_admin_pm(M.client,null)
feedback_add_details("admin_verb","APMM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -19,16 +22,15 @@
var/list/client/targets[0]
for(var/client/T)
if(T.mob)
if(istype(T.mob, /mob/new_player))
if(isnewplayer(T.mob))
targets["(New Player) - [T]"] = T
else if(istype(T.mob, /mob/dead/observer))
else if(isobserver(T.mob))
targets["[T.mob.name](Ghost) - [T]"] = T
else
targets["[T.mob.real_name](as [T.mob.name]) - [T]"] = T
else
targets["(No Mob) - [T]"] = T
var/list/sorted = sortList(targets)
var/target = input(src,"To whom shall we send a message?","Admin PM",null) in sorted|null
var/target = input(src,"To whom shall we send a message?","Admin PM",null) as null|anything in sortList(targets)
cmd_admin_pm(targets[target],null)
feedback_add_details("admin_verb","APM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -44,7 +46,8 @@
else if(istype(whom,/client))
C = whom
if(!C)
if(holder) src << "<font color='red'>Error: Admin-PM: Client not found.</font>"
if(holder)
src << "<font color='red'>Error: Admin-PM: Client not found.</font>"
return
var/datum/adminticket/ticket
@@ -205,4 +208,51 @@
//we don't use message_admins here because the sender/receiver might get it too
for(var/client/X in admins)
if(X.key!=key && X.key!=C.key) //check client/X is an admin and isn't the sender or recipient
X << "<B><font color='blue'>PM: [key_name(src, X, 0)]-&gt;[key_name(C, X, 0)]:</B> \blue [keywordparsedmsg]</font>" //inform X
X << "<B><font color='blue'>PM: [key_name(src, X, 0)]-&gt;[key_name(C, X, 0)]:</B> \blue [keywordparsedmsg]</font>" //inform X
/proc/IrcPm(target,msg,sender)
var/client/C = directory[target]
var/static/stealthkey
var/adminname = config.showircname ? "[sender](IRC)" : "Administrator"
if(!C)
return "No client"
if(!stealthkey)
stealthkey = GenIrcStealthKey()
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
if(!msg)
return "No message"
message_admins("IRC message from [sender] to [key_name_admin(C)] : [msg]")
log_admin("IRC PM: [sender] -> [key_name(C)] : [msg]")
msg = emoji_parse(msg)
C << "<font color='red' size='4'><b>-- Administrator private message --</b></font>"
C << "<font color='red'>Admin PM from-<b><a href='?priv_msg=[stealthkey]'>[adminname]</A></b>: [msg]</font>"
C << "<font color='red'><i>Click on the administrator's name to reply.</i></font>"
window_flash(C)
//always play non-admin recipients the adminhelp sound
C << 'sound/effects/adminhelp.ogg'
C.ircreplyamount = IRCREPLYCOUNT
return "Message Successful"
/proc/GenIrcStealthKey()
var/num = (rand(0,1000))
var/i = 0
while(i == 0)
i = 1
for(var/P in stealthminID)
if(num == stealthminID[P])
num++
i = 0
var/stealth = "@[num2text(num)]"
stealthminID["IRCKEY"] = stealth
return stealth
#undef IRCREPLYCOUNT

View File

@@ -118,16 +118,19 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(isnull(argnum))
return
var/list/lst = list()
. = list()
var/list/named_args = list()
while(argnum--)
var/named_arg = input("Leave blank for positional argument. Positional arguments will be considered as if they were added first.", "Named argument") as text|null
var/value = vv_get_value(restricted_classes = list(VV_RESTORE_DEFAULT))
if (!value["class"])
return
lst += value["value"]
return lst
if(named_arg)
named_args[named_arg] = value["value"]
else
. += value["value"]
if(LAZYLEN(named_args))
. += named_args
/client/proc/get_callproc_returnval(returnval,procname)
. = ""

View File

@@ -35,11 +35,11 @@
var/list/atmos_overlay_types //gas IDs of current active gas overlays
/turf/open/New()
..()
/turf/open/Initialize()
if(!blocks_air)
air = new
air.copy_from_turf(src)
..()
/turf/open/Destroy()
if(active_hotspot)
@@ -113,11 +113,12 @@
/turf/open/proc/tile_graphic()
. = new /list
var/list/gases = air.gases
for(var/id in gases)
var/gas = gases[id]
if(gas[GAS_META][META_GAS_OVERLAY] && gas[MOLES] > gas[GAS_META][META_GAS_MOLES_VISIBLE])
. += gas[GAS_META][META_GAS_OVERLAY]
if(air)
var/list/gases = air.gases
for(var/id in gases)
var/gas = gases[id]
if(gas[GAS_META][META_GAS_OVERLAY] && gas[MOLES] > gas[GAS_META][META_GAS_MOLES_VISIBLE])
. += gas[GAS_META][META_GAS_OVERLAY]
/////////////////////////////SIMULATION///////////////////////////////////

View File

@@ -99,26 +99,28 @@
flags_cover = MASKCOVERSEYES
resistance_flags = FLAMMABLE
actions_types = list(/datum/action/item_action/adjust)
/obj/item/clothing/mask/gas/mime/attack_self(mob/user)
cycle_mask(user)
/obj/item/clothing/mask/gas/mime/ui_action_click(mob/user)
if(!istype(user) || user.incapacitated())
return
/obj/item/clothing/mask/gas/mime/proc/cycle_mask(mob/user)
switch(icon_state)
if("mime")
icon_state = "sadmime"
if("sadmime")
icon_state = "scaredmime"
if("scaredmime")
icon_state = "sexymime"
if("sexymime")
icon_state = "mime"
user.update_inv_wear_mask()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
user << "<span class='notice'>You adjust your mask to portray a different emotion.</span>"
return 1
var/list/options = list()
options["Blanc"] = "mime"
options["Triste"] = "sadmime"
options["Effrayé"] = "scaredmime"
options["Excité"] ="sexymime"
var/choice = input(user,"To what form do you wish to Morph this mask?","Morph Mask") in options
if(src && choice && !user.incapacitated() && in_range(user,src))
icon_state = options[choice]
user.update_inv_wear_mask()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
user << "<span class='notice'>Your Mime Mask has now morphed into [choice]!</span>"
return 1
/obj/item/clothing/mask/gas/monkeymask
name = "monkey mask"
@@ -170,6 +172,7 @@
resistance_flags = FLAMMABLE
obj_integrity = 100
max_integrity = 100
actions_types = list(/datum/action/item_action/adjust)
dog_fashion = null
@@ -186,7 +189,6 @@ obj/item/clothing/mask/gas/tiki_mask/ui_action_click(mob/user)
if(src && choice && !M.stat && in_range(M,src))
icon_state = options[choice]
item_state = options[choice]
user.update_inv_wear_mask()
for(var/X in actions)
var/datum/action/A = X

View File

@@ -268,6 +268,11 @@
/obj/item/clothing/suit/armor/reactive/tesla
name = "reactive tesla armor"
desc = "An experimental suit of armor with sensitive detectors hooked up to a huge capacitor grid, with emitters strutting out of it. Zap."
siemens_coefficient = -1
var/tesla_power = 25000
var/tesla_range = 20
var/tesla_boom = FALSE
var/tesla_stun = FALSE
/obj/item/clothing/suit/armor/reactive/tesla/hit_reaction(mob/living/carbon/human/owner, attack_text)
if(!active)
@@ -277,15 +282,10 @@
var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread
sparks.set_up(1, 1, src)
sparks.start()
owner.visible_message("<span class='danger'>The tesla capacitors on [owner]'s reactive telsa armor are still recharging! The armor merely emits some sparks.</spawn>")
owner.visible_message("<span class='danger'>The tesla capacitors on [owner]'s reactive tesla armor are still recharging! The armor merely emits some sparks.</spawn>")
return
owner.visible_message("<span class='danger'>The [src] blocks the [attack_text], sending out arcs of lightning!</span>")
for(var/mob/living/M in view(6, owner))
if(M == owner)
continue
owner.Beam(M,icon_state="lightning[rand(1, 12)]",time=5)
M.adjustFireLoss(25)
playsound(M, 'sound/machines/defib_zap.ogg', 50, 1, -1)
tesla_zap(owner,tesla_range,tesla_power,tesla_boom, tesla_stun)
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
return 1

View File

@@ -3,9 +3,12 @@
typepath = /datum/round_event/ghost_role/sentience
weight = 10
/datum/round_event/ghost_role/sentience
minimum_required = 1
role_name = "random animal"
var/animals = 1
var/one = "one"
/datum/round_event/ghost_role/sentience/start()
var/sentience_report = "<font size=3><b>[command_name()] Medium-Priority Update</b></font>"
@@ -14,7 +17,7 @@
var/pets = pick("animals/bots", "bots/animals", "pets", "simple animals", "lesser lifeforms", "\[REDACTED\]")
var/strength = pick("human", "moderate", "lizard", "security", "command", "clown", "low", "very low", "\[REDACTED\]")
sentience_report += "<br><br>Based on [data], we believe that one of the station's [pets] has developed [strength] level intelligence, and the ability to communicate."
sentience_report += "<br><br>Based on [data], we believe that [one] of the station's [pets] has developed [strength] level intelligence, and the ability to communicate."
print_command_report(sentience_report, "Classified [command_name()] Update")
priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg')
@@ -36,25 +39,40 @@
if(!potential.len)
return WAITING_FOR_SOMETHING
var/mob/living/simple_animal/SA = pick(potential)
if(!candidates.len)
return NOT_ENOUGH_PLAYERS
var/mob/dead/observer/SG = pick(candidates)
SA.key = SG.key
SA.languages_spoken |= HUMAN
SA.languages_understood |= HUMAN
SA.sentience_act()
var/spawned_animals = 0
while(spawned_animals < animals && candidates.len && potential.len)
var/mob/living/simple_animal/SA = pick_n_take(potential)
var/mob/dead/observer/SG = pick_n_take(candidates)
SA.maxHealth = max(SA.maxHealth, 200)
SA.health = SA.maxHealth
SA.del_on_death = FALSE
spawned_animals++
spawned_mobs += SA
SA.key = SG.key
SA.languages_spoken |= HUMAN
SA.languages_understood |= HUMAN
SA.sentience_act()
SA << "<span class='userdanger'>Hello world!</span>"
SA << "<span class='warning'>Due to freak radiation and/or chemicals \
and/or lucky chance, you have gained human level intelligence \
and the ability to speak and understand human language!</span>"
SA.maxHealth = max(SA.maxHealth, 200)
SA.health = SA.maxHealth
SA.del_on_death = FALSE
spawned_mobs += SA
SA << "<span class='userdanger'>Hello world!</span>"
SA << "<span class='warning'>Due to freak radiation and/or chemicals \
and/or lucky chance, you have gained human level intelligence \
and the ability to speak and understand human language!</span>"
return SUCCESSFUL_SPAWN
/datum/round_event_control/sentience/all
name = "Station-wide Human-level Intelligence"
typepath = /datum/round_event/ghost_role/sentience/all
weight = 0
/datum/round_event/ghost_role/sentience/all
one = "all"
animals = INFINITY // as many as there are ghosts and animals
// cockroach pride, station wide

View File

@@ -124,6 +124,12 @@
list_reagents = list("sodiumchloride" = 20)
possible_states = list()
/obj/item/weapon/reagent_containers/food/condiment/saltshaker/on_reagent_change()
if(reagents.reagent_list.len == 0)
icon_state = "emptyshaker"
else
icon_state = "saltshakersmall"
/obj/item/weapon/reagent_containers/food/condiment/saltshaker/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] begins to swap forms with the salt shaker! It looks like [user.p_theyre()] trying to commit suicide!</span>")
var/newname = "[name]"
@@ -156,6 +162,12 @@
list_reagents = list("blackpepper" = 20)
possible_states = list()
/obj/item/weapon/reagent_containers/food/condiment/peppermill/on_reagent_change()
if(reagents.reagent_list.len == 0)
icon_state = "emptyshaker"
else
icon_state = "peppermillsmall"
/obj/item/weapon/reagent_containers/food/condiment/milk
name = "space milk"
desc = "It's milk. White and nutritious goodness!"

View File

@@ -18,6 +18,15 @@ insert ascii eagle on american flag background here
container_type = OPENCONTAINER
var/obj/item/frying = null //What's being fried RIGHT NOW?
var/cook_time = 0
var/static/list/blacklisted_items = typecacheof(list(
/obj/item/weapon/screwdriver,
/obj/item/weapon/crowbar,
/obj/item/weapon/wrench,
/obj/item/weapon/wirecutters,
/obj/item/device/multitool,
/obj/item/weapon/weldingtool,
/obj/item/weapon/reagent_containers/glass,
/obj/item/weapon/storage/part_replacer))
/obj/item/weapon/circuitboard/machine/deep_fryer
name = "circuit board (Deep Fryer)"
@@ -46,8 +55,16 @@ insert ascii eagle on american flag background here
if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/deepfryholder))
user << "<span class='userdanger'>Your cooking skills are not up to the legendary Doublefry technique.</span>"
return
if(default_unfasten_wrench(user, I))
return
else if(exchange_parts(user, I))
return
else if(default_deconstruction_screwdriver(user, "fryer_off", "fryer_off" ,I)) //where's the open maint panel icon?!
return
else
if(user.drop_item() && !frying)
if(is_type_in_typecache(I, blacklisted_items))
. = ..()
else if(user.drop_item() && !frying)
user << "<span class='notice'>You put [I] into [src].</span>"
frying = I
frying.forceMove(src)
@@ -78,6 +95,7 @@ insert ascii eagle on american flag background here
S.overlays = frying.overlays
S.icon_state = frying.icon_state
S.desc = frying.desc
S.w_class = frying.w_class
reagents.trans_to(S, 2*(cook_time/15))
switch(cook_time)
if(0 to 15)

View File

@@ -110,7 +110,7 @@
if(V == "air")
var/turf/open/O1 = B
var/turf/open/O2 = T
O1.air.copy_from(O2.air)
O1.air.copy_from(O2.return_air())
continue
B.vars[V] = T.vars[V]
toupdate += B

View File

@@ -64,25 +64,25 @@
..()
/obj/machinery/computer/holodeck/Initialize(mapload)
..()
if(!mapload && ticker.current_state < GAME_STATE_PLAYING)
return
program_cache = list()
emag_programs = list()
for(var/typekey in subtypesof(program_type))
var/area/holodeck/A = locate(typekey)
if(!A || A == offline_program) continue
if(A.contents.len == 0) continue // not loaded
if(A.restricted)
emag_programs += A
else
program_cache += A
if(typekey == init_program)
load_program(A,force=1)
if(random_program && program_cache.len && init_program == null)
load_program(pick(program_cache),force=1)
else if(!program)
load_program(offline_program)
. = mapload //late-initialize, area_copy need turfs to have air
if(!mapload)
..()
program_cache = list()
emag_programs = list()
for(var/typekey in subtypesof(program_type))
var/area/holodeck/A = locate(typekey)
if(!A || A == offline_program) continue
if(A.contents.len == 0) continue // not loaded
if(A.restricted)
emag_programs += A
else
program_cache += A
if(typekey == init_program)
load_program(A,force=1)
if(random_program && program_cache.len && init_program == null)
load_program(pick(program_cache),force=1)
else if(!program)
load_program(offline_program)
/obj/machinery/computer/holodeck/power_change()
..()

View File

@@ -42,7 +42,7 @@
name = "asteroid"
icon_state = "asteroid0"
/turf/open/floor/holofloor/asteroid/New()
/turf/open/floor/holofloor/asteroid/Initialize()
icon_state = "asteroid[pick(0,1,2,3,4,5,6,7,8,9,10,11,12)]"
..()
@@ -50,7 +50,7 @@
name = "basalt"
icon_state = "basalt0"
/turf/open/floor/holofloor/basalt/New()
/turf/open/floor/holofloor/basalt/Initialize()
icon_state = "basalt[pick(0,1,2,3,4,5,6,7,8,9,10,11,12)]"
..()
@@ -59,7 +59,7 @@
icon = 'icons/turf/space.dmi'
icon_state = "0"
/turf/open/floor/holofloor/space/New()
/turf/open/floor/holofloor/space/Initialize()
icon_state = SPACE_ICON_STATE // so realistic
..()
@@ -68,11 +68,11 @@
icon = 'icons/turf/space.dmi'
icon_state = "speedspace_ns_1"
/turf/open/floor/holofloor/hyperspace/New()
/turf/open/floor/holofloor/hyperspace/Initialize()
icon_state = "speedspace_ns_[(x + 5*y + (y%2+1)*7)%15+1]"
..()
/turf/open/floor/holofloor/hyperspace/ns/New()
/turf/open/floor/holofloor/hyperspace/ns/Initialize()
..()
icon_state = "speedspace_ns_[(x + 5*y + (y%2+1)*7)%15+1]"
@@ -86,7 +86,7 @@
smooth = SMOOTH_TRUE
canSmoothWith = null
/turf/open/floor/holofloor/carpet/New()
/turf/open/floor/holofloor/carpet/Initialize()
..()
addtimer(CALLBACK(src, .proc/update_icon), 1)

View File

@@ -1,40 +1,22 @@
#define SOAPSTONE_PREFIX_FILE "strings/soapstone_prefixes.txt"
#define SOAPSTONE_SUFFIX_FILE "soapstone_suffixes.json"
//Vocabulary lists; soapstones use a prefix and a suffix. Optionally, they can have a prefix and suffix, then a conjunction that links another set.
var/global/list/soapstone_prefixes = list() //Read from "strings/soapstone_prefixes.txt"; if you're adding your own, put **** where the subject should be!
var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffixes.json"
/obj/item/soapstone
name = "chisel"
desc = "Leave \"informative\" messages for the crew, including the crew of future shifts!\n\
(Not suitable for engraving on shuttles, off station or on cats. Side effects may include beatings, bannings and orbital bombardment.)"
desc = "Leave informative messages for the crew, including the crew of future shifts!\nEven if out of uses, it can still be used to remove messages.\n(Not suitable for engraving on shuttles, off station or on cats. Side effects may include beatings, bannings and orbital bombardment.)"
icon = 'icons/obj/items.dmi'
icon_state = "soapstone"
throw_speed = 3
throw_range = 5
w_class = WEIGHT_CLASS_TINY
var/tool_speed = 50
var/remaining_uses = 3
var/non_dull_name
var/w_engrave = "engrave"
var/w_engraving = "engraving"
var/w_chipping = "chipping"
var/w_dull = "dull"
/obj/item/soapstone/New()
. = ..()
if(!soapstone_prefixes.len)
soapstone_prefixes = file2list(SOAPSTONE_PREFIX_FILE, "\n")
if(!soapstone_suffixes.len)
soapstone_suffixes = list(\
"Characters" = strings(SOAPSTONE_SUFFIX_FILE, "Characters"), \
"Careers" = strings(SOAPSTONE_SUFFIX_FILE, "Careers"), \
"Antagonists" = strings(SOAPSTONE_SUFFIX_FILE, "Antagonists"), \
"Objects" = strings(SOAPSTONE_SUFFIX_FILE, "Objects"), \
"Techniques" = strings(SOAPSTONE_SUFFIX_FILE, "Techniques"), \
"Actions" = strings(SOAPSTONE_SUFFIX_FILE, "Actions"), \
"Geography" = strings(SOAPSTONE_SUFFIX_FILE, "Geography"), \
"Orientation" = strings(SOAPSTONE_SUFFIX_FILE, "Orientation"), \
"Body parts" = strings(SOAPSTONE_SUFFIX_FILE, "Body parts"), \
"Concepts" = strings(SOAPSTONE_SUFFIX_FILE, "Concepts"), \
"Musings" = strings(SOAPSTONE_SUFFIX_FILE, "Musings"), \
)
random_name()
check_name() // could start empty
@@ -43,6 +25,9 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
non_dull_name = name
if(name == "chalk" || name == "magic marker")
desc = replacetext(desc, "engraving", "scribbling")
w_engrave = "scribble"
w_engraving = "scribbling"
w_chipping = "sketching"
if(name == "chalk")
w_dull = "used"
if(name == "magic marker")
@@ -50,6 +35,9 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
if(name == "soapstone" || name == "chisel")
desc = replacetext(desc, "scribbling", "engraving")
w_engrave = initial(w_engrave)
w_engraving = initial(w_engraving)
w_chipping = initial(w_chipping)
w_dull = "dull"
/obj/item/soapstone/examine(mob/user)
@@ -60,48 +48,59 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
user << "It looks like it can be used an unlimited number of times."
/obj/item/soapstone/afterattack(atom/target, mob/user, proximity)
if(!remaining_uses)
user << "<span class='warning'>[src] is [w_dull] and can't be used anymore!</span>"
return
var/turf/T = get_turf(target)
if(!proximity)
return
var/obj/structure/chisel_message/msg = locate() in T
if(msg)
if(msg.creator_key != user.ckey)
user << "<span class='warning'>There's already a message there!</span>"
return
else
if(alert(user, "Erase this message?", name, "Yes", "No") == "Yes")
user.visible_message("<span class='notice'>[user] erases [msg].</span>", "<span class='notice'>You permanently erase [msg].</span>")
playsound(T, 'sound/items/gavel.ogg', 50, 1)
refund_use()
msg.persists = 0
qdel(msg)
return
return
var/obj/structure/chisel_message/already_message = locate(/obj/structure/chisel_message) in T
var/our_message = FALSE
if(already_message)
our_message = already_message.creator_key == user.ckey
if(!remaining_uses && !already_message)
// The dull chisel is dull.
user << "<span class='warning'>[src] is [w_dull].</span>"
return
if(!good_chisel_message_location(T))
user << "<span class='warning'>You can't write there!</span>"
user << "<span class='warning'>It's not appropriate to [w_engrave] on [T].</span>"
return
var/prefix = input(user, "Choose a prefix for your message.", name) as null|anything in soapstone_prefixes
if(!prefix)
if(already_message)
user.visible_message("<span class='notice'>[user] starts erasing [already_message].</span>", "<span class='notice'>You start erasing [already_message].</span>", "<span class='italics'>You hear a [w_chipping] sound.</span>")
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
// Removing our own messages refunds a charge
if(do_after(user, tool_speed, target=target))
user.visible_message("<span class='notice'>[user] has erased [already_message].</span>", "<span class='notice'>You erased [already_message].</span>")
already_message.persists = FALSE
qdel(already_message)
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
if(our_message)
refund_use()
return
var/suffix_category_string = input(user, "Choose a suffix category.", "[prefix]...") as null|anything in soapstone_suffixes
var/list/suffix_category = soapstone_suffixes[suffix_category_string]
if(!suffix_category || !suffix_category.len)
var/message = stripped_input(user, "What would you like to [w_engrave]?", "[name] Message")
if(!message)
user << "You decide not to [w_engrave] anything."
return
var/suffix = input(user, "Choose a suffix.", "[prefix]...") as null|anything in suffix_category
if(!suffix)
if(!target.Adjacent(user) && locate(/obj/structure/chisel_message) in T)
user << "You decide not to [w_engrave] anything."
return
var/processed_message = replacetext(prefix, "****", suffix)
if(!user.Adjacent(T) || !good_chisel_message_location(T) || locate(/obj/structure/chisel_message) in T)
return
user.visible_message("<span class='notice'>[user] writes a message onto [T]!</span>", "<span class='notice'>You write a message onto [T].</span>")
playsound(T, 'sound/items/gavel.ogg', 50, 1)
var/obj/structure/chisel_message/M = new(T)
M.register(user, processed_message)
remove_use()
return 1
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
user.visible_message("<span class='notice'>[user] starts [w_engraving] a message into [T].</span>", "You start [w_engraving] a message into [T].", "<span class='italics'>You hear a [w_chipping] sound.</span>")
if(can_use() && do_after(user, tool_speed, target=T) && can_use())
if(!locate(/obj/structure/chisel_message in T))
user << "You [w_engrave] a message into [T]."
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
var/obj/structure/chisel_message/M = new(T)
M.register(user, message)
remove_use()
/obj/item/soapstone/proc/can_use()
if(remaining_uses == -1 || remaining_uses >= 0)
@@ -172,34 +171,6 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
var/map
var/persists = TRUE
var/positive_ratings = 0
var/negative_ratings = 0
var/list/raters = list() //Ckeys who have rated this message
/obj/structure/chisel_message/attack_hand(mob/user)
if(user.ckey == creator_key)
user << "<span class='warning'>You can't rate your own messages!</span>"
return
if(raters[user.ckey])
user << "<span class='warning'>You've already rated this message!</span>"
return
switch(alert(user, "How would you like to rate this message?", "Message Rating", "Positive", "Negative", "Cancel"))
if("Positive")
for(var/client/C in clients)
if(C.ckey == creator_key)
C.mob << "<span class='notice'>One of your messages was rated as positive!</span>"
user << "<span class='noticealien'>You rated this message as positive.</span>"
positive_ratings++
raters[user.ckey] = "positive"
if("Negative")
for(var/client/C in clients)
if(C.ckey == creator_key)
C.mob << "<span class='danger'>One of your messages was rated as negative!</span>"
user << "<span class='danger'>You rated this message as negative.</span>"
negative_ratings++
raters[user.ckey] = "negative"
/obj/structure/chisel_message/New(newloc)
..()
SSpersistence.chisel_messages += src
@@ -219,6 +190,12 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
map = MAP_NAME
update_icon()
/obj/structure/chisel_message/update_icon()
..()
var/hash = md5(hidden_message)
var/newcolor = copytext(hash, 1, 7)
add_atom_colour("#[newcolor]", FIXED_COLOUR_PRIORITY)
/obj/structure/chisel_message/proc/pack()
var/list/data = list()
data["hidden_message"] = hidden_message
@@ -229,9 +206,6 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
var/turf/T = get_turf(src)
data["x"] = T.x
data["y"] = T.y
data["pos_ratings"] = positive_ratings
data["neg_ratings"] = positive_ratings
data["raters"] = raters
return data
/obj/structure/chisel_message/proc/unpack(list/data)
@@ -239,9 +213,6 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
creator_name = data["creator_name"]
creator_key = data["creator_key"]
realdate = data["realdate"]
positive_ratings = data["pos_ratings"]
negative_ratings = data["neg_ratings"]
raters = data["raters"]
var/x = data["x"]
var/y = data["y"]
@@ -251,10 +222,7 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
/obj/structure/chisel_message/examine(mob/user)
..()
user << "<span class='notice'>[hidden_message]</span>"
user << "Ratings: <span class='noticealien'>[positive_ratings]</span> <span class='danger'>[negative_ratings]</span>"
if(raters[user.ckey])
user << "<i>You rated this message as [raters[user.ckey]].</i>"
user << "<span class='warning'>[hidden_message]</span>"
/obj/structure/chisel_message/Destroy()
if(persists)

View File

@@ -91,20 +91,29 @@
return 1
return ..()
/mob/living/carbon/throw_impact(atom/hit_atom)
/mob/living/carbon/throw_impact(atom/hit_atom, throwingdatum)
. = ..()
var/hurt = TRUE
if(istype(throwingdatum, /datum/thrownthing))
var/datum/thrownthing/D = throwingdatum
if(iscyborg(D.thrower))
var/mob/living/silicon/robot/R = D.thrower
if(!R.emagged)
hurt = FALSE
if(hit_atom.density && isturf(hit_atom))
Weaken(1)
take_bodypart_damage(10)
if(hurt)
Weaken(1)
take_bodypart_damage(10)
if(iscarbon(hit_atom) && hit_atom != src)
var/mob/living/carbon/victim = hit_atom
if(victim.movement_type & FLYING)
return
victim.Weaken(1)
Weaken(1)
victim.take_bodypart_damage(10)
take_bodypart_damage(10)
visible_message("<span class='danger'>[src] crashes into [victim], knocking them both over!</span>", "<span class='userdanger'>You violently crash into [victim]!</span>")
if(hurt)
victim.take_bodypart_damage(10)
take_bodypart_damage(10)
victim.Weaken(1)
Weaken(1)
visible_message("<span class='danger'>[src] crashes into [victim], knocking them both over!</span>", "<span class='userdanger'>You violently crash into [victim]!</span>")
playsound(src,'sound/weapons/punch1.ogg',50,1)
@@ -231,23 +240,6 @@
/mob/living/carbon/is_muzzled()
return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle))
/mob/living/carbon/proc/spin(spintime, speed)
set waitfor = 0
var/D = dir
while(spintime >= speed)
sleep(speed)
switch(D)
if(NORTH)
D = EAST
if(SOUTH)
D = WEST
if(EAST)
D = SOUTH
if(WEST)
D = NORTH
setDir(D)
spintime -= speed
/mob/living/carbon/resist_buckle()
if(restrained())
changeNext_move(CLICK_CD_BREAKOUT)

View File

@@ -168,7 +168,7 @@
O.emp_act(severity)
..()
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0)
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
if(tesla_shock && tesla_ignore)
return FALSE
shock_damage *= siemens_coeff
@@ -190,11 +190,11 @@
jitteriness += 1000 //High numbers for violent convulsions
do_jitter_animation(jitteriness)
stuttering += 2
if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5))
if((!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) && stun)
Stun(2)
spawn(20)
jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less
if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5))
if((!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) && stun)
Stun(3)
Weaken(3)
if(override)

View File

@@ -436,7 +436,7 @@
//Added a safety check in case you want to shock a human mob directly through electrocute_act.
/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0)
/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
if(tesla_shock)
var/total_coeff = 1
if(gloves)
@@ -447,6 +447,8 @@
var/obj/item/clothing/suit/S = wear_suit
if(S.siemens_coefficient <= 0)
total_coeff -= 0.95
else if(S.siemens_coefficient == (-1))
total_coeff -= 1
siemens_coeff = total_coeff
if(tesla_ignore)
siemens_coeff = 0
@@ -461,7 +463,7 @@
heart_attack = 0
if(stat == CONSCIOUS)
src << "<span class='notice'>You feel your heart beating again!</span>"
. = ..(shock_damage,source,siemens_coeff,safety,override,tesla_shock, illusion)
. = ..(shock_damage,source,siemens_coeff,safety,override,tesla_shock, illusion, stun)
if(.)
electrocution_animation(40)
@@ -754,4 +756,4 @@
torn_items += leg_clothes
for(var/obj/item/I in torn_items)
I.take_damage(damage_amount, damage_type, damage_flag, 0)
I.take_damage(damage_amount, damage_type, damage_flag, 0)

View File

@@ -1015,7 +1015,7 @@
var/obj/item/organ/cyberimp/chest/thrusters/T = H.getorganslot("thrusters")
if(!istype(J) && istype(C))
J = C.jetpack
if(istype(J) && J.allow_thrust(0.01, H)) //Prevents stacking
if(istype(J) && J.full_speed && J.allow_thrust(0.01, H)) //Prevents stacking
. -= 2
else if(istype(T) && T.allow_thrust(0.01, H))
. -= 2

View File

@@ -150,4 +150,14 @@
return 1
/mob/living/carbon/monkey/can_use_guns(var/obj/item/weapon/gun/G)
return 1
return 1
/mob/living/carbon/monkey/angry
aggressive = TRUE
/mob/living/carbon/monkey/angry/Initialize()
..()
if(prob(10))
var/obj/item/clothing/head/helmet/justice/escape/helmet = new(src)
equip_to_slot_or_del(helmet,slot_head)
helmet.attack_self(src) // todo encapsulate toggle

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